Re: [Libguestfs] [PATCH 1/4] New API: internal_find_block

2016-09-19 Thread Pino Toscano
On Saturday, 17 September 2016 18:18:53 CEST Matteo Cafasso wrote:
> The internal_find_block command searches all entries referring to the
> given filesystem data block and returns a tsk_dirent structure
> for each of them.
> 
> For filesystems such as NTFS which do not delete the block mapping
> when removing files, it is possible to get multiple non-allocated
> entries for the same block.
> 
> The gathered list of tsk_dirent structs is serialised into XDR format
> and written to a file by the appliance.
> 
> Signed-off-by: Matteo Cafasso 
> ---

LGTM, just one small note below.

> +typedef struct {
> +  int found;

This can be a simple bool (including  to use it).

> +  uint64_t block;
> +} findblk_data;

Thanks,
-- 
Pino Toscano

signature.asc
Description: This is a digitally signed message part.
___
Libguestfs mailing list
Libguestfs@redhat.com
https://www.redhat.com/mailman/listinfo/libguestfs

[Libguestfs] [PATCH 1/4] New API: internal_find_block

2016-09-17 Thread Matteo Cafasso
The internal_find_block command searches all entries referring to the
given filesystem data block and returns a tsk_dirent structure
for each of them.

For filesystems such as NTFS which do not delete the block mapping
when removing files, it is possible to get multiple non-allocated
entries for the same block.

The gathered list of tsk_dirent structs is serialised into XDR format
and written to a file by the appliance.

Signed-off-by: Matteo Cafasso 
---
 daemon/tsk.c | 89 
 generator/actions.ml |  9 ++
 src/MAX_PROC_NR  |  2 +-
 3 files changed, 99 insertions(+), 1 deletion(-)

diff --git a/daemon/tsk.c b/daemon/tsk.c
index af803d7..6ac3952 100644
--- a/daemon/tsk.c
+++ b/daemon/tsk.c
@@ -42,9 +42,16 @@ enum tsk_dirent_flags {
   DIRENT_COMPRESSED = 0x04
 };

+typedef struct {
+  int found;
+  uint64_t block;
+} findblk_data;
+
 static int open_filesystem (const char *, TSK_IMG_INFO **, TSK_FS_INFO **);
 static TSK_WALK_RET_ENUM fswalk_callback (TSK_FS_FILE *, const char *, void *);
 static TSK_WALK_RET_ENUM findino_callback (TSK_FS_FILE *, const char *, void 
*);
+static TSK_WALK_RET_ENUM findblk_callback (TSK_FS_FILE *, const char *, void 
*);
+static TSK_WALK_RET_ENUM attrwalk_callback (TSK_FS_FILE *, TSK_OFF_T , 
TSK_DADDR_T , char *, size_t , TSK_FS_BLOCK_FLAG_ENUM , void *);
 static int send_dirent_info (TSK_FS_FILE *, const char *);
 static char file_type (TSK_FS_FILE *);
 static int file_flags (TSK_FS_FILE *fsfile);
@@ -109,6 +116,36 @@ do_internal_find_inode (const mountable_t *mountable, 
int64_t inode)
   return ret;
 }

+int
+do_internal_find_block (const mountable_t *mountable, int64_t block)
+{
+  int ret = -1;
+  TSK_FS_INFO *fs = NULL;
+  TSK_IMG_INFO *img = NULL;  /* Used internally by tsk_fs_dir_walk */
+  const int flags =
+TSK_FS_DIR_WALK_FLAG_ALLOC | TSK_FS_DIR_WALK_FLAG_UNALLOC |
+TSK_FS_DIR_WALK_FLAG_RECURSE | TSK_FS_DIR_WALK_FLAG_NOORPHAN;
+
+  ret = open_filesystem (mountable->device, , );
+  if (ret < 0)
+return ret;
+
+  reply (NULL, NULL);  /* Reply message. */
+
+  ret = tsk_fs_dir_walk (fs, fs->root_inum, flags,
+ findblk_callback, (void *) );
+  if (ret == 0)
+ret = send_file_end (0);  /* File transfer end. */
+  else
+send_file_end (1);  /* Cancel file transfer. */
+
+  fs->close (fs);
+  img->close (img);
+
+  return ret;
+}
+
+
 /* Inspect the device and initialises the img and fs structures.
  * Return 0 on success, -1 on error.
  */
@@ -172,6 +209,58 @@ findino_callback (TSK_FS_FILE *fsfile, const char *path, 
void *data)
   return (ret == 0) ? TSK_WALK_CONT : TSK_WALK_ERROR;
 }

+/* Find block, it gets called on every FS node.
+ *
+ * Return TSK_WALK_CONT on success, TSK_WALK_ERROR on error.
+ */
+static TSK_WALK_RET_ENUM
+findblk_callback (TSK_FS_FILE *fsfile, const char *path, void *data)
+{
+  findblk_data blkdata;
+  const TSK_FS_ATTR *fsattr = NULL;
+  int ret = 0, count = 0, index = 0;
+  uint64_t *block = (uint64_t *) data;
+  const int flags = TSK_FS_FILE_WALK_FLAG_AONLY | TSK_FS_FILE_WALK_FLAG_SLACK;
+
+  if (entry_is_dot (fsfile))
+return TSK_WALK_CONT;
+
+  blkdata.found = 0;
+  blkdata.block = *block;
+
+  /* Retrieve block list */
+  count = tsk_fs_file_attr_getsize (fsfile);
+
+  for (index = 0; index < count; index++) {
+fsattr = tsk_fs_file_attr_get_idx (fsfile, index);
+
+if (fsattr != NULL && fsattr->flags & TSK_FS_ATTR_NONRES)
+  tsk_fs_attr_walk (fsattr, flags, attrwalk_callback, (void*) );
+  }
+
+  if (blkdata.found)
+ret = send_dirent_info (fsfile, path);
+
+  return (ret == 0) ? TSK_WALK_CONT : TSK_WALK_ERROR;
+}
+
+/* Attribute walk, searches the given block within the FS node attributes. */
+static TSK_WALK_RET_ENUM
+attrwalk_callback (TSK_FS_FILE *fsfile, TSK_OFF_T offset,
+   TSK_DADDR_T blkaddr, char *buf, size_t size,
+   TSK_FS_BLOCK_FLAG_ENUM flags, void *data)
+{
+  findblk_data *blkdata = (findblk_data *) data;
+
+  if (blkaddr == blkdata->block) {
+blkdata->found = 1;
+
+return TSK_WALK_STOP;
+  }
+
+  return TSK_WALK_CONT;
+}
+
 /* Extract the information from the entry, serialize and send it out.
  * Return 0 on success, -1 on error.
  */
diff --git a/generator/actions.ml b/generator/actions.ml
index 91a1819..b38a30f 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -13253,6 +13253,15 @@ is removed." };
 shortdesc = "search the entries associated to the given inode";
 longdesc = "Internal function for find_inode." };

+  { defaults with
+name = "internal_find_block"; added = (1, 35, 6);
+style = RErr, [Mountable "device"; Int64 "block"; FileOut "filename";], [];
+proc_nr = Some 471;
+visibility = VInternal;
+optional = Some "libtsk";
+shortdesc = "search the entries associated to the given block";
+longdesc = "Internal function for find_block." };
+
 ]

 (* Non-API meta-commands available only