]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/findlib/find_one.c
mtimeonly and keepatime in Include + first cut disk seeking + test win32 installer
[bacula/bacula] / bacula / src / findlib / find_one.c
index 8d3bf5e3b4d160962c3a0a4af062aff2384df862..cc3f5be47ca5fd9666c22888bfa90f7194a9a482 100755 (executable)
@@ -28,8 +28,8 @@
 #include "bacula.h"
 #include "find.h"
 
-extern size_t name_max;              /* filename max length */
-extern size_t path_max;              /* path name max length */
+extern int32_t name_max;              /* filename max length */
+extern int32_t path_max;              /* path name max length */
 
 /*
  * Structure for keeping track of hard linked files, we   
@@ -40,15 +40,23 @@ extern size_t path_max;           /* path name max length */
  */
 struct f_link {
     struct f_link *next;
-    dev_t dev;                       /* device */
-    ino_t ino;                       /* inode with device is unique */
+    dev_t dev;                        /* device */
+    ino_t ino;                        /* inode with device is unique */
     short linkcount;
-    uint32_t FileIndex;              /* Bacula FileIndex of this file */
-    char name[1];                    /* The name */
+    uint32_t FileIndex;               /* Bacula FileIndex of this file */
+    char name[1];                     /* The name */
 };
 
+static void free_dir_ff_pkt(FF_PKT *dir_ff_pkt)
+{
+   free(dir_ff_pkt->fname);
+   free(dir_ff_pkt->link);
+   free_pool_memory(dir_ff_pkt->sys_fname);
+   free(dir_ff_pkt);
+}
+
 /*
- * Find a single file.                       
+ * Find a single file.                        
  * handle_file is the callback for handling the file.
  * p is the filename
  * parent_device is the device we are currently on 
@@ -57,7 +65,7 @@ struct f_link {
  */
 int
 find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), 
-              void *pkt, char *fname, dev_t parent_device, int top_level)
+               void *pkt, char *fname, dev_t parent_device, int top_level)
 {
    struct utimbuf restore_times;
    int rtn_stat;
@@ -89,11 +97,11 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
       Dmsg1(300, "Non-directory incremental: %s\n", ff_pkt->fname);
       /* Not a directory */
       if (ff_pkt->statp.st_mtime < ff_pkt->save_time
-         && (ff_pkt->mtime_only || 
-             ff_pkt->statp.st_ctime < ff_pkt->save_time)) {
-        /* Incremental option, file not changed */
-        ff_pkt->type = FT_NOCHG;
-        return handle_file(ff_pkt, pkt);
+          && ((ff_pkt->flags & FO_MTIMEONLY) || 
+              ff_pkt->statp.st_ctime < ff_pkt->save_time)) {
+         /* Incremental option, file not changed */
+         ff_pkt->type = FT_NOCHG;
+         return handle_file(ff_pkt, pkt);
       }
    }
 
@@ -115,21 +123,21 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
     */
    if (ff_pkt->statp.st_nlink > 1
        && (S_ISREG(ff_pkt->statp.st_mode)
-          || S_ISCHR(ff_pkt->statp.st_mode)
-          || S_ISBLK(ff_pkt->statp.st_mode)
-          || S_ISFIFO(ff_pkt->statp.st_mode)
-          || S_ISSOCK(ff_pkt->statp.st_mode))) {
+           || S_ISCHR(ff_pkt->statp.st_mode)
+           || S_ISBLK(ff_pkt->statp.st_mode)
+           || S_ISFIFO(ff_pkt->statp.st_mode)
+           || S_ISSOCK(ff_pkt->statp.st_mode))) {
 
        struct f_link *lp;
 
       /* Search link list of hard linked files */
       for (lp = ff_pkt->linklist; lp; lp = lp->next)
-        if (lp->ino == ff_pkt->statp.st_ino && lp->dev == ff_pkt->statp.st_dev) {
-            ff_pkt->link = lp->name;
-            ff_pkt->type = FT_LNKSAVED;       /* Handle link, file already saved */
-            ff_pkt->LinkFI = lp->FileIndex;
-            return handle_file(ff_pkt, pkt);
-        }
+         if (lp->ino == ff_pkt->statp.st_ino && lp->dev == ff_pkt->statp.st_dev) {
+             ff_pkt->link = lp->name;
+             ff_pkt->type = FT_LNKSAVED;       /* Handle link, file already saved */
+             ff_pkt->LinkFI = lp->FileIndex;
+             return handle_file(ff_pkt, pkt);
+         }
 
       /* File not previously dumped. Chain it into our list. */
       lp = (struct f_link *)bmalloc(sizeof(struct f_link) + strlen(fname) +1);
@@ -138,7 +146,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
       strcpy(lp->name, fname);
       lp->next = ff_pkt->linklist;
       ff_pkt->linklist = lp;
-      ff_pkt->linked = lp;           /* mark saved link */
+      ff_pkt->linked = lp;            /* mark saved link */
    } else {
       ff_pkt->linked = NULL;
    }
