diff options
Diffstat (limited to 'mkfs')
| -rw-r--r-- | mkfs/dirscan.c | 59 | 
1 files changed, 32 insertions, 27 deletions
| diff --git a/mkfs/dirscan.c b/mkfs/dirscan.c index b380d73..0a019ec 100644 --- a/mkfs/dirscan.c +++ b/mkfs/dirscan.c @@ -187,21 +187,27 @@ static int xattr_xcan_dfs(const char *path_prefix, void *selinux_handle,  	return 0;  } -static int populate_dir(fstree_t *fs, tree_node_t *root, dev_t devstart, -			unsigned int flags) +static int populate_dir(int dir_fd, fstree_t *fs, tree_node_t *root, +			dev_t devstart, unsigned int flags)  {  	char *extra = NULL;  	struct dirent *ent;  	struct stat sb;  	tree_node_t *n; +	int childfd;  	DIR *dir; -	dir = opendir("."); +	dir = fdopendir(dir_fd);  	if (dir == NULL) { -		perror("opendir"); +		perror("fdopendir"); +		close(dir_fd);  		return -1;  	} +	/* XXX: fdopendir can dup and close dir_fd internally +	   and still be compliant with the spec. */ +	dir_fd = dirfd(dir); +  	for (;;) {  		errno = 0;  		ent = readdir(dir); @@ -217,7 +223,7 @@ static int populate_dir(fstree_t *fs, tree_node_t *root, dev_t devstart,  		if (!strcmp(ent->d_name, "..") || !strcmp(ent->d_name, "."))  			continue; -		if (fstatat(AT_FDCWD, ent->d_name, &sb, AT_SYMLINK_NOFOLLOW)) { +		if (fstatat(dir_fd, ent->d_name, &sb, AT_SYMLINK_NOFOLLOW)) {  			perror(ent->d_name);  			goto fail;  		} @@ -230,8 +236,10 @@ static int populate_dir(fstree_t *fs, tree_node_t *root, dev_t devstart,  			if (extra == NULL)  				goto fail_rdlink; -			if (readlink(ent->d_name, extra, sb.st_size) < 0) +			if (readlinkat(dir_fd, ent->d_name, +				       extra, sb.st_size) < 0) {  				goto fail_rdlink; +			}  			extra[sb.st_size] = '\0';  		} @@ -248,23 +256,21 @@ static int populate_dir(fstree_t *fs, tree_node_t *root, dev_t devstart,  		free(extra);  		extra = NULL; -	} - -	closedir(dir); -	for (n = root->data.dir.children; n != NULL; n = n->next) {  		if (S_ISDIR(n->mode)) { -			if (pushd(n->name)) -				return -1; - -			if (populate_dir(fs, n, devstart, flags)) -				return -1; +			childfd = openat(dir_fd, n->name, O_DIRECTORY | +					 O_RDONLY | O_CLOEXEC); +			if (childfd < 0) { +				perror(n->name); +				goto fail; +			} -			if (popd()) -				return -1; +			if (populate_dir(childfd, fs, n, devstart, flags)) +				goto fail;  		}  	} +	closedir(dir);  	return 0;  fail_rdlink:  	perror("readlink"); @@ -278,22 +284,21 @@ int fstree_from_dir(fstree_t *fs, const char *path, void *selinux_handle,  		    sqfs_xattr_writer_t *xwr, unsigned int flags)  {  	struct stat sb; -	int ret; +	int fd; -	if (stat(path, &sb)) { +	fd = open(path, O_DIRECTORY | O_RDONLY | O_CLOEXEC); +	if (fd < 0) {  		perror(path);  		return -1;  	} -	if (pushd(path)) -		return -1; - -	ret = populate_dir(fs, fs->root, sb.st_dev, flags); - -	if (popd()) +	if (fstat(fd, &sb)) { +		perror(path); +		close(fd);  		return -1; +	} -	if (ret != 0) +	if (populate_dir(fd, fs, fs->root, sb.st_dev, flags))  		return -1;  	if (xwr != NULL && (selinux_handle != NULL || @@ -302,5 +307,5 @@ int fstree_from_dir(fstree_t *fs, const char *path, void *selinux_handle,  			return -1;  	} -	return ret; +	return 0;  } | 
