]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/findlib/find_one.c
Update running status
[bacula/bacula] / bacula / src / findlib / find_one.c
index 3a62a6b766cc26bd47bf0fbeffb2bfc2c423a287..d80036fb2309d3b80d8c95ece3bfd8b28364163e 100755 (executable)
@@ -1,5 +1,5 @@
 /* 
-   Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+   Copyright (C) 2000-2003 Kern Sibbald and John Walker
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    MA 02111-1307, USA.
 
    This file is based on GNU TAR source code. Except for a few key
-   ideas and some key snippets of code, it has been rewritten for Bacula.
+   ideas, it has been rewritten for Bacula.
 
       Kern Sibbald, MM
 
-   Many thanks to the TAR programmers.
+   Thanks to the TAR programmers.
 
  */
 
 #include "bacula.h"
 #include "find.h"
-/*#include "system.h" */
 
 
 extern size_t name_max;              /* filename max length */
@@ -53,11 +52,10 @@ struct f_link {
 #if HAVE_UTIME_H
 # include <utime.h>
 #else
-struct utimbuf
-  {
+struct utimbuf {
     long actime;
     long modtime;
-  };
+};
 #endif
 
 
@@ -70,19 +68,13 @@ struct utimbuf
  *  decending into a directory.
  */
 int
-find_one_file(FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), void *pkt
-              char *fname, dev_t parent_device, int top_level)
+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)
 {
    struct utimbuf restore_times;
    int rtn_stat;
 
    ff_pkt->fname = ff_pkt->link = fname;
-   if (ff_pkt->compute_MD5) {
-      ff_pkt->flags |= FO_MD5;
-   }
-   if (ff_pkt->GZIP_compression) {
-      ff_pkt->flags |= FO_GZIP;
-   }
 
    if (lstat(fname, &ff_pkt->statp) != 0) {
        /* Cannot stat file */
@@ -149,7 +141,7 @@ find_one_file(FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), void *pkt
 
        struct f_link *lp;
 
-       /* keep linked list of files */
+       /* 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;
@@ -158,10 +150,10 @@ find_one_file(FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), void *pkt
          }
 
        /* File not previously dumped. Chain it into our list. */
-       lp = (struct f_link *)bmalloc(sizeof (struct f_link) + strlen(fname));
+       lp = (struct f_link *)bmalloc(sizeof(struct f_link) + strlen(fname) +1);
        lp->ino = ff_pkt->statp.st_ino;
        lp->dev = ff_pkt->statp.st_dev;
-       strcpy (lp->name, fname);
+       strcpy(lp->name, fname);
        lp->next = ff_pkt->linklist;
        ff_pkt->linklist = lp;
    }
@@ -184,9 +176,9 @@ find_one_file(FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), void *pkt
 
    } else if (S_ISLNK(ff_pkt->statp.st_mode)) {
        int size;
-       char *buffer = (char *)alloca(PATH_MAX + 1);
+       char *buffer = (char *)alloca(path_max + name_max + 2);
 
-       size = readlink(fname, buffer, PATH_MAX + 1);
+       size = readlink(fname, buffer, path_max + name_max + 1);
        if (size < 0) {
           /* Could not follow link */                             
           ff_pkt->type = FT_NOFOLLOW;
@@ -201,9 +193,9 @@ find_one_file(FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), void *pkt
    } else if (S_ISDIR(ff_pkt->statp.st_mode)) {
        DIR *directory;
        struct dirent *entry, *result;
-       char *namebuf;
-       size_t namebuf_len;
-       size_t len;
+       char *link;
+       int link_len;
+       int len;
        int status;
        dev_t our_device = ff_pkt->statp.st_dev;
 
@@ -216,15 +208,16 @@ find_one_file(FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), void *pkt
 
        /* Build a canonical directory name with a trailing slash. */
        len = strlen(fname);
-       namebuf_len = len + DEFAULT_NAMEBUF_LEN;
-       namebuf = (char *)bmalloc(namebuf_len + 2);
-       strncpy(namebuf, fname, namebuf_len);
-       while (len >= 1 && namebuf[len - 1] == '/')
+       link_len = len + 200;
+       link = (char *)bmalloc(link_len + 2);
+       bstrncpy(link, fname, link_len);
+       /* Strip all trailing slashes */
+       while (len >= 1 && link[len - 1] == '/')
         len--;
-       namebuf[len++] = '/';
-       namebuf[len] = '\0';
+       link[len++] = '/';             /* add back one */
+       link[len] = 0;
 
-       ff_pkt->link = namebuf;
+       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)) {
@@ -241,8 +234,8 @@ find_one_file(FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), void *pkt
        * Do not decend into subdirectories (recurse) if the
        * user has turned it off for this directory.
        */
-       if (ff_pkt->no_recursion) {
-         free(namebuf);
+       if (ff_pkt->flags & FO_NO_RECURSION) {
+         free(link);
          /* No recursion into this directory */
          ff_pkt->type = FT_NORECURSE;
          return handle_file(ff_pkt, pkt);
@@ -252,19 +245,19 @@ find_one_file(FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), void *pkt
        * See if we are crossing file systems, and
        * avoid doing so if the user only wants to dump one file system.
        */
-       if (ff_pkt->one_file_system && !top_level
-          && parent_device != ff_pkt->statp.st_dev) {
-         free(namebuf);
+       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;
          return handle_file(ff_pkt, pkt);
        }
-
        /* 
        * Now process the files in this directory.
        */
        errno = 0;
        if ((directory = opendir(fname)) == NULL) {
-         free(namebuf);
+         free(link);
          ff_pkt->type = FT_NOOPEN;
          ff_pkt->ff_errno = errno;
          return handle_file(ff_pkt, pkt);
@@ -275,16 +268,19 @@ find_one_file(FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), void *pkt
        * before traversing it.
        */
        rtn_stat = 1;
-       entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 10);
-       for ( ;; ) {
-          char *p;
+       entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 100);
+       for ( ; !job_cancelled(jcr); ) {
+          char *p, *q;
+          int i;
 
           status  = readdir_r(directory, entry, &result);
+          sm_check(__FILE__, __LINE__, False);
            Dmsg3(200, "readdir stat=%d result=%x name=%s\n", status, result,
              entry->d_name);
           if (status != 0 || result == NULL) {
              break;
           }
+          ASSERT(name_max+1 > sizeof(struct dirent) + (int)NAMELEN(entry));
           p = entry->d_name;
            /* Skip `.', `..', and excluded file names.  */
            if (p[0] == '\0' || (p[0] == '.' && (p[1] == '\0' ||
@@ -292,32 +288,51 @@ find_one_file(FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), void *pkt
              continue;
           }
 
-          if ((int)NAMELEN(entry) + len >= namebuf_len) {
-              namebuf_len = len + NAMELEN(entry);
-              namebuf = (char *)brealloc(namebuf, namebuf_len + 2);
+          if ((int)NAMELEN(entry) + len >= link_len) {
+              link_len = len + NAMELEN(entry) + 1;
+              link = (char *)brealloc(link, link_len + 1);
           }
-          strcpy(namebuf + len, entry->d_name);
-          if (!file_is_excluded(ff_pkt, namebuf)) {
-             rtn_stat = find_one_file(ff_pkt, handle_file, pkt, namebuf, our_device, 0);
+          q = link + len;
+          for (i=0; i < (int)NAMELEN(entry); i++) {
+             *q++ = *p++;
+          }
+          *q = 0;
+          sm_check(__FILE__, __LINE__, False);
+          if (!file_is_excluded(ff_pkt, link)) {
+             rtn_stat = find_one_file(jcr, ff_pkt, handle_file, pkt, link, our_device, 0);
           }
        }
        closedir(directory);
-       free(namebuf);
+       free(link);
        free(entry);
+
        if (ff_pkt->atime_preserve) {
          utime(fname, &restore_times);
        }
        return rtn_stat;
    } /* end check for directory */
 
-   /* The only remaining types are special (character, ...) files */
-   ff_pkt->type = FT_SPEC;
+   /*
+    * If it is explicitly mentioned (i.e. top_level) and is
+    *  a block device, we do a raw backup of it or if it is
+    *  a fifo, we simply read it.
+    */
+   if (top_level && S_ISBLK(ff_pkt->statp.st_mode)) {
+      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->type = FT_FIFO;
+   } else {
+      /* The only remaining types are special (character, ...) files */
+      ff_pkt->type = FT_SPEC;
+   }
    return handle_file(ff_pkt, pkt);
 }
 
-void term_find_one(FF_PKT *ff)
+int term_find_one(FF_PKT *ff)
 {
    struct f_link *lp, *lc;
+   int count = 0;
   
    /* Free up list of hard linked files */
    for (lp = ff->linklist; lp;) {
@@ -325,7 +340,8 @@ void term_find_one(FF_PKT *ff)
       lp = lp->next;
       if (lc) {
         free(lc);
+        count++;
       }
    }
-   return;
+   return count;
 }