From: Kern Sibbald Date: Sat, 11 Feb 2006 09:08:03 +0000 (+0000) Subject: Add scan.c X-Git-Tag: Release-1.38.6~29 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=e670d56b052fe2d2a235c84b473e7d0119cd0787;p=bacula%2Fbacula Add scan.c git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@2782 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/src/stored/scan.c b/bacula/src/stored/scan.c new file mode 100644 index 0000000000..5700ec2142 --- /dev/null +++ b/bacula/src/stored/scan.c @@ -0,0 +1,148 @@ +/* + * + * scan.c scan a directory (on a removable file) for a valid + * Volume name. If found, open the file for append. + * + * Kern Sibbald, MMVI + * + * Version $Id$ + */ +/* + Copyright (C) 2006 Kern Sibbald + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as amended with additional clauses defined in the + file LICENSE in the main source directory. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + the file LICENSE for additional details. + + */ + +#include "bacula.h" +#include "stored.h" + +/* Forward referenced functions */ +static bool is_volume_name_legal(char *name); + + +bool DEVICE::scan_dir_for_volume(DCR *dcr) +{ + DIR* dp; + struct dirent *entry, *result; + int name_max; + char *mount_point; + VOLUME_CAT_INFO dcrVolCatInfo, devVolCatInfo; + struct stat statp; + bool found = false; + POOL_MEM fname(PM_FNAME); + bool need_slash = false; + int len; + + + name_max = pathconf(".", _PC_NAME_MAX); + if (name_max < 1024) { + name_max = 1024; + } + + if (device->mount_point) { + mount_point = device->mount_point; + } else { + mount_point = device->device_name; + } + + if (!(dp = opendir(mount_point))) { + berrno be; + dev_errno = errno; + Dmsg3(29, "scan_dir_for_vol: failed to open dir %s (dev=%s), ERR=%s\n", + mount_point, print_name(), be.strerror()); + goto get_out; + } + + len = strlen(mount_point); + if (len > 0) { + need_slash = mount_point[len - 1] != '/'; + } + entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000); + for ( ;; ) { + if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) { + dev_errno = EIO; + Dmsg2(129, "scan_dir_for_vol: failed to find suitable file in dir %s (dev=%s)\n", + mount_point, print_name()); + break; + } + if (strcmp(result->d_name, ".") == 0 || + strcmp(result->d_name, "..") == 0) { + continue; + } + + if (!is_volume_name_legal(result->d_name)) { + continue; + } + pm_strcpy(fname, mount_point); + if (need_slash) { + pm_strcat(fname, "/"); + } + pm_strcat(fname, result->d_name); + if (lstat(fname.c_str(), &statp) != 0 || + !S_ISREG(statp.st_mode)) { + continue; /* ignore directories & special files */ + } + + /* + * OK, we got a different volume mounted. First save the + * requested Volume info (dcr) structure, then query if + * this volume is really OK. If not, put back the desired + * volume name, mark it not in changer and continue. + */ + memcpy(&dcrVolCatInfo, &dcr->VolCatInfo, sizeof(dcrVolCatInfo)); + memcpy(&devVolCatInfo, &VolCatInfo, sizeof(devVolCatInfo)); + /* Check if this is a valid Volume in the pool */ + bstrncpy(dcr->VolumeName, result->d_name, sizeof(dcr->VolumeName)); + if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE)) { + continue; + } + /* This was not the volume we expected, but it is OK with + * the Director, so use it. + */ + memcpy(&VolCatInfo, &dcr->VolCatInfo, sizeof(VolCatInfo)); + found = true; + break; /* got a Volume */ + } + free(entry); + closedir(dp); + +get_out: + sm_check(__FILE__, __LINE__, false); + return found; +} + +/* + * Check if the Volume name has legal characters + * If ua is non-NULL send the message + */ +static bool is_volume_name_legal(char *name) +{ + int len; + const char *p; + const char *accept = ":.-_"; + + /* Restrict the characters permitted in the Volume name */ + for (p=name; *p; p++) { + if (B_ISALPHA(*p) || B_ISDIGIT(*p) || strchr(accept, (int)(*p))) { + continue; + } + return false; + } + len = strlen(name); + if (len >= MAX_NAME_LENGTH) { + return false; + } + if (len == 0) { + return false; + } + return true; +}