@@ -150,16 +158,16 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
       sizeleft = ff_pkt->statp.st_size;
 
       /* Don't bother opening empty, world readable files.  Also do not open
-        files when archive is meant for /dev/null.  */
+         files when archive is meant for /dev/null.  */
       if (ff_pkt->null_output_device || (sizeleft == 0
-             && MODE_RALL == (MODE_RALL & ff_pkt->statp.st_mode))) {
-        ff_pkt->type = FT_REGE;
+              && MODE_RALL == (MODE_RALL & ff_pkt->statp.st_mode))) {
+         ff_pkt->type = FT_REGE;
       } else {
-        ff_pkt->type = FT_REG;
+         ff_pkt->type = FT_REG;
       }
       rtn_stat = handle_file(ff_pkt, pkt);
       if (ff_pkt->linked) {
-        ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
+         ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
       }
       return rtn_stat;
 
@@ -170,21 +178,21 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
 
       size = readlink(fname, buffer, path_max + name_max + 101);
       if (size < 0) {
-        /* Could not follow link */                             
-        ff_pkt->type = FT_NOFOLLOW;
-        ff_pkt->ff_errno = errno;
-        rtn_stat = handle_file(ff_pkt, pkt);
-        if (ff_pkt->linked) {
-           ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
-        }
-        return rtn_stat;
+         /* Could not follow link */                             
+         ff_pkt->type = FT_NOFOLLOW;
+         ff_pkt->ff_errno = errno;
+         rtn_stat = handle_file(ff_pkt, pkt);
+         if (ff_pkt->linked) {
+            ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
+         }
+         return rtn_stat;
       }
       buffer[size] = 0;
-      ff_pkt->link = buffer;         /* point to link */
-      ff_pkt->type = FT_LNK;         /* got a real link */
+      ff_pkt->link = buffer;          /* point to link */
+      ff_pkt->type = FT_LNK;          /* got a real link */
       rtn_stat = handle_file(ff_pkt, pkt);
       if (ff_pkt->linked) {
-        ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
+         ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
       }
       return rtn_stat;
 
@@ -193,19 +201,26 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
       struct dirent *entry, *result;
       char *link;
       int link_len;
-      int len;  
+      int len;   
       int status;
       dev_t our_device = ff_pkt->statp.st_dev;
 
