MCPcopy Index your code
hub / github.com/RsyncProject/rsync / clean_fname

Function clean_fname

util1.c:960–1032  ·  view source on GitHub ↗

Turns multiple adjacent slashes into a single slash (possible exception: * the preserving of two leading slashes at the start), drops all leading or * interior "." elements unless CFN_KEEP_DOT_DIRS is flagged. Will also drop * a trailing '.' after a '/' if CFN_DROP_TRAILING_DOT_DIR is flagged, removes * a trailing slash (perhaps after removing the aforementioned dot) unless * CFN_KEEP_TRAILI

Source from the content-addressed store, hash-verified

958 * (except at the start) if CFN_COLLAPSE_DOT_DOT_DIRS is flagged. If the
959 * resulting name would be empty, returns ".". */
960int clean_fname(char *name, int flags)
961{
962 char *limit = name, *t = name, *f = name;
963 int anchored;
964
965 if (!name)
966 return 0;
967
968#define DOT_IS_DOT_DOT_DIR(bp) (bp[1] == '.' && (bp[2] == '/' || !bp[2]))
969
970 if ((anchored = *f == '/') != 0) {
971 *t++ = *f++;
972#ifdef __CYGWIN__
973 /* If there are exactly 2 slashes at the start, preserve
974 * them. Would break daemon excludes unless the paths are
975 * really treated differently, so used this sparingly. */
976 if (*f == '/' && f[1] != '/')
977 *t++ = *f++;
978#endif
979 } else if (flags & CFN_KEEP_DOT_DIRS && *f == '.' && f[1] == '/') {
980 *t++ = *f++;
981 *t++ = *f++;
982 } else if (flags & CFN_REFUSE_DOT_DOT_DIRS && *f == '.' && DOT_IS_DOT_DOT_DIR(f))
983 return -1;
984 while (*f) {
985 /* discard extra slashes */
986 if (*f == '/') {
987 f++;
988 continue;
989 }
990 if (*f == '.') {
991 /* discard interior "." dirs */
992 if (f[1] == '/' && !(flags & CFN_KEEP_DOT_DIRS)) {
993 f += 2;
994 continue;
995 }
996 if (f[1] == '\0' && flags & CFN_DROP_TRAILING_DOT_DIR)
997 break;
998 /* collapse ".." dirs */
999 if (flags & (CFN_COLLAPSE_DOT_DOT_DIRS|CFN_REFUSE_DOT_DOT_DIRS) && DOT_IS_DOT_DOT_DIR(f)) {
1000 char *s = t - 1;
1001 if (flags & CFN_REFUSE_DOT_DOT_DIRS)
1002 return -1;
1003 if (s == name && anchored) {
1004 f += 2;
1005 continue;
1006 }
1007 /* backing up for ".." — avoid reading before 'name' */
1008 while (s > limit && s[-1] != '/')
1009 s--;
1010
1011 /* If found prior '/', or we reached the start, adjust t. */
1012 if (s != t - 1 && (s <= name || *s == '/')) {
1013 t = (s == name) ? name : s + 1;
1014 f += 2;
1015 continue;
1016 }
1017 limit = t + 2;

Callers 12

parse_argumentsFunction · 0.85
log_formattedFunction · 0.85
parse_merge_nameFunction · 0.85
set_filter_dirFunction · 0.85
setup_merge_fileFunction · 0.85
parse_filter_fileFunction · 0.85
glob_expandFunction · 0.85
change_dirFunction · 0.85
normalize_pathFunction · 0.85
recv_file_entryFunction · 0.85
make_fileFunction · 0.85
send_file_listFunction · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected