/* * Mount the device. * If timeout, wait until the mount command returns 0. * If !timeout, try to mount the device only once. */ bool DEVICE::mount(DCR *dcr, int timeout) { bool retval = true; Dmsg0(190, "Enter mount\n"); if (is_mounted()) { return true; } retval = mount_backend(dcr, timeout); /* * When the mount command succeeded sent a * bsdEventDeviceMount plugin event so any plugin * that want to do something can do things now. */ if (retval && generate_plugin_event(dcr->jcr, bsdEventDeviceMount, dcr) != bRC_OK) { retval = false; } /* * Mark the device mounted if we succeed. */ if (retval) { set_mounted(); } return retval; }
/* * (Un)mount the device (either a FILE or DVD device) */ bool DEVICE::do_file_mount(int mount, int dotimeout) { POOL_MEM ocmd(PM_FNAME); POOLMEM *results; DIR* dp; char *icmd; struct dirent *entry, *result; int status, tries, name_max, count; berrno be; Dsm_check(200); if (mount) { icmd = device->mount_command; } else { icmd = device->unmount_command; } clear_freespace_ok(); edit_mount_codes(ocmd, icmd); Dmsg2(100, "do_file_mount: cmd=%s mounted=%d\n", ocmd.c_str(), !!is_mounted()); if (dotimeout) { /* Try at most 10 times to (un)mount the device. This should perhaps be configurable. */ tries = 10; } else { tries = 1; } results = get_memory(4000); /* If busy retry each second */ Dmsg1(100, "do_file_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 (tries-- > 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_file_mount(0, 0); } bmicrosleep(1, 0); continue; } Dmsg5(100, "Device %s cannot be %smounted. stat=%d result=%s ERR=%s\n", print_name(), (mount ? "" : "un"), status, results, be.bstrerror(status)); Mmsg(errmsg, _("Device %s cannot be %smounted. ERR=%s\n"), print_name(), (mount ? "" : "un"), be.bstrerror(status)); /* * Now, just to be sure it is not mounted, try to read the filesystem. */ 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(100, "do_file_mount: failed to open dir %s (dev=%s), ERR=%s\n", device->mount_point, print_name(), be.bstrerror()); 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_file_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_file_mount: ignoring %s in %s\n", result->d_name, device->mount_point); } } free(entry); closedir(dp); Dmsg1(100, "do_file_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); free_pool_memory(results); Dmsg0(200, "============ mount=0\n"); Dsm_check(200); return false; } set_mounted(mount); /* set/clear mounted flag */ free_pool_memory(results); Dmsg1(200, "============ mount=%d\n", mount); return true; }