]> git.sur5r.net Git - bacula/bacula/commitdiff
Fix bug # 676 - File Restoration to win32 client fails
authorRobert Nelson <robertn@the-nelsons.org>
Mon, 2 Oct 2006 15:09:45 +0000 (15:09 +0000)
committerRobert Nelson <robertn@the-nelsons.org>
Mon, 2 Oct 2006 15:09:45 +0000 (15:09 +0000)
Fix reopen problem for tape devices.

git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@3530 91ce42f0-d328-0410-95d8-f526ca767f89

bacula/src/findlib/makepath.c
bacula/src/stored/dev.c
bacula/src/win32/build-depkgs-msvc.cmd

index 70e7feaf4c75d78c4ade637c41c60254b21a2e2a..2ca799fadffc8ad3d26271e0115a3f66d75e97fd 100644 (file)
@@ -74,7 +74,7 @@ cleanup(struct saved_cwd *cwd)
       int _fail = restore_cwd(cwd, NULL, NULL);
       free_cwd(cwd);
       if (_fail) {
-        return 1;
+         return 1;
       }
    }
    return 0;
@@ -104,24 +104,24 @@ make_dir(JCR *jcr, const char *dir, const char *dirpath, mode_t mode, int *creat
       struct stat stats;
 
       /* The mkdir and stat calls below may appear to be reversed.
-        They are not.  It is important to call mkdir first and then to
-        call stat (to distinguish the three cases) only if mkdir fails.
-        The alternative to this approach is to `stat' each directory,
-        then to call mkdir if it doesn't exist.  But if some other process
-        were to create the directory between the stat & mkdir, the mkdir
-        would fail with EEXIST.  */
+         They are not. It is important to call mkdir first and then to
+         call stat (to distinguish the three cases) only if mkdir fails.
+         The alternative to this approach is to `stat' each directory,
+         then to call mkdir if it doesn't exist.  But if some other process
+         were to create the directory between the stat & mkdir, the mkdir
+         would fail with EEXIST.  */
 
       if (stat(dir, &stats)) {
-         berrno be;
-         be.set_errno(save_errno);
-         Jmsg(jcr, M_ERROR, 0, _("Cannot create directory %s: ERR=%s\n"),
-                 dirpath, be.strerror());
-         fail = 1;
+          berrno be;
+          be.set_errno(save_errno);
+          Jmsg(jcr, M_ERROR, 0, _("Cannot create directory %s: ERR=%s\n"),
+                  dirpath, be.strerror());
+          fail = 1;
       } else if (!S_ISDIR(stats.st_mode)) {
-         Jmsg(jcr, M_ERROR, 0, _("%s exists but is not a directory\n"), quote(dirpath));
-         fail = 1;
+          Jmsg(jcr, M_ERROR, 0, _("%s exists but is not a directory\n"), quote(dirpath));
+          fail = 1;
       } else {
-         /* DIR (aka DIRPATH) already exists and is a directory. */
+          /* DIR (aka DIRPATH) already exists and is a directory. */
       }
   }
 
@@ -167,25 +167,25 @@ isAbsolute(const char *path)
 
 int
 make_path(
-          JCR *jcr,
-          const char *argpath,
-          int mode,
-          int parent_mode,
-          uid_t owner,
-          gid_t group,
-          int preserve_existing,
-          char *verbose_fmt_string)
+           JCR *jcr,
+           const char *argpath,
+           int mode,
+           int parent_mode,
+           uid_t owner,
+           gid_t group,
+           int preserve_existing,
+           char *verbose_fmt_string)
 {
   struct stat stats;
   int retval = 0;
 
   if (stat(argpath, &stats)) {
       char *slash;
-      int tmp_mode;            /* Initial perms for leading dirs.  */
-      int re_protect;          /* Should leading dirs be unwritable? */
+      int tmp_mode;              /* Initial perms for leading dirs.  */
+      int re_protect;            /* Should leading dirs be unwritable? */
       struct ptr_list {
-       char *dirname_end;
-       struct ptr_list *next;
+        char *dirname_end;
+        struct ptr_list *next;
       };
       struct ptr_list *p, *leading_dirs = NULL;
       struct saved_cwd cwd;
@@ -201,172 +201,195 @@ make_path(
       strip_trailing_slashes(dirpath);
 
       /* If leading directories shouldn't be writable or executable,
-        or should have set[ug]id or sticky bits set and we are setting
-        their owners, we need to fix their permissions after making them.  */
+         or should have set[ug]id or sticky bits set and we are setting
+         their owners, we need to fix their permissions after making them.  */
       if (((parent_mode & WX_USR) != WX_USR)
-         || ((owner != (uid_t)-1 || group != (gid_t)-1)
-             && (parent_mode & (S_ISUID | S_ISGID | S_ISVTX)) != 0)) {
-        tmp_mode = S_IRWXU;
-        re_protect = 1;
+          || ((owner != (uid_t)-1 || group != (gid_t)-1)
+              && (parent_mode & (S_ISUID | S_ISGID | S_ISVTX)) != 0)) {
+         tmp_mode = S_IRWXU;
+         re_protect = 1;
       } else {
-        tmp_mode = parent_mode;
-        re_protect = 0;
+         tmp_mode = parent_mode;
+         re_protect = 0;
       }
 
 #if defined(HAVE_WIN32)
-      // chdir can fail if permissions are sufficiently restricted since I don't think
-      // backup/restore security rights affect ChangeWorkingDirectory
+      /* chdir can fail if permissions are sufficiently restricted since I don't think
+         backup/restore security rights affect ChangeWorkingDirectory */
       cwd.do_chdir = 0;
+
+      /* Validate drive letter */
+      if (dirpath[1] == ':') {
+         char drive[4] = "X:\\";
+
+         drive[0] = dirpath[0];
+
+         UINT drive_type = GetDriveType(drive);
+
+         if (drive_type == DRIVE_UNKNOWN || drive_type == DRIVE_NO_ROOT_DIR) {
+            Jmsg(jcr, M_ERROR, 0, _("%c: is not a valid drive\n"), dirpath[0]);
+            return 1;
+         }
+
+         if (dirpath[2] == '\0') {
+            return 0;
+         }
+
+         slash = &dirpath[3];
+      } else {
+         slash = dirpath;
+      }
 #else
       /* If we can record the current working directory, we may be able
-        to do the chdir optimization.  */
+         to do the chdir optimization. */
       cwd.do_chdir = !save_cwd(&cwd);
+
+      slash = dirpath;
 #endif
+
       /* If we've saved the cwd and DIRPATH is an absolute pathname,
-        we must chdir to `/' in order to enable the chdir optimization.
-        So if chdir ("/") fails, turn off the optimization.  */
+         we must chdir to `/' in order to enable the chdir optimization.
+         So if chdir ("/") fails, turn off the optimization.  */
       if (cwd.do_chdir && isAbsolute(dirpath) && (chdir("/") < 0)) {
-        cwd.do_chdir = 0;
+         cwd.do_chdir = 0;
       }
 
-      slash = dirpath;
-
       /* Skip over leading slashes.  */
       while (*slash == '/')
-        slash++;
+         slash++;
 
       while (1) {
-         int newly_created_dir;
-         int fail;
-
-         /* slash points to the leftmost unprocessed component of dirpath.  */
-         basename_dir = slash;
-
-         slash = strchr (slash, '/');
-         if (slash == NULL) {
-            break;
-         }
-
-         /* If we're *not* doing chdir before each mkdir, then we have to refer
-            to the target using the full (multi-component) directory name.  */
-         if (!cwd.do_chdir) {
-            basename_dir = dirpath;
-         }
-
-         *slash = '\0';
-         fail = make_dir(jcr, basename_dir, dirpath, tmp_mode, &newly_created_dir);
-         if (fail) {
-             umask(oldmask);
-             cleanup(&cwd);
-             return 1;
-         }
-
-         if (newly_created_dir) {
-             Dmsg0(300, "newly_created_dir\n");
-
-             if ((owner != (uid_t)-1 || group != (gid_t)-1)
-                 && chown(basename_dir, owner, group)
+          int newly_created_dir;
+          int fail;
+
+          /* slash points to the leftmost unprocessed component of dirpath.  */
+          basename_dir = slash;
+
+          slash = strchr (slash, '/');
+          if (slash == NULL) {
+             break;
+          }
+
+          /* If we're *not* doing chdir before each mkdir, then we have to refer
+             to the target using the full (multi-component) directory name.  */
+          if (!cwd.do_chdir) {
+             basename_dir = dirpath;
+          }
+
+          *slash = '\0';
+          fail = make_dir(jcr, basename_dir, dirpath, tmp_mode, &newly_created_dir);
+          if (fail) {
+              umask(oldmask);
+              cleanup(&cwd);
+              return 1;
+          }
+
+          if (newly_created_dir) {
+              Dmsg0(300, "newly_created_dir\n");
+
+              if ((owner != (uid_t)-1 || group != (gid_t)-1)
+                  && chown(basename_dir, owner, group)
 #if defined(AFS) && defined (EPERM)
-                 && errno != EPERM
+                  && errno != EPERM
 #endif
-                 ) {
-                /* Note, if we are restoring as NON-root, this may not be fatal */
-                berrno be;
-                Jmsg(jcr, M_ERROR, 0, _("Cannot change owner and/or group of %s: ERR=%s\n"),
-                     quote(dirpath), be.strerror());
-             }
-             Dmsg0(300, "Chown done.\n");
-
-             if (re_protect) {
-                struct ptr_list *pnew = (struct ptr_list *)
-                   alloca(sizeof (struct ptr_list));
-                pnew->dirname_end = slash;
-                pnew->next = leading_dirs;
-                leading_dirs = pnew;
-                Dmsg0(300, "re_protect\n");
-             }
-         }
-
-         /* If we were able to save the initial working directory,
-            then we can use chdir to change into each directory before
-            creating an entry in that directory.  This avoids making
-            stat and mkdir process O(n^2) file name components.  */
-         if (cwd.do_chdir && chdir(basename_dir) < 0) {
-             berrno be;
-             Jmsg(jcr, M_ERROR, 0, _("Cannot chdir to directory, %s: ERR=%s\n"),
-                    quote(dirpath), be.strerror());
-             umask(oldmask);
-             cleanup(&cwd);
-             return 1;
-         }
-
-         *slash++ = '/';
-
-         /* Avoid unnecessary calls to `stat' when given
-            pathnames containing multiple adjacent slashes.  */
-         while (*slash == '/')
-            slash++;
+                  ) {
+                 /* Note, if we are restoring as NON-root, this may not be fatal */
+                 berrno be;
+                 Jmsg(jcr, M_ERROR, 0, _("Cannot change owner and/or group of %s: ERR=%s\n"),
+                      quote(dirpath), be.strerror());
+              }
+              Dmsg0(300, "Chown done.\n");
+
+              if (re_protect) {
+                 struct ptr_list *pnew = (struct ptr_list *)
+                    alloca(sizeof (struct ptr_list));
+                 pnew->dirname_end = slash;
+                 pnew->next = leading_dirs;
+                 leading_dirs = pnew;
+                 Dmsg0(300, "re_protect\n");
+              }
+          }
+
+          /* If we were able to save the initial working directory,
+             then we can use chdir to change into each directory before
+             creating an entry in that directory.  This avoids making
+             stat and mkdir process O(n^2) file name components.  */
+          if (cwd.do_chdir && chdir(basename_dir) < 0) {
+              berrno be;
+              Jmsg(jcr, M_ERROR, 0, _("Cannot chdir to directory, %s: ERR=%s\n"),
+                     quote(dirpath), be.strerror());
+              umask(oldmask);
+              cleanup(&cwd);
+              return 1;
+          }
+
+          *slash++ = '/';
+
+          /* Avoid unnecessary calls to `stat' when given
+             pathnames containing multiple adjacent slashes.  */
+          while (*slash == '/')
+             slash++;
       } /* end while (1) */
 
       if (!cwd.do_chdir) {
-        basename_dir = dirpath;
+         basename_dir = dirpath;
       }
 
       /* We're done making leading directories.
-        Create the final component of the path.  */
+         Create the final component of the path.  */
 
       Dmsg1(300, "Create final component. mode=%o\n", mode);
       if (make_dir(jcr, basename_dir, dirpath, mode, NULL)) {
-         umask(oldmask);
-         cleanup(&cwd);
-         return 1;
+          umask(oldmask);
+          cleanup(&cwd);
+          return 1;
       }
 
       /* Done creating directories.  Restore original umask.  */
       umask(oldmask);
 
       if (owner != (uid_t)-1 || group != (gid_t)-1) {
-         if (chown(basename_dir, owner, group)
+          if (chown(basename_dir, owner, group)
 #ifdef AFS
-             && errno != EPERM
+              && errno != EPERM
 #endif
-             )
-           {
-             berrno be;
-             Jmsg(jcr, M_WARNING, 0, _("Cannot change owner and/or group of %s: ERR=%s\n"),
-                    quote(dirpath), be.strerror());
-           }
+              )
+            {
+              berrno be;
+              Jmsg(jcr, M_WARNING, 0, _("Cannot change owner and/or group of %s: ERR=%s\n"),
+                     quote(dirpath), be.strerror());
+            }
       }
 
       /* The above chown may have turned off some permission bits in MODE.
-        Another reason we may have to use chmod here is that mkdir(2) is
-        required to honor only the file permission bits.  In particular,
-        it need not honor the `special' bits, so if MODE includes any
-        special bits, set them here.  */
+         Another reason we may have to use chmod here is that mkdir(2) is
+         required to honor only the file permission bits.  In particular,
+         it need not honor the `special' bits, so if MODE includes any
+         special bits, set them here.  */
       if (mode & ~S_IRWXUGO) {
-        Dmsg1(300, "Final chmod mode=%o\n", mode);
+         Dmsg1(300, "Final chmod mode=%o\n", mode);
       }
       if ((mode & ~S_IRWXUGO) && chmod(basename_dir, mode)) {
-         berrno be;
-         Jmsg(jcr, M_WARNING, 0, _("Cannot change permissions of %s: ERR=%s\n"),
-            quote(dirpath), be.strerror());
+          berrno be;
+          Jmsg(jcr, M_WARNING, 0, _("Cannot change permissions of %s: ERR=%s\n"),
+             quote(dirpath), be.strerror());
       }
 
      if (cleanup(&cwd)) {
-       return 1;
+        return 1;
      }
 
       /* If the mode for leading directories didn't include owner "wx"
-        privileges, we have to reset their protections to the correct
-        value.  */
+         privileges, we have to reset their protections to the correct
+         value.  */
       for (p = leading_dirs; p != NULL; p = p->next) {
-         *(p->dirname_end) = '\0';
-         Dmsg2(300, "Reset parent mode=%o dir=%s\n", parent_mode, dirpath);
-         if (chmod(dirpath, parent_mode)) {
-             berrno be;
-             Jmsg(jcr, M_WARNING, 0, _("Cannot change permissions of %s: ERR=%s\n"),
-                    quote(dirpath), be.strerror());
-         }
+          *(p->dirname_end) = '\0';
+          Dmsg2(300, "Reset parent mode=%o dir=%s\n", parent_mode, dirpath);
+          if (chmod(dirpath, parent_mode)) {
+              berrno be;
+              Jmsg(jcr, M_WARNING, 0, _("Cannot change permissions of %s: ERR=%s\n"),
+                     quote(dirpath), be.strerror());
+          }
       }
   } else {
       /* We get here if the entire path already exists.  */
@@ -374,34 +397,34 @@ make_path(
       const char *dirpath = argpath;
 
       if (!S_ISDIR(stats.st_mode)) {
-         Jmsg(jcr, M_ERROR, 0, _("%s exists but is not a directory\n"), quote(dirpath));
-         return 1;
+          Jmsg(jcr, M_ERROR, 0, _("%s exists but is not a directory\n"), quote(dirpath));
+          return 1;
       }
 
       if (!preserve_existing) {
-         Dmsg0(300, "Do not preserve existing.\n");
-         /* chown must precede chmod because on some systems,
-            chown clears the set[ug]id bits for non-superusers,
-            resulting in incorrect permissions.
-            On System V, users can give away files with chown and then not
-            be able to chmod them.  So don't give files away.  */
-
-         if ((owner != (uid_t)-1 || group != (gid_t)-1)
-             && chown(dirpath, owner, group)
+          Dmsg0(300, "Do not preserve existing.\n");
+          /* chown must precede chmod because on some systems,
+             chown clears the set[ug]id bits for non-superusers,
+             resulting in incorrect permissions.
+             On System V, users can give away files with chown and then not
+             be able to chmod them.  So don't give files away.  */
+
+          if ((owner != (uid_t)-1 || group != (gid_t)-1)
+              && chown(dirpath, owner, group)
 #ifdef AFS
-             && errno != EPERM
+              && errno != EPERM
 #endif
-             ) {
-             berrno be;
-             Jmsg(jcr, M_WARNING, 0, _("Cannot change owner and/or group of %s: ERR=%s\n"),
-                    quote(dirpath), be.strerror());
-           }
-         if (chmod(dirpath, mode)) {
-             berrno be;
-             Jmsg(jcr, M_WARNING, 0, _("Cannot change permissions of %s: ERR=%s\n"),
-                                quote(dirpath), be.strerror());
-         }
-         Dmsg2(300, "pathexists chmod mode=%o dir=%s\n", mode, dirpath);
+              ) {
+              berrno be;
+              Jmsg(jcr, M_WARNING, 0, _("Cannot change owner and/or group of %s: ERR=%s\n"),
+                     quote(dirpath), be.strerror());
+            }
+          if (chmod(dirpath, mode)) {
+              berrno be;
+              Jmsg(jcr, M_WARNING, 0, _("Cannot change permissions of %s: ERR=%s\n"),
+                                 quote(dirpath), be.strerror());
+          }
+          Dmsg2(300, "pathexists chmod mode=%o dir=%s\n", mode, dirpath);
       }
   }
   return retval;
index c86658797dbaad7e3de1f2c834c2d6b2ab90be72..70c083417de3a9dc51721ecca4f18adf652694f9 100644 (file)
@@ -332,7 +332,9 @@ void DEVICE::open_tape_device(DCR *dcr, int omode)
 
    get_autochanger_loaded_slot(dcr);
 
+   openmode = omode;
    set_mode(omode);
+
    if (timeout < 1) {
       timeout = 1;
    }
index 778301a35ff06b8db5fb1ccf53b41d6a8d6bde41..d0e1538b9104bf01343452b441d96e5b3c75d0e2 100644 (file)
@@ -21,7 +21,9 @@ SET SCRIPT_DIR=%CD%
 CD ..\..\..
 set TOP_DIR=%CD%
 
-cd %TOP_DIR%/depkgs-msvc
+IF NOT EXIST %TOP_DIR%\depkgs-msvc\nul MD %TOP_DIR%\depkgs-msvc
+
+cd %TOP_DIR%\depkgs-msvc
 set DEPPKG_DIR=%CD%
 
 cd %DEPPKG_DIR%