-      if (access(fname, R_OK) == -1 && geteuid() != 0) {
-        /* Could not access() directory */
-        ff_pkt->type = FT_NOACCESS;
-        ff_pkt->ff_errno = errno;
-        rtn_stat = handle_file(ff_pkt, pkt);
-        if (ff_pkt->linked) {
-           ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
-        }
-        return rtn_stat;
+      /*  
+       * If we are using Win32 (non-portable) backup API, don't check
+       *  access as everything is more complicated, and
+       *  in principle, we should be able to access everything.
+       */
+      if (!have_win32_api() || (ff_pkt->flags & FO_PORTABLE)) {
+         if (access(fname, R_OK) == -1 && geteuid() != 0) {
+            /* Could not access() directory */
+            ff_pkt->type = FT_NOACCESS;
+            ff_pkt->ff_errno = errno;
+            rtn_stat = handle_file(ff_pkt, pkt);
+            if (ff_pkt->linked) {
+               ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
+            }
+            return rtn_stat;
+         }
       }
 
       /* Build a canonical directory name with a trailing slash in link var */
@@ -215,25 +230,39 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
       bstrncpy(link, fname, link_len);
       /* Strip all trailing slashes */
       while (len >= 1 && link[len - 1] == '/')
-       len--;
+        len--;
       link[len++] = '/';             /* add back one */
       link[len] = 0;
 
       ff_pkt->link = link;
       if (ff_pkt->incremental &&
-         (ff_pkt->statp.st_mtime < ff_pkt->save_time &&
-          ff_pkt->statp.st_ctime < ff_pkt->save_time)) {
-        /* Incremental option, directory entry not changed */
-        ff_pkt->type = FT_DIRNOCHG;
+          (ff_pkt->statp.st_mtime < ff_pkt->save_time &&
+           ff_pkt->statp.st_ctime < ff_pkt->save_time)) {
+         /* Incremental option, directory entry not changed */
+         ff_pkt->type = FT_DIRNOCHG;
       } else {
-        ff_pkt->type = FT_DIR;
+         ff_pkt->type = FT_DIR;
       }
-      FF_PKT *dir_ff_pkt;
-      dir_ff_pkt = (FF_PKT *)bmalloc(sizeof(FF_PKT));
+
+      /*
+       * Create a temporary ff packet for this directory
+       *   entry, and defer handling the directory until
+       *   we have recursed into it.  This saves the
+       *   directory after all files have been processed, and
+       *   during the restore, the directory permissions will
+       *   be reset after all the files have been restored.
+       */
+      Dmsg1(300, "Create temp ff packet for dir: %s\n", ff_pkt->fname);
+      FF_PKT *dir_ff_pkt = (FF_PKT *)bmalloc(sizeof(FF_PKT));
       memcpy(dir_ff_pkt, ff_pkt, sizeof(FF_PKT));
       dir_ff_pkt->fname = bstrdup(ff_pkt->fname);
       dir_ff_pkt->link = bstrdup(ff_pkt->link);
-       
+      dir_ff_pkt->sys_fname = get_pool_memory(PM_FNAME);
+      dir_ff_pkt->included_files_list = NULL;
+      dir_ff_pkt->excluded_files_list = NULL;
+      dir_ff_pkt->excluded_paths_list = NULL;
+      dir_ff_pkt->linklist = NULL;
+        
       ff_pkt->link = ff_pkt->fname;     /* reset "link" */
 
       /* 
@@ -241,17 +270,15 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
        * user has turned it off for this directory.
        */
       if (ff_pkt->flags & FO_NO_RECURSION) {
-        free(link);
-        /* No recursion into this directory */
-        ff_pkt->type = FT_NORECURSE;
-        rtn_stat = handle_file(ff_pkt, pkt);
-        if (ff_pkt->linked) {
-           ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
-        }
-        free(dir_ff_pkt->fname);
-        free(dir_ff_pkt->link);
-        free(dir_ff_pkt);
-        return rtn_stat;
+         /* No recursion into this directory */
+         ff_pkt->type = FT_NORECURSE;
+         rtn_stat = handle_file(ff_pkt, pkt);
+         if (ff_pkt->linked) {
+            ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
+         }
+         free(link);
+         free_dir_ff_pkt(dir_ff_pkt);
+         return rtn_stat;
       }
 
       /* 
@@ -259,35 +286,32 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
        * avoid doing so if the user only wants to dump one file system.
        */
       if (!top_level && !(ff_pkt->flags & FO_MULTIFS) &&
-          parent_device != ff_pkt->statp.st_dev) {
-        free(link);
-        /* returning here means we do not handle this directory */
-        ff_pkt->type = FT_NOFSCHG;
-        rtn_stat = handle_file(ff_pkt, pkt);
-        if (ff_pkt->linked) {
-           ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
-        }
-        free(dir_ff_pkt->fname);
-        free(dir_ff_pkt->link);
-        free(dir_ff_pkt);
-        return rtn_stat;
+           parent_device != ff_pkt->statp.st_dev) {
+         /* returning here means we do not handle this directory */
+         ff_pkt->type = FT_NOFSCHG;
+         rtn_stat = handle_file(ff_pkt, pkt);
+         if (ff_pkt->linked) {
+            ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
+         }
+         free(link);
+         free_dir_ff_pkt(dir_ff_pkt);
+         return rtn_stat;
       }
       /* 
-       * Open directory for reading files within 
+       * Decend into or "recurse" into the directory to read
+       *   all the files in it.
        */
       errno = 0;
       if ((directory = opendir(fname)) == NULL) {
-        free(link);
-        ff_pkt->type = FT_NOOPEN;
-        ff_pkt->ff_errno = errno;
-        rtn_stat = handle_file(ff_pkt, pkt);
-        if (ff_pkt->linked) {
-           ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
-        }
-        free(dir_ff_pkt->fname);
-        free(dir_ff_pkt->link);
-        free(dir_ff_pkt);
-        return rtn_stat;
+         ff_pkt->type = FT_NOOPEN;
+         ff_pkt->ff_errno = errno;
+         rtn_stat = handle_file(ff_pkt, pkt);
+         if (ff_pkt->linked) {
+            ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
+         }
+         free(link);
+         free_dir_ff_pkt(dir_ff_pkt);
+         return rtn_stat;
       }
 
       /*
@@ -298,36 +322,38 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
       rtn_stat = 1;
       entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 100);
       for ( ; !job_canceled(jcr); ) {
-        char *p, *q;
-        int i;
-
-        status  = readdir_r(directory, entry, &result);
-        if (status != 0 || result == NULL) {
-           break;
-        }
-        ASSERT(name_max+1 > sizeof(struct dirent) + (int)NAMELEN(entry));
-        p = entry->d_name;
+         char *p, *q;
+         int i;
+
+         status  = readdir_r(directory, entry, &result);
+         if (status != 0 || result == NULL) {
+//          Dmsg2(99, "readdir returned stat=%d result=0x%x\n",
+//             status, (long)result);
+            break;
+         }
+         ASSERT(name_max+1 > (int)sizeof(struct dirent) + (int)NAMELEN(entry));
+         p = entry->d_name;
          /* Skip `.', `..', and excluded file names.  */
          if (p[0] == '\0' || (p[0] == '.' && (p[1] == '\0' ||
              (p[1] == '.' && p[2] == '\0')))) {
-           continue;
-        }
-
-        if ((int)NAMELEN(entry) + len >= link_len) {
-            link_len = len + NAMELEN(entry) + 1;
-            link = (char *)brealloc(link, link_len + 1);
-        }
-        q = link + len;
-        for (i=0; i < (int)NAMELEN(entry); i++) {
-           *q++ = *p++;
-        }
-        *q = 0;
-        if (!file_is_excluded(ff_pkt, link)) {
-           rtn_stat = find_one_file(jcr, ff_pkt, handle_file, pkt, link, our_device, 0);
-           if (ff_pkt->linked) {
-              ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
-           }
-        }
+            continue;
+         }
+
+         if ((int)NAMELEN(entry) + len >= link_len) {
+             link_len = len + NAMELEN(entry) + 1;
+             link = (char *)brealloc(link, link_len + 1);
+         }
+         q = link + len;
+         for (i=0; i < (int)NAMELEN(entry); i++) {
+            *q++ = *p++;
+         }
+         *q = 0;
+         if (!file_is_excluded(ff_pkt, link)) {
+            rtn_stat = find_one_file(jcr, ff_pkt, handle_file, pkt, link, our_device, 0);
+            if (ff_pkt->linked) {
+               ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
+            }
+         }
       }
       closedir(directory);
       free(link);
