]> git.sur5r.net Git - bacula/bacula/commitdiff
Add scan.c
authorKern Sibbald <kern@sibbald.com>
Sat, 11 Feb 2006 09:08:03 +0000 (09:08 +0000)
committerKern Sibbald <kern@sibbald.com>
Sat, 11 Feb 2006 09:08:03 +0000 (09:08 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@2782 91ce42f0-d328-0410-95d8-f526ca767f89

bacula/src/stored/scan.c [new file with mode: 0644]

diff --git a/bacula/src/stored/scan.c b/bacula/src/stored/scan.c
new file mode 100644 (file)
index 0000000..5700ec2
--- /dev/null
@@ -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;
+}