Change nftw() to depth-first scan to handle restoring directory permissions correctly.

When sorting cause directories to be sorted after files and in descending order of nesting level.
Take out stray printf().
This commit is contained in:
Moinak Ghosh 2014-01-01 21:38:17 +05:30
parent 683c3e48b5
commit aef48f715f

View file

@ -82,7 +82,7 @@ AE_IFIFO Named pipe (fifo)
#define AW_BLOCK_SIZE (256 * 1024) #define AW_BLOCK_SIZE (256 * 1024)
typedef struct member_entry { typedef struct member_entry {
char name[NAMELEN]; uchar_t name[NAMELEN];
uint32_t file_pos; // 32-bit file position to limit memory usage. uint32_t file_pos; // 32-bit file position to limit memory usage.
uint64_t size; uint64_t size;
} member_entry_t; } member_entry_t;
@ -515,7 +515,6 @@ do_mmap:
while (fpath[n] == '/' && n > 0) n--; while (fpath[n] == '/' && n > 0) n--;
while (fpath[n] != '/' && fpath[n] != '\\' && n > 0) n--; while (fpath[n] != '/' && fpath[n] != '\\' && n > 0) n--;
*namechars = &fpath[n+1]; *namechars = &fpath[n+1];
printf("%s\n", fpath);
} }
return (rbytes); return (rbytes);
} }
@ -531,7 +530,6 @@ add_pathname(const char *fpath, const struct stat *sb,
uchar_t *buf; uchar_t *buf;
const char *basename; const char *basename;
if (tflag == FTW_DP) return (0);
if (tflag == FTW_DNR || tflag == FTW_NS) { if (tflag == FTW_DNR || tflag == FTW_NS) {
log_msg(LOG_WARN, 0, "Cannot access %s\n", fpath); log_msg(LOG_WARN, 0, "Cannot access %s\n", fpath);
return (0); return (0);
@ -616,7 +614,14 @@ add_pathname(const char *fpath, const struct stat *sb,
dot = strrchr(basename, '.'); dot = strrchr(basename, '.');
// Small NAMELEN so these loops will be unrolled by compiler. // Small NAMELEN so these loops will be unrolled by compiler.
if (tflag != FTW_DP) {
/*
* If not a directory then we store upto first 4 chars of
* the extension, if present, or first 4 chars of the
* filename.
*/
for (i = 0; i < NAMELEN; i++) member->name[i] = 0; for (i = 0; i < NAMELEN; i++) member->name[i] = 0;
i = 0; i = 0;
if (!dot) { if (!dot) {
while (basename[i] != '\0' && i < NAMELEN) { while (basename[i] != '\0' && i < NAMELEN) {
@ -628,6 +633,21 @@ add_pathname(const char *fpath, const struct stat *sb,
member->name[i] = dot[i]; i++; member->name[i] = dot[i]; i++;
} }
} }
} else {
/*
* If this is directory then we store 0xff in the 4 bytes
* and invert the size value. This is done to cause directories
* to be always sorted after other pathname entries and to
* be sorted in descending order of nesting depth.
* If we are extracting all permissions then read-only directory
* permissions cannot be set before all their child members are
* extracted. The following ensures directories are sorted after
* other pathnames and they are sorted in descending order of
* their nesting depth.
*/
for (i = 0; i < NAMELEN; i++) member->name[i] = 255;
member->size = INT64_MAX - ftwbuf->level;
}
} }
cont: cont:
buf = a_state.pbuf + a_state.bufpos; buf = a_state.pbuf + a_state.bufpos;
@ -729,7 +749,11 @@ setup_archiver(pc_ctx_t *pctx, struct stat *sbuf)
a_state.arc_size = 0; a_state.arc_size = 0;
a_state.fcount = 0; a_state.fcount = 0;
if (S_ISDIR(sb.st_mode)) { if (S_ISDIR(sb.st_mode)) {
err = nftw(fn->filename, add_pathname, 1024, FTW_PHYS); /*
* Depth-First scan, FTW_DEPTH, is needed to handle restoring
* all directory permissions correctly.
*/
err = nftw(fn->filename, add_pathname, 1024, FTW_PHYS | FTW_DEPTH);
} else { } else {
int tflag; int tflag;
struct FTW ftwbuf; struct FTW ftwbuf;