diff options
| -rw-r--r-- | bin/gensquashfs/mkfs.c | 4 | ||||
| -rw-r--r-- | include/fstree.h | 14 | ||||
| -rw-r--r-- | lib/fstree/fstree_from_dir.c | 55 | ||||
| -rw-r--r-- | tests/fstree_from_file.c | 2 | 
4 files changed, 62 insertions, 13 deletions
diff --git a/bin/gensquashfs/mkfs.c b/bin/gensquashfs/mkfs.c index 2885d84..b25d325 100644 --- a/bin/gensquashfs/mkfs.c +++ b/bin/gensquashfs/mkfs.c @@ -160,8 +160,8 @@ int main(int argc, char **argv)  	}  	if (opt.infile == NULL) { -		if (fstree_from_dir(&sqfs.fs, sqfs.fs.root, -				    opt.packdir, opt.dirscan_flags)) { +		if (fstree_from_dir(&sqfs.fs, sqfs.fs.root, opt.packdir, +				    NULL, NULL, opt.dirscan_flags)) {  			goto out;  		}  	} else { diff --git a/include/fstree.h b/include/fstree.h index e5fc966..35d6778 100644 --- a/include/fstree.h +++ b/include/fstree.h @@ -41,6 +41,15 @@ typedef struct file_info_t file_info_t;  typedef struct dir_info_t dir_info_t;  typedef struct fstree_t fstree_t; +/* +  Optionally used by fstree_from_dir and fstree_from_subdir to +  execute custom actions for each discovered node. + +  If it returns a value > 0, the new node is discarded, if < 0, scanning is +  aborted and returns a failure status. + */ +typedef int (*scan_node_callback)(void *user, fstree_t *fs, tree_node_t *node); +  /* Additional meta data stored in a tree_node_t for regular files. */  struct file_info_t {  	/* Linked list pointer for files in fstree_t */ @@ -252,7 +261,8 @@ int fstree_resolve_hard_link(fstree_t *fs, tree_node_t *node);    Returns 0 on success, prints to stderr on failure.   */  int fstree_from_dir(fstree_t *fs, tree_node_t *root, -		    const char *path, unsigned int flags); +		    const char *path, scan_node_callback cb, void *user, +		    unsigned int flags);  /*    Same as fstree_from_dir, but scans a sub-directory inside the specified path. @@ -261,6 +271,6 @@ int fstree_from_dir(fstree_t *fs, tree_node_t *root,   */  int fstree_from_subdir(fstree_t *fs, tree_node_t *root,  		       const char *path, const char *subdir, -		       unsigned int flags); +		       scan_node_callback cb, void *user, unsigned int flags);  #endif /* FSTREE_H */ diff --git a/lib/fstree/fstree_from_dir.c b/lib/fstree/fstree_from_dir.c index d3e188d..cb066b1 100644 --- a/lib/fstree/fstree_from_dir.c +++ b/lib/fstree/fstree_from_dir.c @@ -12,30 +12,53 @@  #include <string.h>  #include <errno.h> +static void discard_node(tree_node_t *root, tree_node_t *n) +{ +	tree_node_t *it; + +	if (n == root->data.dir.children) { +		root->data.dir.children = n->next; +	} else { +		it = root->data.dir.children; + +		while (it != NULL && it->next != n) +			it = it->next; + +		if (it != NULL) +			it->next = n->next; +	} + +	free(n); +} +  #ifdef _WIN32  int fstree_from_subdir(fstree_t *fs, tree_node_t *root,  		       const char *path, const char *subdir, +		       scan_node_callback cb, void *user,  		       unsigned int flags)  {  	(void)fs; (void)root; (void)path; (void)subdir; (void)flags; +	(void)cb; (void)user;  	fputs("Packing a directory is not supported on Windows.\n", stderr);  	return -1;  }  int fstree_from_dir(fstree_t *fs, tree_node_t *root, -		    const char *path, unsigned int flags) +		    const char *path, scan_node_callback cb, +		    void *user, unsigned int flags)  { -	return fstree_from_subdir(fs, root, path, NULL, flags); +	return fstree_from_subdir(fs, root, path, NULL, cb, user, flags);  }  #else  static int populate_dir(int dir_fd, fstree_t *fs, tree_node_t *root, -			dev_t devstart, unsigned int flags) +			dev_t devstart, scan_node_callback cb, +			void *user, unsigned int flags)  {  	char *extra = NULL;  	struct dirent *ent; +	int ret, childfd;  	struct stat sb;  	tree_node_t *n; -	int childfd;  	DIR *dir;  	dir = fdopendir(dir_fd); @@ -122,6 +145,8 @@ static int populate_dir(int dir_fd, fstree_t *fs, tree_node_t *root,  						    false, false);  			if (n == NULL)  				continue; + +			ret = 0;  		} else {  			n = fstree_mknode(root, ent->d_name,  					  strlen(ent->d_name), extra, &sb); @@ -129,11 +154,21 @@ static int populate_dir(int dir_fd, fstree_t *fs, tree_node_t *root,  				perror("creating tree node");  				goto fail;  			} + +			ret = (cb == NULL) ? 0 : cb(user, fs, n);  		}  		free(extra);  		extra = NULL; +		if (ret < 0) +			goto fail; + +		if (ret > 0) { +			discard_node(root, n); +			continue; +		} +  		if (S_ISDIR(n->mode) && !(flags & DIR_SCAN_NO_RECURSION)) {  			childfd = openat(dir_fd, n->name, O_DIRECTORY |  					 O_RDONLY | O_CLOEXEC); @@ -142,8 +177,10 @@ static int populate_dir(int dir_fd, fstree_t *fs, tree_node_t *root,  				goto fail;  			} -			if (populate_dir(childfd, fs, n, devstart, flags)) +			if (populate_dir(childfd, fs, n, devstart, +					 cb, user, flags)) {  				goto fail; +			}  		}  	} @@ -159,6 +196,7 @@ fail:  int fstree_from_subdir(fstree_t *fs, tree_node_t *root,  		       const char *path, const char *subdir, +		       scan_node_callback cb, void *user,  		       unsigned int flags)  {  	struct stat sb; @@ -199,12 +237,13 @@ int fstree_from_subdir(fstree_t *fs, tree_node_t *root,  		return -1;  	} -	return populate_dir(fd, fs, root, sb.st_dev, flags); +	return populate_dir(fd, fs, root, sb.st_dev, cb, user, flags);  }  int fstree_from_dir(fstree_t *fs, tree_node_t *root, -		    const char *path, unsigned int flags) +		    const char *path, scan_node_callback cb, +		    void *user, unsigned int flags)  { -	return fstree_from_subdir(fs, root, path, NULL, flags); +	return fstree_from_subdir(fs, root, path, NULL, cb, user, flags);  }  #endif diff --git a/tests/fstree_from_file.c b/tests/fstree_from_file.c index f8f0892..140ffd7 100644 --- a/tests/fstree_from_file.c +++ b/tests/fstree_from_file.c @@ -15,7 +15,7 @@ int main(void)  	fstree_t fs;  	TEST_ASSERT(fstree_init(&fs, NULL) == 0); -	TEST_ASSERT(fstree_from_file(&fs, TEST_PATH) == 0); +	TEST_ASSERT(fstree_from_file(&fs, TEST_PATH, NULL) == 0);  	fstree_post_process(&fs);  	n = fs.root->data.dir.children;  | 
