char * base_name (char const *name) { char const *base = last_component (name); size_t length; /* If there is no last component, then name is a file system root or the empty string. */ if (! *base) return xstrndup (name, base_len (name)); /* Collapse a sequence of trailing slashes into one. */ length = base_len (base); if (ISSLASH (base[length])) length++; /* On systems with drive letters, `a/b:c' must return `./b:c' rather than `b:c' to avoid confusion with a drive letter. On systems with pure POSIX semantics, this is not an issue. */ if (FILE_SYSTEM_PREFIX_LEN (base)) { char *p = xmalloc (length + 3); p[0] = '.'; p[1] = '/'; memcpy (p + 2, base, length); p[length + 2] = '\0'; return p; } /* Finally, copy the basename. */ return xstrndup (base, length); }
char * mfile_name_concat (char const *dir, char const *abase, char **base_in_result) { char const *dirbase = last_component (dir); size_t dirbaselen = base_len (dirbase); size_t dirlen = dirbase - dir + dirbaselen; size_t needs_separator = (dirbaselen && ! ISSLASH (dirbase[dirbaselen - 1])); char const *base = longest_relative_suffix (abase); size_t baselen = strlen (base); char *p_concat = malloc (dirlen + needs_separator + baselen + 1); char *p; if (p_concat == NULL) return NULL; p = mempcpy (p_concat, dir, dirlen); *p = DIRECTORY_SEPARATOR; p += needs_separator; if (base_in_result) *base_in_result = p - IS_ABSOLUTE_FILE_NAME (abase); p = mempcpy (p, base, baselen); *p = '\0'; return p_concat; }
bool strip_trailing_slashes (char *file) { char *base = base_name (file); char *base_lim = base + base_len (base); bool had_slash = (*base_lim != '\0'); *base_lim = '\0'; return had_slash; }
static void check_extension (char *file, size_t filelen, char e) { char *base = last_component (file); size_t baselen = base_len (base); size_t baselen_max = HAVE_LONG_FILE_NAMES ? 255 : NAME_MAX_MINIMUM; if (HAVE_DOS_FILE_NAMES || NAME_MAX_MINIMUM < baselen) { /* The new base name is long enough to require a pathconf check. */ long name_max; /* Temporarily modify the buffer into its parent directory name, invoke pathconf on the directory, and then restore the buffer. */ char tmp[sizeof "."]; memcpy (tmp, base, sizeof "."); strcpy (base, "."); errno = 0; name_max = pathconf (file, _PC_NAME_MAX); if (0 <= name_max || errno == 0) { long size = baselen_max = name_max; if (name_max != size) baselen_max = SIZE_MAX; } memcpy (base, tmp, sizeof "."); } if (HAVE_DOS_FILE_NAMES && baselen_max <= 12) { /* Live within DOS's 8.3 limit. */ char *dot = strchr (base, '.'); if (!dot) baselen_max = 8; else { char const *second_dot = strchr (dot + 1, '.'); baselen_max = (second_dot ? second_dot - base : dot + 1 - base + 3); } } if (baselen_max < baselen) { baselen = file + filelen - base; if (baselen_max <= baselen) baselen = baselen_max - 1; base[baselen] = e; base[baselen + 1] = '\0'; } }
bool strip_trailing_slashes (char *file) { char *base = last_component (file); char *base_lim; bool had_slash; /* last_component returns "" for file system roots, but we need to turn `///' into `/'. */ if (! *base) base = file; base_lim = base + base_len (base); had_slash = (*base_lim != '\0'); *base_lim = '\0'; return had_slash; }
char * path_concat (const char *dir, const char *base, char **base_in_result) { char *p; char *p_concat; size_t baselen; size_t dirlen; if (!dir) { p_concat = strdup (base); if (base_in_result) *base_in_result = p_concat; return p_concat; } /* DIR is not empty. */ baselen = base_len (base); dirlen = strlen (dir); p_concat = malloc (dirlen + baselen + 2); if (!p_concat) return 0; p = mempcpy (p_concat, dir, dirlen); if (FILESYSTEM_PREFIX_LEN (dir) < dirlen) { if (ISSLASH (*(p - 1)) && ISSLASH (*base)) --p; else if (!ISSLASH (*(p - 1)) && !ISSLASH (*base)) *p++ = DIRECTORY_SEPARATOR; } if (base_in_result) *base_in_result = p; memcpy (p, base, baselen); p[baselen] = '\0'; return p_concat; }
static char const * expand_name (char *name, bool is_dir, char const *other_name) { if (STREQ (name, "-")) fatal ("cannot interactively merge standard input"); if (! is_dir) return name; else { /* Yield NAME/BASE, where BASE is OTHER_NAME's basename. */ char const *base = last_component (other_name); size_t namelen = strlen (name), baselen = base_len (base); bool insert_slash = *last_component (name) && name[namelen - 1] != '/'; char *r = xmalloc (namelen + insert_slash + baselen + 1); memcpy (r, name, namelen); r[namelen] = '/'; memcpy (r + namelen + insert_slash, base, baselen); r[namelen + insert_slash + baselen] = '\0'; return r; } }
char *mfile_name_concat( char *dir, char *abase, char **base_in_result ) { char *dirbase = last_component( dir ); size_t dirbaselen = base_len( dirbase ); size_t dirlen = dirbaselen + ( dirbase - dir ); size_t needs_separator = dirbaselen == 0 || dirbase[ dirbaselen - 1 ] == '/' ? 0 : 1; char *base = longest_relative_suffix( abase ); size_t baselen = strlen( base ); char *p_concat = malloc( ( baselen + needs_separator + dirlen + 1 ) * sizeof( char ) ); char *p; if ( p_concat == 0 ) { return 0; } p = mempcpy( p_concat, dir, dirlen ); p[0] = '/'; p = &p[ needs_separator ]; if ( base_in_result != 0 ) base_in_result[0] = &p[ ( abase[0] == '/' ) * -1 ]; p = mempcpy( p, base, baselen ); p[0] = 0; return p_concat; }
/* Rename the file SRC to DST. This replacement is necessary on Windows, on which the system rename function will not replace an existing DST. */ int rpl_rename (char const *src, char const *dst) { int error; size_t src_len = strlen (src); size_t dst_len = strlen (dst); char *src_base = last_component (src); char *dst_base = last_component (dst); bool src_slash; bool dst_slash; bool dst_exists; struct stat src_st; struct stat dst_st; /* Filter out dot as last component. */ if (!src_len || !dst_len) { errno = ENOENT; return -1; } if (*src_base == '.') { size_t len = base_len (src_base); if (len == 1 || (len == 2 && src_base[1] == '.')) { errno = EINVAL; return -1; } } if (*dst_base == '.') { size_t len = base_len (dst_base); if (len == 1 || (len == 2 && dst_base[1] == '.')) { errno = EINVAL; return -1; } } /* Presence of a trailing slash requires directory semantics. If the source does not exist, or if the destination cannot be turned into a directory, give up now. Otherwise, strip trailing slashes before calling rename. There are no symlinks on mingw, so stat works instead of lstat. */ src_slash = ISSLASH (src[src_len - 1]); dst_slash = ISSLASH (dst[dst_len - 1]); if (stat (src, &src_st)) return -1; if (stat (dst, &dst_st)) { if (errno != ENOENT || (!S_ISDIR (src_st.st_mode) && dst_slash)) return -1; dst_exists = false; } else { if (S_ISDIR (dst_st.st_mode) != S_ISDIR (src_st.st_mode)) { errno = S_ISDIR (dst_st.st_mode) ? EISDIR : ENOTDIR; return -1; } dst_exists = true; } /* There are no symlinks, so if a file existed with a trailing slash, it must be a directory, and we don't have to worry about stripping strip trailing slash. However, mingw refuses to replace an existing empty directory, so we have to help it out. And canonicalize_file_name is not yet ported to mingw; however, for directories, getcwd works as a viable alternative. Ensure that we can get back to where we started before using it; later attempts to return are fatal. Note that we can end up losing a directory if rename then fails, but it was empty, so not much damage was done. */ if (dst_exists && S_ISDIR (dst_st.st_mode)) { char *cwd = getcwd (NULL, 0); char *src_temp; char *dst_temp; if (!cwd || chdir (cwd)) return -1; if (IS_ABSOLUTE_FILE_NAME (src)) { dst_temp = chdir (dst) ? NULL : getcwd (NULL, 0); src_temp = chdir (src) ? NULL : getcwd (NULL, 0); } else { src_temp = chdir (src) ? NULL : getcwd (NULL, 0); if (!IS_ABSOLUTE_FILE_NAME (dst) && chdir (cwd)) abort (); dst_temp = chdir (dst) ? NULL : getcwd (NULL, 0); } if (chdir (cwd)) abort (); free (cwd); if (!src_temp || !dst_temp) { free (src_temp); free (dst_temp); errno = ENOMEM; return -1; } src_len = strlen (src_temp); if (strncmp (src_temp, dst_temp, src_len) == 0 && (ISSLASH (dst_temp[src_len]) || dst_temp[src_len] == '\0')) { error = dst_temp[src_len]; free (src_temp); free (dst_temp); if (error) { errno = EINVAL; return -1; } return 0; } if (rmdir (dst)) { error = errno; free (src_temp); free (dst_temp); errno = error; return -1; } free (src_temp); free (dst_temp); } /* MoveFileEx works if SRC is a directory without any flags, but fails with MOVEFILE_REPLACE_EXISTING, so try without flags first. Thankfully, MoveFileEx handles hard links correctly, even though rename() does not. */ if (MoveFileEx (src, dst, 0)) return 0; /* Retry with MOVEFILE_REPLACE_EXISTING if the move failed due to the destination already existing. */ error = GetLastError (); if (error == ERROR_FILE_EXISTS || error == ERROR_ALREADY_EXISTS) { if (MoveFileEx (src, dst, MOVEFILE_REPLACE_EXISTING)) return 0; error = GetLastError (); } switch (error) { case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: case ERROR_BAD_PATHNAME: case ERROR_DIRECTORY: errno = ENOENT; break; case ERROR_ACCESS_DENIED: case ERROR_SHARING_VIOLATION: errno = EACCES; break; case ERROR_OUTOFMEMORY: errno = ENOMEM; break; case ERROR_CURRENT_DIRECTORY: errno = EBUSY; break; case ERROR_NOT_SAME_DEVICE: errno = EXDEV; break; case ERROR_WRITE_PROTECT: errno = EROFS; break; case ERROR_WRITE_FAULT: case ERROR_READ_FAULT: case ERROR_GEN_FAILURE: errno = EIO; break; case ERROR_HANDLE_DISK_FULL: case ERROR_DISK_FULL: case ERROR_DISK_TOO_FRAGMENTED: errno = ENOSPC; break; case ERROR_FILE_EXISTS: case ERROR_ALREADY_EXISTS: errno = EEXIST; break; case ERROR_BUFFER_OVERFLOW: case ERROR_FILENAME_EXCED_RANGE: errno = ENAMETOOLONG; break; case ERROR_INVALID_NAME: case ERROR_DELETE_PENDING: errno = EPERM; /* ? */ break; # ifndef ERROR_FILE_TOO_LARGE /* This value is documented but not defined in all versions of windows.h. */ # define ERROR_FILE_TOO_LARGE 223 # endif case ERROR_FILE_TOO_LARGE: errno = EFBIG; break; default: errno = EINVAL; break; } return -1; }
int rpl_rename (char const *src, char const *dst) { size_t src_len = strlen (src); size_t dst_len = strlen (dst); char *src_temp = (char *) src; char *dst_temp = (char *) dst; bool src_slash; bool dst_slash; bool dst_exists; int ret_val = -1; int rename_errno = ENOTDIR; struct stat src_st; struct stat dst_st; if (!src_len || !dst_len) return rename (src, dst); /* Let strace see the ENOENT failure. */ # if RENAME_DEST_EXISTS_BUG { char *src_base = last_component (src); char *dst_base = last_component (dst); if (*src_base == '.') { size_t len = base_len (src_base); if (len == 1 || (len == 2 && src_base[1] == '.')) { errno = EINVAL; return -1; } } if (*dst_base == '.') { size_t len = base_len (dst_base); if (len == 1 || (len == 2 && dst_base[1] == '.')) { errno = EINVAL; return -1; } } } # endif /* RENAME_DEST_EXISTS_BUG */ src_slash = src[src_len - 1] == '/'; dst_slash = dst[dst_len - 1] == '/'; # if !RENAME_HARD_LINK_BUG && !RENAME_DEST_EXISTS_BUG /* If there are no trailing slashes, then trust the native implementation unless we also suspect issues with hard link detection or file/directory conflicts. */ if (!src_slash && !dst_slash) return rename (src, dst); # endif /* !RENAME_HARD_LINK_BUG && !RENAME_DEST_EXISTS_BUG */ /* Presence of a trailing slash requires directory semantics. If the source does not exist, or if the destination cannot be turned into a directory, give up now. Otherwise, strip trailing slashes before calling rename. */ if (lstat (src, &src_st)) return -1; if (lstat (dst, &dst_st)) { if (errno != ENOENT || (!S_ISDIR (src_st.st_mode) && dst_slash)) return -1; dst_exists = false; } else { if (S_ISDIR (dst_st.st_mode) != S_ISDIR (src_st.st_mode)) { errno = S_ISDIR (dst_st.st_mode) ? EISDIR : ENOTDIR; return -1; } # if RENAME_HARD_LINK_BUG if (SAME_INODE (src_st, dst_st)) return 0; # endif /* RENAME_HARD_LINK_BUG */ dst_exists = true; } # if (RENAME_TRAILING_SLASH_SOURCE_BUG || RENAME_DEST_EXISTS_BUG \ || RENAME_HARD_LINK_BUG) /* If the only bug was that a trailing slash was allowed on a non-existing file destination, as in Solaris 10, then we've already covered that situation. But if there is any problem with a trailing slash on an existing source or destination, as in Solaris 9, or if a directory can overwrite a symlink, as on Cygwin 1.5, or if directories cannot be created with trailing slash, as on NetBSD 1.6, then we must strip the offending slash and check that we have not encountered a symlink instead of a directory. Stripping a trailing slash interferes with POSIX semantics, where rename behavior on a symlink with a trailing slash operates on the corresponding target directory. We prefer the GNU semantics of rejecting any use of a symlink with trailing slash, but do not enforce them, since Solaris 10 is able to obey POSIX semantics and there might be clients expecting it, as counter-intuitive as those semantics are. Technically, we could also follow the POSIX behavior by chasing a readlink trail, but that is harder to implement. */ if (src_slash) { src_temp = strdup (src); if (!src_temp) { /* Rather than rely on strdup-posix, we set errno ourselves. */ rename_errno = ENOMEM; goto out; } strip_trailing_slashes (src_temp); if (lstat (src_temp, &src_st)) { rename_errno = errno; goto out; } if (S_ISLNK (src_st.st_mode)) goto out; } if (dst_slash) { dst_temp = strdup (dst); if (!dst_temp) { rename_errno = ENOMEM; goto out; } strip_trailing_slashes (dst_temp); if (lstat (dst_temp, &dst_st)) { if (errno != ENOENT) { rename_errno = errno; goto out; } } else if (S_ISLNK (dst_st.st_mode)) goto out; } # endif /* RENAME_TRAILING_SLASH_SOURCE_BUG || RENAME_DEST_EXISTS_BUG || RENAME_HARD_LINK_BUG */
static enum numbered_backup_result numbered_backup (char **buffer, size_t buffer_size, size_t filelen) { enum numbered_backup_result result = BACKUP_IS_NEW; DIR *dirp; struct dirent *dp; char *buf = *buffer; size_t versionlenmax = 1; char *base = last_component (buf); size_t base_offset = base - buf; size_t baselen = base_len (base); /* Temporarily modify the buffer into its parent directory name, open the directory, and then restore the buffer. */ char tmp[sizeof "."]; memcpy (tmp, base, sizeof "."); strcpy (base, "."); dirp = opendir (buf); memcpy (base, tmp, sizeof "."); strcpy (base + baselen, ".~1~"); if (!dirp) return result; while ((dp = readdir (dirp)) != NULL) { char const *p; char *q; bool all_9s; size_t versionlen; size_t new_buflen; if (! REAL_DIR_ENTRY (dp) || _D_EXACT_NAMLEN (dp) < baselen + 4) continue; if (memcmp (buf + base_offset, dp->d_name, baselen + 2) != 0) continue; p = dp->d_name + baselen + 2; /* Check whether this file has a version number and if so, whether it is larger. Use string operations rather than integer arithmetic, to avoid problems with integer overflow. */ if (! ('1' <= *p && *p <= '9')) continue; all_9s = (*p == '9'); for (versionlen = 1; ISDIGIT (p[versionlen]); versionlen++) all_9s &= (p[versionlen] == '9'); if (! (p[versionlen] == '~' && !p[versionlen + 1] && (versionlenmax < versionlen || (versionlenmax == versionlen && memcmp (buf + filelen + 2, p, versionlen) <= 0)))) continue; /* This directory has the largest version number seen so far. Append this highest numbered extension to the file name, prepending '0' to the number if it is all 9s. */ versionlenmax = all_9s + versionlen; result = (all_9s ? BACKUP_IS_LONGER : BACKUP_IS_SAME_LENGTH); new_buflen = filelen + 2 + versionlenmax + 1; if (buffer_size <= new_buflen) { buf = xnrealloc (buf, 2, new_buflen); buffer_size = new_buflen * 2; } q = buf + filelen; *q++ = '.'; *q++ = '~'; *q = '0'; q += all_9s; memcpy (q, p, versionlen + 2); /* Add 1 to the version number. */ q += versionlen; while (*--q == '9') *q = '0'; ++*q; } closedir (dirp); *buffer = buf; return result; }
bool same_name(const char *source, const char *dest) { /* Compare the basenames. */ char const *source_basename = last_component(source); char const *dest_basename = last_component(dest); size_t source_baselen = base_len(source_basename); size_t dest_baselen = base_len(dest_basename); bool identical_basenames = ((source_baselen == dest_baselen) && (memcmp(source_basename, dest_basename, dest_baselen) == 0)); bool compare_dirs = identical_basenames; bool same = false; #if ! _POSIX_NO_TRUNC && HAVE_PATHCONF && (defined(_PC_NAME_MAX) || defined(_POSIX_NAME_MAX)) /* This implementation silently truncates components of file names. If * the base names might be truncated, check whether the truncated * base names are the same, while checking the directories. */ size_t slen_max = (HAVE_LONG_FILE_NAMES ? 255 : _POSIX_NAME_MAX); size_t min_baselen = MIN(source_baselen, dest_baselen); if ((slen_max <= min_baselen) && (memcmp(source_basename, dest_basename, slen_max) == 0)) { compare_dirs = true; } #else /* use 'MIN' macro: */ size_t min_baselen = MIN(source_baselen, dest_baselen); /* dummy condition to use value stored to it: */ if ((min_baselen == source_baselen) || (min_baselen == dest_baselen)) { ; } #endif /* !_POSIX_NO_TRUNC && HAVE_PATHCONF && (_PC_NAME_MAX || _POSIX_NAME_MAX) */ if (compare_dirs) { struct stat source_dir_stats; struct stat dest_dir_stats; char *source_dirname, *dest_dirname; /* Compare the parent directories (via the device and inode numbers). */ source_dirname = dir_name(source); dest_dirname = dir_name(dest); if (stat(source_dirname, &source_dir_stats)) { /* Should NOT happen. */ error (1, errno, "%s", source_dirname); } if (stat(dest_dirname, &dest_dir_stats)) { /* Should NOT happen. */ error (1, errno, "%s", dest_dirname); } same = SAME_INODE(source_dir_stats, dest_dir_stats); #if ! _POSIX_NO_TRUNC && HAVE_PATHCONF && defined _PC_NAME_MAX if (same && ! identical_basenames) { long name_max = (errno = 0, pathconf(dest_dirname, _PC_NAME_MAX)); if (name_max < 0) { if (errno) { /* Should NOT happen. */ error(1, errno, "%s", dest_dirname); } same = false; } else same = ((name_max <= min_baselen) && (memcmp(source_basename, dest_basename, name_max) == 0)); } #endif /* !_POSIX_NO_TRUNC && HAVE_PATHCONF && _PC_NAME_MAX */ free(source_dirname); free(dest_dirname); } return same; }
int main (void) { struct test *t; bool ok = true; for (t = tests; t->name; t++) { char *dir = dir_name (t->name); int dirlen = dir_len (t->name); char *last = last_component (t->name); char *base = base_name (t->name); int baselen = base_len (base); char *stripped = strdup (t->name); bool modified = strip_trailing_slashes (stripped); bool absolute = IS_ABSOLUTE_FILE_NAME (t->name); if (! (strcmp (dir, t->dir) == 0 && (dirlen == strlen (dir) || (dirlen + 1 == strlen (dir) && dir[dirlen] == '.')))) { ok = false; printf ("dir_name '%s': got '%s' len %d," " expected '%s' len %ld\n", t->name, dir, dirlen, t->dir, (unsigned long) strlen (t->dir)); } if (strcmp (last, t->last)) { ok = false; printf ("last_component '%s': got '%s', expected '%s'\n", t->name, last, t->last); } if (! (strcmp (base, t->base) == 0 && (baselen == strlen (base) || (baselen + 1 == strlen (base) && ISSLASH (base[baselen]))))) { ok = false; printf ("base_name '%s': got '%s' len %d," " expected '%s' len %ld\n", t->name, base, baselen, t->base, (unsigned long) strlen (t->base)); } if (strcmp (stripped, t->stripped) || modified != t->modified) { ok = false; printf ("strip_trailing_slashes '%s': got %s %s, expected %s %s\n", t->name, stripped, modified ? "changed" : "unchanged", t->stripped, t->modified ? "changed" : "unchanged"); } if (t->absolute != absolute) { ok = false; printf ("'%s': got %s, expected %s\n", t->name, absolute ? "absolute" : "relative", t->absolute ? "absolute" : "relative"); } free (dir); free (base); free (stripped); } return ok ? 0 : 1; }
extern char strip_trailing_slashes(char *__T34544056); static void __zvm_this_file_init(void); static __attribute__((__constructor__)) void __zvm_file_constructor(void); char strip_trailing_slashes( char *file) { auto char __T34690784; auto int __zvm_memchk_nesting_nr; auto void *__zvm_prev_stack_end; auto char __T33175560; auto char *base; auto char *base_lim = 0xaaaaaaaaaaaaaaaa; auto char had_slash; # 32 __zvm_memchk_nesting_nr = (__zvm_memchk_push_function("strip_trailing_slashes", 0, "/home/release/apps/grep2.5.3/grep-2.9/lib/stripslash.c", 31)); __zvm_memchk_add_stack_object("/home/release/apps/grep2.5.3/grep-2.9/lib/stripslash.c", ((int)31), ((void *)((unsigned long)(&base))), ((unsigned long)8), ((unsigned long)1), ((const char *)((unsigned long)"base")), ((int)__zvm_memchk_nesting_nr)); __ZVM_DECL_LOCAL_MLS(); __zvm_mls_scope_in(__zvm_cc_var, 1, file, (__zvm_varinfo + 1U)); __ZVM_PUSH_FUNC_INIT((__zvm_funcinfo + 2U)); __zcov_update_counter(0); __ZVM_PUSH_FUNC((__zvm_funcinfo + 0U)); base = (((void *)(__zvm_mls_set_instrumented(__zvm_cc_var))) , ((char *)(__zvm_mls_ptr_init((last_component(((const char *)file))))))); { # 39 if ((!((int)((*((char *)(__zvm_component_reference_inline((__zvm_varinfo + 2U), ((void *)((unsigned long)base)), ((long)0L), ((int)1), ((void *)((unsigned long)__zvm_cc_var)))))))))) { __zcov_update_counter(1); ((void *)(__zvm_mls_set_instrumented(__zvm_cc_var))) , ((char *)(__zvm_mls_ptr_assignment((__zvm_varinfo + 3U), __zvm_cc_var, (&base), file, 0))); } else { __zcov_update_counter(2); } } __zcov_update_counter(3); __ZVM_PUSH_FUNC((__zvm_funcinfo + 1U)); ((void *)(__zvm_mls_set_instrumented(__zvm_cc_var))) , ((char *)(__zvm_mls_ptr_assignment((__zvm_varinfo + 4U), __zvm_cc_var, (&base_lim), (base + (base_len(((const char *)base)))), 0))); had_slash = ((char)((((int)((*((char *)(__zvm_component_reference_inline((__zvm_varinfo + 5U), ((void *)((unsigned long)base_lim)), ((long)0L), ((int)1), ((void *)((unsigned long)__zvm_cc_var)))))))) != 0) != 0)); (*((char *)(__zvm_component_reference_inline((__zvm_varinfo + 6U), ((void *)((unsigned long)base_lim)), ((long)0L), ((int)1), ((void *)((unsigned long)__zvm_cc_var)))))) = ((char)0); { __T33175560 = had_slash; __zvm_mls_scope_out("/home/release/apps/grep2.5.3/grep-2.9/lib/stripslash.c", 43, __zvm_cc_var, __zvm_mls_return_unused, 0, 3, 0, base, "base", base_lim, "base_lim", file, "file"); __ZVM_POP_FUNC_END(); { __T34690784 = __T33175560; __zvm_memchk_pop_function("strip_trailing_slashes", __zvm_memchk_nesting_nr); return __T34690784; } } } static void __zvm_this_file_init(void) { } static __attribute__((__constructor__)) void __zvm_file_constructor(void) { __zvm_file_ctr(((void *)__zvm_dirnames)); __zvm_this_file_init(); __zvm_local_init_inline(); __zvm_dr_varinfo_init(((void *)__zvm_varinfo), zvm_file_option); __zvm_update_align(4U); }
bool same_name (const char *source, const char *dest) { /* Compare the basenames. */ char const *source_basename = last_component (source); char const *dest_basename = last_component (dest); size_t source_baselen = base_len (source_basename); size_t dest_baselen = base_len (dest_basename); bool identical_basenames = (source_baselen == dest_baselen && memcmp (source_basename, dest_basename, dest_baselen) == 0); bool compare_dirs = identical_basenames; bool same = false; #if ! _POSIX_NO_TRUNC && HAVE_PATHCONF && defined _PC_NAME_MAX /* This implementation silently truncates components of file names. If the base names might be truncated, check whether the truncated base names are the same, while checking the directories. */ size_t slen_max = HAVE_LONG_FILE_NAMES ? 255 : _POSIX_NAME_MAX; size_t min_baselen = MIN (source_baselen, dest_baselen); if (slen_max <= min_baselen && memcmp (source_basename, dest_basename, slen_max) == 0) compare_dirs = true; #endif if (compare_dirs) { struct stat source_dir_stats; struct stat dest_dir_stats; char *source_dirname, *dest_dirname; /* Compare the parent directories (via the device and inode numbers). */ source_dirname = dir_name (source); dest_dirname = dir_name (dest); if (stat (source_dirname, &source_dir_stats)) { /* Shouldn't happen. */ error (1, errno, "%s", source_dirname); } if (stat (dest_dirname, &dest_dir_stats)) { /* Shouldn't happen. */ error (1, errno, "%s", dest_dirname); } same = SAME_INODE (source_dir_stats, dest_dir_stats); #if ! _POSIX_NO_TRUNC && HAVE_PATHCONF && defined _PC_NAME_MAX if (same && ! identical_basenames) { long name_max = (errno = 0, pathconf (dest_dirname, _PC_NAME_MAX)); if (name_max < 0) { if (errno) { /* Shouldn't happen. */ error (1, errno, "%s", dest_dirname); } same = false; } else same = (name_max <= min_baselen && memcmp (source_basename, dest_basename, name_max) == 0); } #endif free (source_dirname); free (dest_dirname); } return same; }