static void test_unflagged(void) { struct statx buf; TEST(statx(AT_FDCWD, TESTDIR_UNFLAGGED, 0, 0, &buf)); if (TST_RET == 0) tst_res(TPASS, "sys_statx(AT_FDCWD, %s, 0, 0, &buf)", TESTDIR_UNFLAGGED); else tst_brk(TFAIL | TTERRNO, "sys_statx(AT_FDCWD, %s, 0, 0, &buf)", TESTDIR_UNFLAGGED); if ((buf.stx_attributes & STATX_ATTR_COMPRESSED) == 0) tst_res(TPASS, "STATX_ATTR_COMPRESSED flag is not set"); else tst_res(TFAIL, "STATX_ATTR_COMPRESSED flag is set"); if ((buf.stx_attributes & STATX_ATTR_APPEND) == 0) tst_res(TPASS, "STATX_ATTR_APPEND flag is not set"); else tst_res(TFAIL, "STATX_ATTR_APPEND flag is set"); if ((buf.stx_attributes & STATX_ATTR_IMMUTABLE) == 0) tst_res(TPASS, "STATX_ATTR_IMMUTABLE flag is not set"); else tst_res(TFAIL, "STATX_ATTR_IMMUTABLE flag is set"); if ((buf.stx_attributes & STATX_ATTR_NODUMP) == 0) tst_res(TPASS, "STATX_ATTR_NODUMP flag is not set"); else tst_res(TFAIL, "STATX_ATTR_NODUMP flag is set"); }
void __tar_collect_and_sort_names (void) { struct name *n, *n_next; int num_names; struct stat statbuf; __tar_name_gather (); if (gnu_dumpfile) __tar_read_dir_file (); if (!namelist) __tar_addname ("."); for (n = namelist; n; n = n_next) { n_next = n->next; if (n->found || n->dir_contents) continue; if (n->regexp) /* FIXME just skip regexps for now */ continue; if (n->change_dir) if (chdir (n->change_dir) < 0) { ERROR ((0, errno, _("Cannot chdir to %s"), n->change_dir)); continue; } if ( #ifdef AIX statx (n->name, &statbuf, STATSIZE, STX_HIDDEN | STX_LINK) #else lstat (n->name, &statbuf) < 0 #endif ) { ERROR ((0, errno, _("Cannot stat %s"), n->name)); continue; } if (S_ISDIR (statbuf.st_mode)) { n->found++; __tar_add_dir_name (n->name, statbuf.st_dev); } } num_names = 0; for (n = namelist; n; n = n->next) num_names++; namelist = (struct name *) __tar_merge_sort ((voidstar) namelist, (unsigned) num_names, (char *) (&(namelist->next)) - (char *) namelist, __tar_name_cmp); for (n = namelist; n; n = n->next) { n->found = 0; } if (gnu_dumpfile) __tar_write_dir_file (); }
time_t get_file_btime (const char *path) { static int not_implemented = 0; int flags = AT_NO_AUTOMOUNT; unsigned int mask = STATX_BTIME; struct statx stxbuf; long ret = 0; time_t btime; btime = 0; if (not_implemented) { return btime; } memset (&stxbuf, 0xbf, sizeof(stxbuf)); errno = 0; ret = statx (AT_FDCWD, path, flags, mask, &stxbuf); if (ret < 0) { if (errno == ENOSYS) { printf("nemo-creation-date: kernel needs to be (>= 4.15) - file creation dates not available\n"); not_implemented = 1; } return btime; } btime = (&stxbuf)->stx_btime.tv_sec; return btime; }
void collect_and_sort_names (void) { struct name *name; struct name *next_name; int counter; struct stat stat_info; name_gather (); if (listed_incremental_option) read_directory_file (); if (!name_list_head) add_name ("."); for (name = name_list_head; name; name = next_name) { next_name = name->next; if (name->match_found || name->dir_contents) continue; if (name->is_wildcard) /* FIXME: just skip wildcards for now */ continue; if (name->change_dir) if (chdir (name->change_dir) < 0) { ERROR ((0, errno, _("Cannot chdir to %s"), name->change_dir)); continue; } if ( #ifdef AIX statx (name->name, &stat_info, STATSIZE, STX_HIDDEN | STX_LINK) #else lstat (name->name, &stat_info) < 0 #endif ) { ERROR ((0, errno, _("Cannot stat %s"), name->name)); continue; } if (S_ISDIR (stat_info.st_mode)) { name->match_found = true; add_hierarchy_to_namelist (name->name, stat_info.st_dev); } } counter = 0; for (name = name_list_head; name; name = name->next) counter++; name_list_head = (struct name *) merge_sort ((voidstar) name_list_head, counter, (char *) (&(name_list_head->next)) - (char *) name_list_head, compare_names); for (name = name_list_head; name; name = name->next) name->match_found = false; if (listed_incremental_option) write_dir_file (); }
char * get_directory_contents (char *path, dev_t device) { struct accumulator *accumulator; /* Recursively scan the given PATH. */ { DIR *dirp = opendir (path); /* for scanning directory */ struct dirent *entry; /* directory entry being scanned */ char *name_buffer; /* directory, `/', and directory member */ size_t name_buffer_size; /* allocated size of name_buffer, minus 2 */ size_t name_length; /* used length in name_buffer */ struct directory *directory; /* for checking if already already seen */ bool all_children; if (dirp == NULL) { ERROR ((0, errno, _("Cannot open directory %s"), path)); return NULL; } errno = 0; /* FIXME: errno should be read-only */ name_buffer_size = strlen (path) + NAME_FIELD_SIZE; name_buffer = xmalloc (name_buffer_size + 2); strcpy (name_buffer, path); if (path[strlen (path) - 1] != '/') strcat (name_buffer, "/"); name_length = strlen (name_buffer); directory = find_directory (path); all_children = directory ? directory->all_new : false; accumulator = new_accumulator (); while (entry = readdir (dirp), entry) { struct stat stat_info; /* Skip `.' and `..'. */ if (is_dot_or_dotdot (entry->d_name)) continue; if (NAMLEN (entry) + name_length >= name_buffer_size) { while (NAMLEN (entry) + name_length >= name_buffer_size) name_buffer_size += NAME_FIELD_SIZE; name_buffer = (char *) xrealloc (name_buffer, name_buffer_size + 2); } strcpy (name_buffer + name_length, entry->d_name); if (dereference_option #ifdef AIX ? statx (name_buffer, &stat_info, STATSIZE, STX_HIDDEN) : statx (name_buffer, &stat_info, STATSIZE, STX_HIDDEN | STX_LINK) #else ? stat (name_buffer, &stat_info) : lstat (name_buffer, &stat_info) #endif ) { ERROR ((0, errno, _("Cannot stat %s"), name_buffer)); continue; } if ((one_file_system_option && device != stat_info.st_dev) || (exclude_option && check_exclude (name_buffer))) add_to_accumulator (accumulator, "N", (size_t) 1); #ifdef AIX else if (S_ISHIDDEN (stat_info.st_mode)) { add_to_accumulator (accumulator, "D", (size_t) 1); strcat (entry->d_name, "A"); entry->d_namlen++; } #endif else if (S_ISDIR (stat_info.st_mode)) { if (directory = find_directory (name_buffer), directory) { /* The same file can have two different devices if an NFS directory is mounted in multiple locations, which is relatively common when automounting. For avoiding spurious incremental redumping of directories, we have to plainly consider all NFS devices as equal, relying on the i-node only to establish differences. Devices having the high bit set usually are NFS devices. */ /* FIXME: Göran Uddeborg <*****@*****.**> says, on 1996-09-20, that SunOS 5/Solaris 2 uses unsigned long for the device number type. */ if ((((short) directory->device_number >= 0 || (short) stat_info.st_dev >= 0) && directory->device_number != stat_info.st_dev) || directory->inode_number != stat_info.st_ino) { if (verbose_option) WARN ((0, 0, _("Directory %s has been renamed"), name_buffer)); directory->all_new = true; directory->device_number = stat_info.st_dev; directory->inode_number = stat_info.st_ino; } directory->dir_text = ""; } else { if (verbose_option) WARN ((0, 0, _("Directory %s is new"), name_buffer)); note_directory (name_buffer, stat_info.st_dev, stat_info.st_ino, ""); directory = find_directory (name_buffer); directory->all_new = true; } if (all_children && directory) directory->all_new = true; add_to_accumulator (accumulator, "D", (size_t) 1); } else if (all_children || FILE_IS_NEW_ENOUGH (&stat_info)) add_to_accumulator (accumulator, "Y", (size_t) 1); else add_to_accumulator (accumulator, "N", (size_t) 1); add_to_accumulator (accumulator, entry->d_name, NAMLEN (entry) + 1); } add_to_accumulator (accumulator, "\000\000", (size_t) 2); free (name_buffer); closedir (dirp); } /* Sort the contents of the directory, now that we have it all. */ { char *pointer = get_accumulator (accumulator); size_t counter; char *cursor; char *buffer; char **array; char **array_cursor; counter = 0; for (cursor = pointer; *cursor; cursor += strlen (cursor) + 1) counter++; if (counter == 0) { delete_accumulator (accumulator); return NULL; } array = (char **) xmalloc (sizeof (char *) * (counter + 1)); array_cursor = array; for (cursor = pointer; *cursor; cursor += strlen (cursor) + 1) *array_cursor++ = cursor; *array_cursor = NULL; qsort ((voidstar) array, counter, sizeof (char *), compare_dirents); buffer = (char *) xmalloc ((size_t) (cursor - pointer + 2)); cursor = buffer; for (array_cursor = array; *array_cursor; array_cursor++) { char *string = *array_cursor; while ((*cursor++ = *string++)) continue; } *cursor = '\0'; delete_accumulator (accumulator); free (array); return buffer; } }
int __xstat (int ver, const char *pathname, struct stat *st) { assert (ver == 0); return statx (pathname, st, sizeof (*st), STX_NORMAL); }
int main() { int fd; char cwd[128]; struct stat sbuf; struct utimbuf ubuf; #ifdef __NR_statx struct statx stx; #endif getcwd(cwd, 128); //staptest// getcwd (XXXX, 128) = NNNN fd = creat("foobar", S_IREAD|S_IWRITE); //staptest// [[[[open ("foobar", O_WRONLY|O_CREAT[[[[.O_LARGEFILE]]]]?|O_TRUNC!!!!creat ("foobar"!!!!openat (AT_FDCWD, "foobar", O_WRONLY|O_CREAT|O_TRUNC]]]], 0600) = NNNN fstat(fd, &sbuf); //staptest// fstat (NNNN, XXXX) = 0 fstat(-1, &sbuf); //staptest// fstat (-1, XXXX) = -NNNN (EBADF) // Here we specify -1 to both arguments, to avoid a SIGSEGV. fstat(-1, (struct stat *)-1); #if __WORDSIZE != 64 // Notice we're not checking for 0x[f]+ here for the 2nd // argument. On RHEL[67] {x86_64,s390x}, for a 32-bit exe, glibc // substituted a real structure address (verified with strace). // staptest// fstat (-1, XXXX) = -NNNN #else //staptest// fstat (-1, 0x[f]+) = -NNNN #endif #ifdef __NR_statx memset(&stx, 0xbf, sizeof(stx)); statx(AT_FDCWD, "foobar", AT_SYMLINK_NOFOLLOW, AT_STATX_FORCE_SYNC, &stx); //staptest// statx (AT_FDCWD, "foobar", AT_SYMLINK_NOFOLLOW, AT_STATX_FORCE_SYNC, XXXX) = 0 statx((int)-1, "foobar", AT_SYMLINK_NOFOLLOW, AT_STATX_FORCE_SYNC, &stx); //staptest// statx (-1, "foobar", AT_SYMLINK_NOFOLLOW, AT_STATX_FORCE_SYNC, XXXX) = -NNNN (EBADF) statx(AT_FDCWD, (const char *)-1, AT_SYMLINK_NOFOLLOW, AT_STATX_FORCE_SYNC, &stx); #ifdef __s390__ //staptest// statx (AT_FDCWD, 0x[7]?[f]+, AT_SYMLINK_NOFOLLOW, AT_STATX_FORCE_SYNC, XXXX) = -NNNN (EFAULT) #else //staptest// statx (AT_FDCWD, 0x[f]+, AT_SYMLINK_NOFOLLOW, AT_STATX_FORCE_SYNC, XXXX) = -NNNN (EFAULT) #endif statx(AT_FDCWD, "foobar", (unsigned)-1, AT_STATX_FORCE_SYNC, &stx); //staptest// statx (AT_FDCWD, "foobar", AT_SYMLINK_NOFOLLOW|AT_REMOVEDIR|AT_SYMLINK_FOLLOW|AT_NO_AUTOMOUNT|AT_EMPTY_PATH|XXXX, AT_STATX_FORCE_SYNC, XXXX) = -NNNN (EINVAL) statx(AT_FDCWD, "foobar", AT_SYMLINK_NOFOLLOW, (unsigned)-1, &stx); //staptest// statx (AT_FDCWD, "foobar", AT_SYMLINK_NOFOLLOW, 0x[f]+, XXXX) = NNNN statx(AT_FDCWD, "foobar", AT_SYMLINK_NOFOLLOW, AT_STATX_FORCE_SYNC, (struct statx *)-1); #ifdef __s390__ //staptest// statx (AT_FDCWD, "foobar", AT_SYMLINK_NOFOLLOW, AT_STATX_FORCE_SYNC, 0x[7]?[f]+) = -NNNN (EFAULT) #else //staptest// statx (AT_FDCWD, "foobar", AT_SYMLINK_NOFOLLOW, AT_STATX_FORCE_SYNC, 0x[f]+) = -NNNN (EFAULT) #endif #endif close(fd); stat("foobar", &sbuf); //staptest// [[[[stat ("foobar", XXXX!!!!fstatat (AT_FDCWD, "foobar", XXXX, 0x0]]]]) = 0 stat((char *)-1, &sbuf); #if defined(__s390__) //staptest// stat (0x[7]?[f]+, XXXX) = -NNNN #else //staptest// [[[[stat (0x[f]+, XXXX!!!!fstatat (AT_FDCWD, 0x[f]+, XXXX, 0x0]]]]) = -NNNN #endif // Here we specify -1 to both arguments, to avoid a SIGSEGV. stat((char *)-1, (struct stat *)-1); #if __WORDSIZE != 64 // Notice we're not checking for 0x[f]+ here for the 2nd // argument. On RHEL[67] {x86_64,s390x}, for a 32-bit exe, glibc // substituted a real structure address (verified with strace). //staptest// stat (0x[7]?[f]+, XXXX) = -NNNN #else //staptest// [[[[stat (0x[f]+, 0x[f]+!!!!fstatat (AT_FDCWD, 0x[f]+, 0x[f]+, 0x0]]]]) = -NNNN #endif lstat("foobar", &sbuf); //staptest// [[[[lstat ("foobar", XXXX!!!!fstatat (AT_FDCWD, "foobar", XXXX, AT_SYMLINK_NOFOLLOW]]]]) = 0 lstat((char *)-1, &sbuf); #if defined(__s390__) //staptest// lstat (0x[7]?[f]+, XXXX) = -NNNN (EFAULT) #else //staptest// [[[[lstat (0x[f]+, XXXX!!!!fstatat (AT_FDCWD, 0x[f]+, XXXX, AT_SYMLINK_NOFOLLOW]]]]) = -NNNN (EFAULT) #endif // Here we specify -1 to both arguments, to avoid a SIGSEGV. lstat((char *)-1, (struct stat *)-1); #if __WORDSIZE != 64 // Notice we're not checking for 0x[f]+ here for the 2nd // argument. On RHEL[67] {x86_64,s390x}, for a 32-bit exe, glibc // substituted a real structure address (verified with strace). //staptest// lstat (0x[7]?[f]+, XXXX) = -NNNN #else //staptest// [[[[lstat (0x[f]+, 0x[f]+!!!!fstatat (AT_FDCWD, 0x[f]+, 0x[f]+, AT_SYMLINK_NOFOLLOW]]]]) = -NNNN #endif #if GLIBC_SUPPORT fstatat(AT_FDCWD, "foobar", &sbuf, AT_SYMLINK_NOFOLLOW); //staptest// fstatat (AT_FDCWD, "foobar", XXXX, AT_SYMLINK_NOFOLLOW) = 0 fstatat(-1, "foobar", &sbuf, AT_SYMLINK_NOFOLLOW); //staptest// fstatat (-1, "foobar", XXXX, AT_SYMLINK_NOFOLLOW) = -NNNN (EBADF) fstatat(AT_FDCWD, (char *)-1, &sbuf, AT_SYMLINK_NOFOLLOW); #if defined(__s390__) //staptest// fstatat (AT_FDCWD, 0x[7]?[f]+, XXXX, AT_SYMLINK_NOFOLLOW) = -NNNN (EFAULT) #else //staptest// fstatat (AT_FDCWD, 0x[f]+, XXXX, AT_SYMLINK_NOFOLLOW) = -NNNN (EFAULT) #endif // Try to avoid a SIGSEGV. fstatat(-1, "foobar", (struct stat *)-1, AT_SYMLINK_NOFOLLOW); #if __WORDSIZE != 64 // Notice we're not checking for 0x[f]+ here for the 3rd // argument. On RHEL[67] {x86_64,s390x}, for a 32-bit exe, glibc // substituted a real structure address (verified with strace). //staptest// fstatat (-1, "foobar", XXXX, AT_SYMLINK_NOFOLLOW) = -NNNN #else //staptest// fstatat (-1, "foobar", 0x[f]+, AT_SYMLINK_NOFOLLOW) = -NNNN #endif fstatat(AT_FDCWD, "foobar", &sbuf, -1); //staptest// fstatat (AT_FDCWD, "foobar", XXXX, AT_[^ ]+|XXXX) = -NNNN (EINVAL) #endif ubuf.actime = 1; ubuf.modtime = 1135641600; utime("foobar", &ubuf); #if defined(__aarch64__) //staptest// utimensat (AT_FDCWD, "foobar", \[1.[0]+\]\[1135641600.[0]+\], 0x0) = #elif defined(__ia64__) || defined(__arm__) //staptest// utimes ("foobar", \[1.000000\]\[1135641600.000000\]) = #else //staptest// utime ("foobar", \[Thu Jan 1 00:00:01 1970, Tue Dec 27 00:00:00 2005\]) = 0 #endif ubuf.actime = 1135690000; ubuf.modtime = 1135700000; utime("foobar", &ubuf); #if defined(__aarch64__) //staptest// utimensat (AT_FDCWD, "foobar", \[1135690000.[0]+\]\[1135700000.[0]+\], 0x0) = #elif defined(__ia64__) || defined(__arm__) //staptest// utimes ("foobar", \[1135690000.000000\]\[1135700000.000000\]) = #else //staptest// utime ("foobar", \[Tue Dec 27 13:26:40 2005, Tue Dec 27 16:13:20 2005\]) = 0 #endif ubuf.actime = 1; ubuf.modtime = 1135641600; utime((char *)-1, &ubuf); #if defined(__aarch64__) //staptest// utimensat (AT_FDCWD, 0x[f]+, \[1.[0]+\]\[1135641600.[0]+\], 0x0) = -NNNN #elif defined(__ia64__) || defined(__arm__) //staptest// utimes (0x[f]+, \[1.000000\]\[1135641600.000000\]) = -NNNN #elif defined(__s390__) //staptest// utime (0x[7]?[f]+, \[Thu Jan 1 00:00:01 1970, Tue Dec 27 00:00:00 2005\]) = -NNNN #else //staptest// utime (0x[f]+, \[Thu Jan 1 00:00:01 1970, Tue Dec 27 00:00:00 2005\]) = -NNNN #endif #if defined(__ia64__) || defined(__arm__) || defined(__aarch64__) // Avoid a SIGSEGV by specifying NULL, not -1. utime("foobar", (struct utimbuf *)NULL); //staptest// [[[[utimes ("foobar", NULL!!!!utimensat (AT_FDCWD, "foobar", NULL, 0x0]]]]) = NNNN #else utime("foobar", (struct utimbuf *)-1); //staptest// utime ("foobar", \[Thu Jan 1 00:00:00 1970, Thu Jan 1 00:00:00 1970\]) = -NNNN #endif return 0; }
void collect_and_sort_names (void) { struct name *name; struct name *next_name; int num_names; struct stat statbuf; name_gather (); if (listed_incremental_option) read_directory_file (); if (!namelist) addname ("."); for (name = namelist; name; name = next_name) { next_name = name->next; if (name->found || name->dir_contents) continue; if (name->regexp) /* FIXME: just skip regexps for now */ continue; if (name->change_dir) if (chdir (name->change_dir) < 0) { ERROR ((0, errno, _("Cannot chdir to %s"), name->change_dir)); continue; } if ( #ifdef AIX statx (name->name, &statbuf, STATSIZE, STX_HIDDEN | STX_LINK) #else lstat (name->name, &statbuf) < 0 #endif ) { ERROR ((0, errno, _("Cannot stat %s"), name->name)); continue; } if (S_ISDIR (statbuf.st_mode)) { name->found = 1; add_hierarchy_to_namelist (name->name, statbuf.st_dev); } } num_names = 0; for (name = namelist; name; name = name->next) num_names++; namelist = (struct name *) merge_sort ((voidstar) namelist, num_names, (char *) (&(namelist->next)) - (char *) namelist, compare_names); for (name = namelist; name; name = name->next) name->found = 0; if (listed_incremental_option) write_dir_file (); }
char * __tar_get_dir_contents (char *p, int device) { DIR *dirp; register struct dirent *d; char *new_buf; char *namebuf; int bufsiz; int len; voidstar the_buffer; char *buf; size_t n_strs; #if 0 int n_size; #endif char *p_buf; char **vec, **p_vec; errno = 0; dirp = opendir (p); bufsiz = strlen (p) + NAMSIZ; namebuf = tar_xmalloc ((size_t) (bufsiz + 2)); if (!dirp) { ERROR ((0, errno, _("Cannot open directory %s"), p)); new_buf = NULL; } else { struct dirname *dp; int all_children; dp = __tar_get_dir (p); all_children = dp ? dp->allnew : 0; strcpy (namebuf, p); if (p[strlen (p) - 1] != '/') strcat (namebuf, "/"); len = strlen (namebuf); the_buffer = __tar_init_buffer (); while (d = readdir (dirp), d) { struct stat hs; /* Skip `.' and `..'. */ if (__tar_is_dot_or_dotdot (d->d_name)) continue; if ((int) NAMLEN (d) + len >= bufsiz) { bufsiz += NAMSIZ; namebuf = (char *) tar_realloc (namebuf, (size_t) (bufsiz + 2)); } strcpy (namebuf + len, d->d_name); #ifdef AIX if (flag_follow_links ? statx (namebuf, &hs, STATSIZE, STX_HIDDEN) : statx (namebuf, &hs, STATSIZE, STX_HIDDEN | STX_LINK)) #else if (flag_follow_links ? stat (namebuf, &hs) : lstat (namebuf, &hs)) #endif { ERROR ((0, errno, _("Cannot stat %s"), namebuf)); continue; } if ((flag_local_filesys && device != hs.st_dev) || (flag_exclude && __tar_check_exclude (namebuf))) __tar_add_buffer (the_buffer, "N", 1); #ifdef AIX else if (S_ISHIDDEN (hs.st_mode)) { __tar_add_buffer (the_buffer, "D", 1); strcat (d->d_name, "A"); d->d_namlen++; } #endif /* AIX */ else if (S_ISDIR (hs.st_mode)) { if (dp = __tar_get_dir (namebuf), dp) { if (dp->dev != hs.st_dev || dp->ino != hs.st_ino) { if (flag_verbose) WARN ((0, 0, _("Directory %s has been renamed"), namebuf)); dp->allnew = 1; dp->dev = hs.st_dev; dp->ino = hs.st_ino; } dp->dir_text = ""; } else { if (flag_verbose) WARN ((0, 0, _("Directory %s is new"), namebuf)); __tar_add_dir (namebuf, hs.st_dev, hs.st_ino, ""); dp = __tar_get_dir (namebuf); dp->allnew = 1; } if (all_children && dp) dp->allnew = 1; __tar_add_buffer (the_buffer, "D", 1); } else if (!all_children && flag_new_files && new_time > hs.st_mtime && (flag_new_files > 1 || new_time > hs.st_ctime)) __tar_add_buffer (the_buffer, "N", 1); else __tar_add_buffer (the_buffer, "Y", 1); __tar_add_buffer (the_buffer, d->d_name, (int) (NAMLEN (d) + 1)); } __tar_add_buffer (the_buffer, "\000\000", 2); closedir (dirp); /* Well, we've read in the contents of the dir, now sort them. */ buf = __tar_get_buffer (the_buffer); if (buf[0] == '\0') { __tar_flush_buffer (the_buffer); new_buf = NULL; } else { n_strs = 0; for (p_buf = buf; *p_buf;) { int tmp; tmp = strlen (p_buf) + 1; n_strs++; p_buf += tmp; } vec = (char **) tar_xmalloc (sizeof (char *) * (n_strs + 1)); for (p_vec = vec, p_buf = buf; *p_buf; p_buf += strlen (p_buf) + 1) *p_vec++ = p_buf; *p_vec = 0; qsort ((voidstar) vec, n_strs, sizeof (char *), __tar_dirent_cmp); new_buf = (char *) tar_xmalloc ((size_t) (p_buf - buf + 2)); for (p_vec = vec, p_buf = new_buf; *p_vec; p_vec++) { char *p_tmp; for (p_tmp = *p_vec; (*p_buf++ = *p_tmp++); ) ; } *p_buf++ = '\0'; free (vec); __tar_flush_buffer (the_buffer); } } free (namebuf); return new_buf; }