From: Robert Nelson Date: Mon, 2 Oct 2006 15:09:45 +0000 (+0000) Subject: Fix bug # 676 - File Restoration to win32 client fails X-Git-Tag: Release-2.0.0~387 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=43828c73729051efd4a2eb36a0daffb7ef5f4372;p=bacula%2Fbacula Fix bug # 676 - File Restoration to win32 client fails Fix reopen problem for tape devices. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@3530 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/src/findlib/makepath.c b/bacula/src/findlib/makepath.c index 70e7feaf4c..2ca799fadf 100644 --- a/bacula/src/findlib/makepath.c +++ b/bacula/src/findlib/makepath.c @@ -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; diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c index c86658797d..70c083417d 100644 --- a/bacula/src/stored/dev.c +++ b/bacula/src/stored/dev.c @@ -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; } diff --git a/bacula/src/win32/build-depkgs-msvc.cmd b/bacula/src/win32/build-depkgs-msvc.cmd index 778301a35f..d0e1538b91 100644 --- a/bacula/src/win32/build-depkgs-msvc.cmd +++ b/bacula/src/win32/build-depkgs-msvc.cmd @@ -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%