]> git.sur5r.net Git - bacula/bacula/commitdiff
kes Fix Win32 reparse points. Bacula will not recurse into any
authorKern Sibbald <kern@sibbald.com>
Wed, 21 May 2008 11:59:00 +0000 (11:59 +0000)
committerKern Sibbald <kern@sibbald.com>
Wed, 21 May 2008 11:59:00 +0000 (11:59 +0000)
     reparse point directory, including mount points, unless the
     directory is explicitly mentioned at the top level (same as
     with Unix).  A file that is linked to another file will be
     backed up -- much as Unix does for hardlinked files.
     This *should* fix bug #1041.

git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/branches/Branch-2.2@7001 91ce42f0-d328-0410-95d8-f526ca767f89

bacula/src/baconfig.h
bacula/src/findlib/find_one.c
bacula/src/version.h
bacula/src/win32/compat/compat.cpp
bacula/technotes-2.1

index f5b0282da7df3c2f569cc73ae3feb0978ee91fbe..491cf0189b96c85d37fca7c93e8f3d9f1cefa061 100644 (file)
 #define NPRT(x) (x)?(x):_("*None*")
  
 #if defined(HAVE_WIN32)
+
+#define WIN32_REPARSE_POINT 1
+#define WIN32_MOUNT_POINT   2
+
 void InitWinAPIWrapper();
 
 #define  OSDependentInit()    InitWinAPIWrapper()
index a1ee4dcf71c8a345c594e0c6457d214b68e3de4c..7837748ead6146e822fa848dcd2c29e83714b3db 100644 (file)
@@ -515,9 +515,11 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt,
        * We have set st_rdev to 1 if it is a reparse point, otherwise 0,
        *  if st_rdev is 2, it is a mount point 
        */
