+ Dmsg0(190, "Enter mount\n");
+ if (is_mounted()) {
+ return true;
+ } else if (requires_mount()) {
+ return do_mount(1, timeout);
+ }
+ return true;
+}
+
+/* Unmount the device
+ * If timeout, wait until the unmount command returns 0.
+ * If !timeout, try to unmount the device only once.
+ */
+bool DEVICE::unmount(int timeout)
+{
+ Dmsg0(90, "Enter unmount\n");
+ if (is_mounted()) {
+ return do_mount(0, timeout);
+ }
+ return true;
+}
+
+/* (Un)mount the device */
+bool DEVICE::do_mount(int mount, int dotimeout)
+{
+ POOL_MEM ocmd(PM_FNAME);
+ POOLMEM *results;
+ char *icmd;
+ int status, timeout;
+
+ sm_check(__FILE__, __LINE__, false);
+ if (mount) {
+ if (is_mounted()) {
+ Dmsg0(200, "======= mount=1\n");
+ return true;
+ }
+ icmd = device->mount_command;
+ } else {
+ if (!is_mounted()) {
+ Dmsg0(200, "======= mount=0\n");
+ return true;
+ }
+ icmd = device->unmount_command;
+ }
+
+ clear_freespace_ok();
+ edit_mount_codes(ocmd, icmd);
+
+ Dmsg2(100, "do_mount: cmd=%s mounted=%d\n", ocmd.c_str(), !!is_mounted());
+
+ if (dotimeout) {
+ /* Try at most 1 time to (un)mount the device. This should perhaps be configurable. */
+ timeout = 1;
+ } else {
+ timeout = 0;
+ }
+ results = get_memory(4000);
+ results[0] = 0;
+
+ /* If busy retry each second */
+ Dmsg1(20, "do_mount run_prog=%s\n", ocmd.c_str());
+ while ((status = run_program_full_output(ocmd.c_str(),
+ max_open_wait/2, results)) != 0) {
+ /* Doesn't work with internationalization (This is not a problem) */
+ if (mount && fnmatch("*is already mounted on*", results, 0) == 0) {
+ break;
+ }
+ if (!mount && fnmatch("* not mounted*", results, 0) == 0) {
+ break;
+ }
+ if (timeout-- > 0) {
+ /* Sometimes the device cannot be mounted because it is already mounted.
+ * Try to unmount it, then remount it */
+ if (mount) {
+ Dmsg1(400, "Trying to unmount the device %s...\n", print_name());
+ do_mount(0, 0);
+ }
+ bmicrosleep(1, 0);
+ continue;
+ }
+ if (status != 0) {
+ berrno be;
+ Dmsg5(40, "Device %s cannot be %smounted. stat=%d result=%s ERR=%s\n", print_name(),
+ (mount ? "" : "un"), status, results, be.strerror(status));
+ Mmsg(errmsg, _("Device %s cannot be %smounted. ERR=%s\n"),
+ print_name(), (mount ? "" : "un"), be.strerror(status));
+ } else {
+ Dmsg4(40, "Device %s cannot be %smounted. stat=%d ERR=%s\n", print_name(),
+ (mount ? "" : "un"), status, results);
+ Mmsg(errmsg, _("Device %s cannot be %smounted. ERR=%s\n"),
+ print_name(), (mount ? "" : "un"), results);
+ }
+ /*
+ * Now, just to be sure it is not mounted, try to read the
+ * filesystem.
+ */
+ DIR* dp;
+ struct dirent *entry, *result;
+ int name_max;
+ int count;
+
+ name_max = pathconf(".", _PC_NAME_MAX);
+ if (name_max < 1024) {
+ name_max = 1024;
+ }
+
+ if (!(dp = opendir(device->mount_point))) {
+ berrno be;
+ dev_errno = errno;
+ Dmsg3(29, "do_mount: failed to open dir %s (dev=%s), ERR=%s\n",
+ device->mount_point, print_name(), be.strerror());
+ goto get_out;
+ }
+
+ entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000);
+ count = 0;
+ while (1) {
+ if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
+ dev_errno = EIO;
+ Dmsg2(129, "do_mount: failed to find suitable file in dir %s (dev=%s)\n",
+ device->mount_point, print_name());
+ break;
+ }
+ if ((strcmp(result->d_name, ".")) && (strcmp(result->d_name, "..")) && (strcmp(result->d_name, ".keep"))) {
+ count++; /* result->d_name != ., .. or .keep (Gentoo-specific) */
+ break;
+ } else {
+ Dmsg2(129, "do_mount: ignoring %s in %s\n", result->d_name, device->mount_point);
+ }
+ }
+ free(entry);
+ closedir(dp);
+
+ Dmsg1(29, "do_mount: got %d files in the mount point (not counting ., .. and .keep)\n", count);
+
+ if (count > 0) {
+ /* If we got more than ., .. and .keep */
+ /* there must be something mounted */
+ if (mount) {
+ Dmsg1(100, "Did Mount by count=%d\n", count);
+ break;
+ } else {
+ /* An unmount request. We failed to unmount - report an error */
+ set_mounted(true);
+ free_pool_memory(results);
+ Dmsg0(200, "== error mount=1 wanted unmount\n");
+ return false;
+ }
+ }
+get_out:
+ set_mounted(false);
+ sm_check(__FILE__, __LINE__, false);
+ free_pool_memory(results);
+ Dmsg0(200, "============ mount=0\n");
+ return false;