@@ -340,16 +366,14 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
        *  the directory modes and dates.  Temp directory values
        *  were used without this record.
        */
-      handle_file(dir_ff_pkt, pkt);      /* handle directory entry */
+      handle_file(dir_ff_pkt, pkt);       /* handle directory entry */
       if (ff_pkt->linked) {
-        ff_pkt->linked->FileIndex = dir_ff_pkt->FileIndex;
+         ff_pkt->linked->FileIndex = dir_ff_pkt->FileIndex;
       }
-      free(dir_ff_pkt->fname);
-      free(dir_ff_pkt->link);
-      free(dir_ff_pkt);
+      free_dir_ff_pkt(dir_ff_pkt);
 
-      if (ff_pkt->atime_preserve) {
-        utime(fname, &restore_times);
+      if (ff_pkt->flags & FO_KEEPATIME) {
+         utime(fname, &restore_times);
       }
       return rtn_stat;
    } /* end check for directory */
@@ -359,10 +383,21 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
     *  a block device, we do a raw backup of it or if it is
     *  a fifo, we simply read it.
     */
+#ifdef HAVE_FREEBSD_OS
+   /*
+    * On FreeBSD, all block devices are character devices, so
+    *   to be able to read a raw disk, we need the check for
+    *   a character device.
+    * crw-r-----  1 root  operator  - 116, 0x00040002 Jun  9 19:32 /dev/ad0s3
+    * crw-r-----  1 root  operator  - 116, 0x00040002 Jun  9 19:32 /dev/rad0s3
+    */
+   if (top_level && (S_ISBLK(ff_pkt->statp.st_mode) || S_ISCHR(ff_pkt->statp.st_mode))) {
+#else
    if (top_level && S_ISBLK(ff_pkt->statp.st_mode)) {
-      ff_pkt->type = FT_RAW;         /* raw partition */
+#endif
+      ff_pkt->type = FT_RAW;          /* raw partition */
    } else if (top_level && S_ISFIFO(ff_pkt->statp.st_mode) &&
-             ff_pkt->flags & FO_READFIFO) {
+              ff_pkt->flags & FO_READFIFO) {
       ff_pkt->type = FT_FIFO;
    } else {
       /* The only remaining types are special (character, ...) files */
@@ -385,8 +420,8 @@ int term_find_one(FF_PKT *ff)
       lc = lp;
       lp = lp->next;
       if (lc) {
-        free(lc);
-        count++;
+         free(lc);
+         count++;
       }
    }
    return count;