Optimize --inplace chunck search to avoid a non-aligned search.
[rsync/rsync.git] / loadparm.c
index 905a910..10c3345 100644 (file)
@@ -54,7 +54,8 @@ extern item_list dparam_list;
 #endif
 
 #define DEFAULT_DONT_COMPRESS "*.gz *.zip *.z *.rpm *.deb *.iso *.bz2" \
-       " *.t[gb]z *.7z *.mp[34] *.mov *.avi *.ogg *.jpg *.jpeg"
+       " *.t[gb]z *.7z *.mp[34] *.mov *.avi *.ogg *.jpg *.jpeg *.png" \
+       " *.lzo *.rzip *.lzma *.rar *.ace *.gpg *.xz *.txz *.lz *.tlz"
 
 /* the following are used by loadparm for option lists */
 typedef enum {
@@ -89,9 +90,7 @@ struct parm_struct {
 #define LP_SNUM_OK(i) ((i) >= 0 && (i) < (int)section_list.count)
 #define SECTION_PTR(s, p) (((char*)(s)) + (ptrdiff_t)(((char*)(p))-(char*)&Vars.l))
 
-/*
- * This structure describes global (ie., server-wide) parameters.
- */
+/* This structure describes global (ie., server-wide) parameters. */
 typedef struct {
        char *bind_address;
        char *motd_file;
@@ -101,11 +100,10 @@ typedef struct {
        int rsync_port;
 } global_vars;
 
-/*
- * This structure describes a single section.  Their order must match the
+/* This structure describes a single section.  Their order must match the
  * initializers below, which you can accomplish by keeping each sub-section
  * sorted.  (e.g. in vim, just visually select each subsection and use !sort.)
- */
+ * NOTE: the char* variables MUST all remain at the start of the stuct! */
 typedef struct {
        char *auth_users;
        char *charset;
@@ -132,6 +130,8 @@ typedef struct {
        char *secrets_file;
        char *temp_dir;
        char *uid;
+/* NOTE: update this macro if the last char* variable changes! */
+#define LOCAL_STRING_COUNT() (offsetof(local_vars, uid) / sizeof (char*) + 1)
 
        int max_connections;
        int max_verbosity;
@@ -186,7 +186,7 @@ static const all_vars Defaults = {
  /* exclude; */                        NULL,
  /* exclude_from; */           NULL,
  /* filter; */                 NULL,
- /* gid; */                    NOBODY_GROUP,
+ /* gid; */                    NULL,
  /* hosts_allow; */            NULL,
  /* hosts_deny; */             NULL,
  /* include; */                        NULL,
@@ -203,7 +203,7 @@ static const all_vars Defaults = {
  /* refuse_options; */         NULL,
  /* secrets_file; */           NULL,
  /* temp_dir; */               NULL,
- /* uid; */                    NOBODY_USER,
+ /* uid; */                    NULL,
 
  /* max_connections; */                0,
  /* max_verbosity; */          1,
@@ -366,11 +366,61 @@ static void reset_all_vars(void)
        memcpy(&Vars, &Defaults, sizeof Vars);
 }
 
+/* Expand %VAR% references.  Any unknown vars or unrecognized
+ * syntax leaves the raw chars unchanged. */
+static char *expand_vars(char *str)
+{
+       char *buf, *t, *f;
+       int bufsize;
+
+       if (strchr(str, '%') == NULL)
+               return str;
+
+       bufsize = strlen(str) + 2048;
+       if ((buf = new_array(char, bufsize+1)) == NULL) /* +1 for trailing '\0' */
+               out_of_memory("expand_vars");
+
+       for (t = buf, f = str; bufsize && *f; ) {
+               if (*f == '%' && *++f != '%') {
+                       char *percent = strchr(f, '%');
+                       if (percent) {
+                               char *val;
+                               *percent = '\0';
+                               val = getenv(f);
+                               *percent = '%';
+                               if (val) {
+                                       int len = strlcpy(t, val, bufsize+1);
+                                       if (len > bufsize)
+                                               break;
+                                       bufsize -= len;
+                                       t += len;
+                                       f = percent + 1;
+                                       continue;
+                               }
+                       }
+                       f--;
+               }
+               *t++ = *f++;
+               bufsize--;
+       }
+       *t = '\0';
+
+       if (*f) {
+               rprintf(FLOG, "Overflowed buf in expand_vars() trying to expand: %s\n", str);
+               exit_cleanup(RERR_MALLOC);
+       }
+
+       if (bufsize && (buf = realloc(buf, t - buf + 1)) == NULL)
+               out_of_memory("expand_vars");
+
+       return buf;
+}
+
 /* In this section all the functions that are used to access the
  * parameters from the rest of the program are defined. */
 
 #define FN_GLOBAL_STRING(fn_name, ptr) \
- char *fn_name(void) {return *(char **)(ptr) ? *(char **)(ptr) : "";}
+ char *fn_name(void) {return expand_vars(*(char **)(ptr) ? *(char **)(ptr) : "");}
 #define FN_GLOBAL_BOOL(fn_name, ptr) \
  BOOL fn_name(void) {return *(BOOL *)(ptr);}
 #define FN_GLOBAL_CHAR(fn_name, ptr) \
@@ -379,7 +429,7 @@ static void reset_all_vars(void)
  int fn_name(void) {return *(int *)(ptr);}
 
 #define FN_LOCAL_STRING(fn_name, val) \
- char *fn_name(int i) {return LP_SNUM_OK(i) && iSECTION(i).val? iSECTION(i).val : (Vars.l.val? Vars.l.val : "");}
+ char *fn_name(int i) {return expand_vars(LP_SNUM_OK(i) && iSECTION(i).val ? iSECTION(i).val : Vars.l.val ? Vars.l.val : "");}
 #define FN_LOCAL_BOOL(fn_name, val) \
  BOOL fn_name(int i) {return LP_SNUM_OK(i)? iSECTION(i).val : Vars.l.val;}
 #define FN_LOCAL_CHAR(fn_name, val) \
@@ -438,62 +488,31 @@ FN_LOCAL_BOOL(lp_transfer_logging, transfer_logging)
 FN_LOCAL_BOOL(lp_use_chroot, use_chroot)
 FN_LOCAL_BOOL(lp_write_only, write_only)
 
-/* Assign a copy of v to *s.  Handles NULL strings.  *v must
- * be initialized when this is called, either to NULL or a malloc'd
- * string.
- *
- * FIXME There is a small leak here in that sometimes the existing
- * value will be dynamically allocated, and the old copy is lost.
- * However, we can't always deallocate the old value, because the
- * initial values in Defaults.l are static strings.  It would be nice
- * to have either all-strdup'd values, or to never need to free
- * memory. */
-static void string_set(char **s, const char *v)
+/* Assign a copy of v to *s.  Handles NULL strings.  We don't worry
+ * about overwriting a malloc'd string because the long-running
+ * (port-listening) daemon only loads the config file once, and the
+ * per-job (forked or xinitd-ran) daemon only re-reads the file at
+ * the start, so any lost memory is inconsequential. */
+static inline void string_set(char **s, const char *v)
 {
-       if (!v) {
+       if (!v)
                *s = NULL;
-               return;
-       }
-       if (!(*s = strdup(v)))
+       else if (!(*s = strdup(v)))
                out_of_memory("string_set");
 }
 
-/* Copy the local_vars, duplicating any strings in the source. */
+/* Copy the local_vars, strdup'ing any strings.  NOTE:  this depends on
+ * the structure starting with a contiguous list of the char* variables,
+ * and having an accurate count in the LOCAL_STRING_COUNT() macro. */
 static void copy_section(local_vars *psectionDest, local_vars *psectionSource)
 {
-       int i;
-
-       for (i = 0; parm_table[i].label; i++) {
-               if (parm_table[i].ptr && parm_table[i].class == P_LOCAL) {
-                       void *def_ptr = parm_table[i].ptr;
-                       void *src_ptr = SECTION_PTR(psectionSource, def_ptr);
-                       void *dest_ptr = SECTION_PTR(psectionDest, def_ptr);
+       int count = LOCAL_STRING_COUNT();
+       char **strings = (char**)psectionDest;
 
-                       switch (parm_table[i].type) {
-                       case P_BOOL:
-                       case P_BOOLREV:
-                               *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
-                               break;
-
-                       case P_INTEGER:
-                       case P_ENUM:
-                       case P_OCTAL:
-                               *(int *)dest_ptr = *(int *)src_ptr;
-                               break;
-
-                       case P_CHAR:
-                               *(char *)dest_ptr = *(char *)src_ptr;
-                               break;
-
-                       case P_PATH:
-                       case P_STRING:
-                               string_set(dest_ptr, *(char **)src_ptr);
-                               break;
-
-                       default:
-                               break;
-                       }
-               }
+       memcpy(psectionDest, psectionSource, sizeof psectionDest[0]);
+       while (count--) {
+               if (strings[count] && !(strings[count] = strdup(strings[count])))
+                       out_of_memory("copy_section");
        }
 }
 
@@ -634,6 +653,17 @@ static BOOL do_parameter(char *parmname, char *parmvalue)
        }
 
        /* now switch on the type of variable it is */
+       switch (parm_table[parmnum].type) {
+       case P_PATH:
+       case P_STRING:
+               /* delay expansion of vars */
+               break;
+       default:
+               /* expand any %VARS% now */
+               parmvalue = expand_vars(parmvalue);
+               break;
+       }
+
        switch (parm_table[parmnum].type) {
        case P_BOOL:
                set_boolean(parm_ptr, parmvalue);