extern int module_id;
extern int modify_window;
extern char *partial_dir;
-extern struct exclude_list_struct server_exclude_list;
+extern struct filter_list_struct server_filter_list;
int sanitize_paths = 0;
int set_modtime(char *fname, time_t modtime)
{
- if (dry_run)
- return 0;
-
if (verbose > 2) {
rprintf(FINFO, "set modtime of %s to (%ld) %s",
fname, (long)modtime,
asctime(localtime(&modtime)));
}
+ if (dry_run)
+ return 0;
+
{
-#ifdef HAVE_UTIMBUF
+#if HAVE_UTIMBUF
struct utimbuf tbuf;
tbuf.actime = time(NULL);
tbuf.modtime = modtime;
return utime(fname,&tbuf);
-#elif defined(HAVE_UTIME)
+#elif HAVE_UTIME
time_t t[2];
t[0] = time(NULL);
t[1] = modtime;
*
* Derived from GNU C's cccp.c.
*/
-static int full_write(int desc, char *ptr, size_t len)
+int full_write(int desc, char *ptr, size_t len)
{
int total_written;
/** Copy a file.
*
- * This is used in conjunction with the --temp-dir option */
+ * This is used in conjunction with the --temp-dir and --backup options */
int copy_file(char *source, char *dest, mode_t mode)
{
int ifd;
return fcntl(fd,F_SETLK,&lock) == 0;
}
-static int exclude_server_path(char *arg)
+static int filter_server_path(char *arg)
{
char *s;
- if (server_exclude_list.head) {
+ if (server_filter_list.head) {
for (s = arg; (s = strchr(s, '/')) != NULL; ) {
*s = '\0';
- if (check_exclude(&server_exclude_list, arg, 1) < 0) {
+ if (check_filter(&server_filter_list, arg, 1) < 0) {
/* We must leave arg truncated! */
return 1;
}
char **argv = *argv_ptr;
int argc = *argc_ptr;
int maxargs = *maxargs_ptr;
-#if !(defined(HAVE_GLOB) && defined(HAVE_GLOB_H))
+#if !(HAVE_GLOB && HAVE_GLOB_H)
if (argc == maxargs) {
maxargs += MAX_ARGS;
if (!(argv = realloc_array(argv, char *, maxargs)))
if (!*s)
s = ".";
s = argv[argc++] = strdup(s);
- exclude_server_path(s);
+ filter_server_path(s);
#else
glob_t globbuf;
int i;
s = strdup(s);
memset(&globbuf, 0, sizeof globbuf);
- if (!exclude_server_path(s))
+ if (!filter_server_path(s))
glob(s, 0, NULL, &globbuf);
if (MAX((int)globbuf.gl_pathc, 1) > maxargs - argc) {
maxargs += globbuf.gl_pathc + MAX_ARGS;
return cnt;
}
-/* Turns multiple adjacent slashes into a single slash; gets rid of "./"
- * elements; collapses ".." elements except for those at the start of the
- * string; removes a trailing slash. If the resulting name would be empty,
- * change it into a ".". */
-unsigned int clean_fname(char *name)
+/* Turns multiple adjacent slashes into a single slash, gets rid of "./"
+ * elements (but not a trailing dot dir), removes a trailing slash, and
+ * optionally collapses ".." elements (except for those at the start of the
+ * string). If the resulting name would be empty, change it into a ".". */
+unsigned int clean_fname(char *name, BOOL collapse_dot_dot)
{
char *limit = name - 1, *t = name, *f = name;
int anchored;
continue;
}
/* collapse ".." dirs */
- if (f[1] == '.' && (f[2] == '/' || !f[2])) {
+ if (collapse_dot_dot
+ && f[1] == '.' && (f[2] == '/' || !f[2])) {
char *s = t - 1;
if (s == name && anchored) {
f += 2;
f += 2;
continue;
}
- *t++ = *f++;
- *t++ = *f++;
- limit = t;
+ limit = t + 2;
}
}
while (*f && (*t++ = *f++) != '/') {}
* The rootdir string contains a value to use in place of a leading slash.
* Specify NULL to get the default of lp_path(module_id).
*
- * If depth is > 0, it is a count of how many '..'s to allow at the start
- * of the path.
+ * If depth is >= 0, it is a count of how many '..'s to allow at the start
+ * of the path. Use -1 to allow unlimited depth.
*
- * We call clean_fname() to clean up the path, but we preserve a trailing
- * slash because that is sometimes significant on command-line arguments.
- */
+ * We also clean the path in a manner similar to clean_fname() but with a
+ * few differences:
+ *
+ * Turns multiple adjacent slashes into a single slash, gets rid of "." dir
+ * elements (INCLUDING a trailing dot dir), PRESERVES a trailing slash, and
+ * ALWAYS collapses ".." elements (except for those at the start of the
+ * string up to "depth" deep). If the resulting name would be empty,
+ * change it into a ".". */
char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth)
{
char *start, *sanp;
- int allowdotdot = 0;
int rlen = 0;
if (dest != p) {
}
start = sanp = dest + rlen;
- while (*p == '/') {
- /* remove leading slashes */
- p++;
- }
while (*p != '\0') {
+ /* discard leading or extra slashes */
+ if (*p == '/') {
+ p++;
+ continue;
+ }
/* this loop iterates once per filename component in p.
* both p (and sanp if the original had a slash) should
* always be left pointing after a slash
*/
if (*p == '.' && (p[1] == '/' || p[1] == '\0')) {
/* skip "." component */
- while (*++p == '/') {
- /* skip following slashes */
- ;
- }
+ p++;
continue;
}
- allowdotdot = 0;
if (*p == '.' && p[1] == '.' && (p[2] == '/' || p[2] == '\0')) {
/* ".." component followed by slash or end */
- if (depth > 0 && sanp == start) {
- /* allow depth levels of .. at the beginning */
- --depth;
- allowdotdot = 1;
- } else {
+ if (depth <= 0 || sanp != start) {
p += 2;
- while (*p == '/') p++;
if (sanp != start) {
/* back up sanp one level */
--sanp; /* now pointing at slash */
}
continue;
}
- }
- while (1) {
- /* copy one component through next slash */
- *sanp++ = *p++;
- if (*p == '\0' || p[-1] == '/') {
- while (*p == '/') {
- /* skip multiple slashes */
- p++;
- }
- break;
- }
- }
- if (allowdotdot) {
+ /* allow depth levels of .. at the beginning */
+ depth--;
/* move the virtual beginning to leave the .. alone */
- start = sanp;
+ start = sanp + 3;
}
+ /* copy one component through next slash */
+ while (*p && (*sanp++ = *p++) != '/') {}
}
if (sanp == dest) {
/* ended up with nothing, so put in "." component */
curr_dir_len += len;
}
- curr_dir_len = clean_fname(curr_dir);
+ curr_dir_len = clean_fname(curr_dir, 1);
return 1;
}
fn = fname;
if ((int)pathjoin(t, sz, partial_dir, fn) >= sz)
return NULL;
- if (server_exclude_list.head
- && check_exclude(&server_exclude_list, partial_fname, 0) < 0)
+ if (server_filter_list.head
+ && check_filter(&server_filter_list, partial_fname, 0) < 0)
return NULL;
return partial_fname;
dir = partial_fname;
if (create) {
STRUCT_STAT st;
-#if SUPPORT_LINKS
int statret = do_lstat(dir, &st);
-#else
- int statret = do_stat(dir, &st);
-#endif
if (statret == 0 && !S_ISDIR(st.st_mode)) {
if (do_unlink(dir) < 0)
return 0;
static char TimeBuf[200];
struct tm *tm = localtime(&t);
-#ifdef HAVE_STRFTIME
+#if HAVE_STRFTIME
strftime(TimeBuf, sizeof TimeBuf - 1, "%Y/%m/%d %H:%M:%S", tm);
#else
strlcpy(TimeBuf, asctime(tm), sizeof TimeBuf);