-      if (have_win32_api() && ff_pkt->statp.st_rdev == 1) {
-         ff_pkt->type = FT_REPARSE;
+#if defined(HAVE_WIN32)
+      if (ff_pkt->statp.st_rdev == WIN32_REPARSE_POINT) {
+          ff_pkt->type = FT_REPARSE;
       }
+#endif
       /*
        * Note, we return the directory to the calling program (handle_file)
        * when we first see the directory (FT_DIRBEGIN.
@@ -555,11 +557,16 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt,
        * to cross, or we may be restricted by a list of permitted
        * file systems.
        */
+      bool is_win32_mount_point = false;
+#if defined(HAVE_WIN32)
+      is_win32_mount_point = ff_pkt->statp.st_rdev == WIN32_MOUNT_POINT;
+#endif
       if (!top_level && ff_pkt->flags & FO_NO_RECURSION) {
          ff_pkt->type = FT_NORECURSE;
          recurse = false;
-      } else if (!top_level && parent_device != ff_pkt->statp.st_dev) {
-         if(!(ff_pkt->flags & FO_MULTIFS)) {
+      } else if (!top_level && (parent_device != ff_pkt->statp.st_dev ||
+                 is_win32_mount_point)) {
+         if (!(ff_pkt->flags & FO_MULTIFS)) {
             ff_pkt->type = FT_NOFSCHG;
             recurse = false;
          } else if (!accept_fstype(ff_pkt, NULL)) {
index d40560bdd0e3fc879d64acc89ec31f592d70d2ae..8a7426aeb28138d475faefe72aecb4c247f32fc7 100644 (file)
@@ -3,9 +3,9 @@
  */
 
 #undef  VERSION
-#define VERSION "2.2.10-b3"
-#define BDATE   "20 May 2008"
-#define LSMDATE "20May08"
+#define VERSION "2.2.10-b4"
+#define BDATE   "21 May 2008"
+#define LSMDATE "21May08"
 
 #define PROG_COPYRIGHT "Copyright (C) %d-2008 Free Software Foundation Europe e.V.\n"
 #define BYEAR "2008"       /* year for copyright messages in progs */
index f549e266127820def0fe6131a90919d56822d461..a3171c3c308d404c3478d01da0217b70ca6bd1fd 100644 (file)
@@ -644,6 +644,8 @@ statDir(const char *file, struct stat *sb)
       LocalFree((void *)err);
       errno = b_errno_win32;
       return -1;
+   } else {
+      FindClose(h);
    }
 
    sb->st_mode = 0777;               /* start with everything */
@@ -655,12 +657,23 @@ statDir(const char *file, struct stat *sb)
        sb->st_mode |= S_ISVTX; /* use sticky bit -> hidden */
    sb->st_mode |= S_IFDIR;
 
-   /* Use st_rdev to store reparse attribute */
-   sb->st_rdev = (*pdwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ? 1 : 0; 
-   if (sb->st_rdev == 1 && *pdwReserved0 & IO_REPARSE_TAG_MOUNT_POINT) {
-      sb->st_rdev = 2;                /* mount point */
-   }
-
+   /* 
+    * Store reparse/mount point info in st_rdev.  Note a
+    *  Win32 reparse point (junction point) is like a link
+    *  though it can have many properties (directory link,
+    *  soft link, hard link, HSM, ...
+    *  A mount point is a reparse point where another volume
+    *  is mounted, so it is like a Unix mount point (change of
+    *  filesystem).
+    */
+   if (*pdwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
+      if (*pdwReserved0 & IO_REPARSE_TAG_MOUNT_POINT) {
+         sb->st_rdev = WIN32_MOUNT_POINT;           /* mount point */
+      } else {
+         sb->st_rdev = WIN32_REPARSE_POINT;         /* reparse point */
+      }
+   }  
+   Dmsg2(100, "st_rdev=%d file=%s\n", sb->st_rdev, file);
    sb->st_size = *pnFileSizeHigh;
    sb->st_size <<= 32;
    sb->st_size |= *pnFileSizeLow;
@@ -670,7 +683,6 @@ statDir(const char *file, struct stat *sb)
    sb->st_atime = cvt_ftime_to_utime(*pftLastAccessTime);
    sb->st_mtime = cvt_ftime_to_utime(*pftLastWriteTime);
    sb->st_ctime = cvt_ftime_to_utime(*pftCreationTime);
-   FindClose(h);
 
    return 0;
 }
@@ -679,11 +691,10 @@ int
 fstat(int fd, struct stat *sb)
 {
    BY_HANDLE_FILE_INFORMATION info;
-   char tmpbuf[1024];
 
    if (!GetFileInformationByHandle((HANDLE)fd, &info)) {
        const char *err = errorString();
-       Dmsg2(99, "GetfileInformationByHandle(%s): %s\n", tmpbuf, err);
+       Dmsg1(99, "GetfileInformationByHandle: %s\n", err);
        LocalFree((void *)err);
        errno = b_errno_win32;
        return -1;
@@ -708,7 +719,11 @@ fstat(int fd, struct stat *sb)
    sb->st_mode |= S_IFREG;
 
    /* Use st_rdev to store reparse attribute */
-   sb->st_rdev = (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ? 1 : 0; 
+   if  (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
+      sb->st_rdev = WIN32_REPARSE_POINT;
+   }
+   Dmsg3(100, "st_rdev=%d sizino=%d ino=%lld\n", sb->st_rdev, sizeof(sb->st_ino),
+      (long long)sb->st_ino);
 
    sb->st_size = info.nFileSizeHigh;
    sb->st_size <<= 32;
@@ -727,8 +742,8 @@ stat2(const char *file, struct stat *sb)
 {
    HANDLE h;
    int rval = 0;
-   char tmpbuf[1024];
-   conv_unix_to_win32_path(file, tmpbuf, 1024);
+   char tmpbuf[5000];
+   conv_unix_to_win32_path(file, tmpbuf, 5000);
 
    DWORD attr = (DWORD)-1;
 
@@ -779,12 +794,11 @@ stat(const char *file, struct stat *sb)
    WIN32_FILE_ATTRIBUTE_DATA data;
    errno = 0;
 
-
    memset(sb, 0, sizeof(*sb));
 
    if (p_GetFileAttributesExW) {
       /* dynamically allocate enough space for UCS2 filename */
-      POOLMEM* pwszBuf = get_pool_memory (PM_FNAME);
+      POOLMEM *pwszBuf = get_pool_memory(PM_FNAME);
       make_win32_path_UTF8_2_wchar(&pwszBuf, file);
 
       BOOL b = p_GetFileAttributesExW((LPCWSTR) pwszBuf, GetFileExInfoStandard, &data);
@@ -793,6 +807,7 @@ stat(const char *file, struct stat *sb)
       if (!b) {
          return stat2(file, sb);
       }
+
    } else if (p_GetFileAttributesExA) {
       if (!p_GetFileAttributesExA(file, GetFileExInfoStandard, &data)) {
          return stat2(file, sb);
@@ -842,6 +857,8 @@ stat(const char *file, struct stat *sb)
         file[1] == ':' && file[2] != 0) {
       statDir(file, sb);
    }
+   Dmsg3(100, "sizino=%d ino=%lld file=%s\n", sizeof(sb->st_ino),
+                       (long long)sb->st_ino, file);
    return 0;
 }
 
@@ -2128,10 +2145,10 @@ utime(const char *fname, struct utimbuf *times)
     HANDLE h = INVALID_HANDLE_VALUE;
 
     if (p_CreateFileW) {
-      POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
-      make_win32_path_UTF8_2_wchar(&pwszBuf, tmpbuf);
+       POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
+       make_win32_path_UTF8_2_wchar(&pwszBuf, tmpbuf);
 
-      h = p_CreateFileW((LPCWSTR)pwszBuf,
+       h = p_CreateFileW((LPCWSTR)pwszBuf,
                         FILE_WRITE_ATTRIBUTES,
                         FILE_SHARE_WRITE|FILE_SHARE_READ|FILE_SHARE_DELETE,
                         NULL,
@@ -2139,9 +2156,9 @@ utime(const char *fname, struct utimbuf *times)
                         FILE_FLAG_BACKUP_SEMANTICS, // required for directories
                         NULL);
 
-      free_pool_memory(pwszBuf);
+       free_pool_memory(pwszBuf);
     } else if (p_CreateFileA) {
-      h = p_CreateFileA(tmpbuf,
+       h = p_CreateFileA(tmpbuf,
                         FILE_WRITE_ATTRIBUTES,
                         FILE_SHARE_WRITE|FILE_SHARE_READ|FILE_SHARE_DELETE,
                         NULL,
@@ -2151,11 +2168,11 @@ utime(const char *fname, struct utimbuf *times)
     }
 
     if (h == INVALID_HANDLE_VALUE) {
-        const char *err = errorString();
-        Dmsg2(99, "Cannot open file \"%s\" for utime(): ERR=%s", tmpbuf, err);
-        LocalFree((void *)err);
-        errno = b_errno_win32;
-        return -1;
+       const char *err = errorString();
+       Dmsg2(99, "Cannot open file \"%s\" for utime(): ERR=%s", tmpbuf, err);
+       LocalFree((void *)err);
+       errno = b_errno_win32;
+       return -1;
     }
 
     int rval = SetFileTime(h, NULL, &acc, &mod) ? 0 : -1;
@@ -2170,49 +2187,49 @@ utime(const char *fname, struct utimbuf *times)
 int
 file_open(const char *file, int flags, int mode)
 {
-    DWORD access = 0;
-    DWORD shareMode = 0;
-    DWORD create = 0;
-    DWORD msflags = 0;
-    HANDLE foo = INVALID_HANDLE_VALUE;
-    const char *remap = file;
-
-    if (flags & O_WRONLY) access = GENERIC_WRITE;
-    else if (flags & O_RDWR) access = GENERIC_READ|GENERIC_WRITE;
-    else access = GENERIC_READ;
-
-    if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
-       create = CREATE_NEW;
-    else if ((flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
-       create = CREATE_ALWAYS;
-    else if (flags & O_CREAT)
-       create = OPEN_ALWAYS;
-    else if (flags & O_TRUNC)
-       create = TRUNCATE_EXISTING;
-    else 
-       create = OPEN_EXISTING;
-
-    shareMode = 0;
-
-    if (flags & O_APPEND) {
-        printf("open...APPEND not implemented yet.");
-        exit(-1);
-    }
+   DWORD access = 0;
+   DWORD shareMode = 0;
+   DWORD create = 0;
+   DWORD msflags = 0;
+   HANDLE foo = INVALID_HANDLE_VALUE;
+   const char *remap = file;
+
+   if (flags & O_WRONLY) access = GENERIC_WRITE;
+   else if (flags & O_RDWR) access = GENERIC_READ|GENERIC_WRITE;
+   else access = GENERIC_READ;
+
+   if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+      create = CREATE_NEW;
+   else if ((flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
+      create = CREATE_ALWAYS;
+   else if (flags & O_CREAT)
+      create = OPEN_ALWAYS;
+   else if (flags & O_TRUNC)
+      create = TRUNCATE_EXISTING;
+   else 
+      create = OPEN_EXISTING;
+
+   shareMode = 0;
+
+   if (flags & O_APPEND) {
+      printf("open...APPEND not implemented yet.");
+      exit(-1);
+   }
 
-    if (p_CreateFileW) {
-       POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
-       make_win32_path_UTF8_2_wchar(&pwszBuf, file);
+   if (p_CreateFileW) {
+      POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
+      make_win32_path_UTF8_2_wchar(&pwszBuf, file);
 
-       foo = p_CreateFileW((LPCWSTR) pwszBuf, access, shareMode, NULL, create, msflags, NULL);
-       free_pool_memory(pwszBuf);
-    } else if (p_CreateFileA)
-       foo = CreateFile(file, access, shareMode, NULL, create, msflags, NULL);
+      foo = p_CreateFileW((LPCWSTR) pwszBuf, access, shareMode, NULL, create, msflags, NULL);
+      free_pool_memory(pwszBuf);
+   } else if (p_CreateFileA)
+      foo = CreateFile(file, access, shareMode, NULL, create, msflags, NULL);
 
-    if (INVALID_HANDLE_VALUE == foo) {
-        errno = b_errno_win32;
-        return(int) -1;
-    }
-    return (int)foo;
+   if (INVALID_HANDLE_VALUE == foo) {
+      errno = b_errno_win32;
+      return (int)-1;
+   }
+   return (int)foo;
 
 }
 
index ff1cf72bcdfc03073fa9bed1bfbc9bf39841c923..849ec4bbfee6a3798e9391ff878e977f11e10128 100644 (file)
@@ -2,6 +2,13 @@
 
 General:
 
+21May08
+kes  Fix Win32 reparse points. Bacula will not recurse into any
+     reparse point directory, including mount points, unless the
+     directory is explicitly mentioned at the top level (same as
+     with Unix).  A file that is linked to another file will be
+     backed up -- much as Unix does for hardlinked files.
+     This *should* fix bug #1041.
 20May08
 kes  Remove double quotes from ChangeLog and ReleaseNotes
 kes  Remove StorageId test when pruning and recycling (Eric's changes).