Re: [PATCH 4/9] switch_root: rewrite to use fstatat() and unlinkat()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 06/19/2009 05:26 AM, Karel Zak wrote:
> Signed-off-by: Karel Zak <kzak@xxxxxxxxxx>

Signed-off-by: Peter Jones <pjones@xxxxxxxxxx>

> ---
>  sys-utils/switch_root.c |   87 ++++++++++++++++++++++++-----------------------
>  1 files changed, 44 insertions(+), 43 deletions(-)
> 
> diff --git a/sys-utils/switch_root.c b/sys-utils/switch_root.c
> index 1520387..3c42c3d 100644
> --- a/sys-utils/switch_root.c
> +++ b/sys-utils/switch_root.c
> @@ -44,70 +44,71 @@ enum {
>  };
>  
>  /* remove all files/directories below dirName -- don't cross mountpoints */
> -static int
> -recursiveRemove(char * dirName)
> +static int recursiveRemove(char *dirName)
>  {
> -	struct stat sb,rb;
> -	DIR * dir;
> -	struct dirent * d;
> -	char * strBuf = alloca(strlen(dirName) + 1024);
> +	struct stat rb;
> +	DIR *dir;
> +	int rc = -1;
> +	int dfd;
>  
>  	if (!(dir = opendir(dirName))) {
>  		printf("error opening %s: %m\n", dirName);
> -		return 0;
> +		goto done;
>  	}
>  
> -	if (fstat(dirfd(dir),&rb)) {
> +	dfd = dirfd(dir);
> +
> +	if (fstat(dfd, &rb)) {
>  		printf("unable to stat %s: %m\n", dirName);
> -		closedir(dir);
> -		return 0;
> +		goto done;
>  	}
>  
> -	errno = 0;
> +	while(1) {
> +		struct dirent *d;
>  
> -	while ((d = readdir(dir))) {
>  		errno = 0;
> +		if (!(d = readdir(dir))) {
> +			if (errno) {
> +				printf("error reading from %s: %m\n", dirName);
> +				goto done;
> +			}
> +			break;	/* end of directory */
> +		}
>  
> -		if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) {
> -			errno = 0;
> +		if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
>  			continue;
> -		}
>  
> -		strcpy(strBuf, dirName);
> -		strcat(strBuf, "/");
> -		strcat(strBuf, d->d_name);
> +		if (d->d_type == DT_DIR) {
> +			struct stat sb;
>  
> -		if (lstat(strBuf, &sb)) {
> -			printf("failed to stat %s: %m\n", strBuf);
> -			errno = 0;
> -			continue;
> -		}
> +			if (fstatat(dfd, d->d_name, &sb, AT_SYMLINK_NOFOLLOW)) {
> +				printf("failed to stat %s/%s: %m\n",
> +						dirName, d->d_name);
> +				continue;
> +			}
>  
> -		/* only descend into subdirectories if device is same as dir */
> -		if (S_ISDIR(sb.st_mode)) {
> +			/* remove subdirectories if device is same as dir */
>  			if (sb.st_dev == rb.st_dev) {
> -				recursiveRemove(strBuf);
> -				if (rmdir(strBuf))
> -					printf("failed to rmdir %s: %m\n", strBuf);
> -			}
> -			errno = 0;
> -			continue;
> -		}
> -		if (unlink(strBuf)) {
> -			printf("failed to remove %s: %m\n", strBuf);
> -			errno = 0;
> -			continue;
> +				char subdir[ strlen(dirName) +
> +					     strlen(d->d_name) + 2 ];
> +
> +				sprintf(subdir, "%s/%s", dirName, d->d_name);
> +				recursiveRemove(subdir);
> +			} else
> +				continue;
>  		}
> -	}
>  
> -	if (errno) {
> -		closedir(dir);
> -		printf("error reading from %s: %m\n", dirName);
> -		return 1;
> +		if (unlinkat(dfd, d->d_name,
> +			     d->d_type == DT_DIR ? AT_REMOVEDIR : 0))
> +			printf("failed to unlink %s/%s: %m\n", dirName, d->d_name);
>  	}
>  
> -	closedir(dir);
> -	return 0;
> +	rc = 0;	/* success */
> +
> +done:
> +	if (dir)
> +		closedir(dir);
> +	return rc;
>  }
>  
>  static int switchroot(const char *newroot)


-- 
        Peter

Gravity is a habit that is hard to shake off.
		-- Pratchett
--
To unsubscribe from this list: send the line "unsubscribe util-linux-ng" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux