void RootConsoleMenu::GotRootCmd(const CCommand &cmd) { unsigned int argnum = cmd.ArgC(); if (argnum >= 2) { const char *cmdname = cmd.Arg(1); if (strcmp(cmdname, "internal") == 0) { if (argnum >= 3) { const char *arg = cmd.Arg(2); if (strcmp(arg, "1") == 0) { SM_ConfigsExecuted_Global(); } else if (strcmp(arg, "2") == 0) { if (argnum >= 4) { SM_ConfigsExecuted_Plugin(atoi(cmd.Arg(3))); } } } return; } CCommandArgs ocmd(cmd); ConsoleEntry *entry; if (m_Commands.retrieve(cmdname, &entry)) { if (entry->version2) { entry->cmd->OnRootConsoleCommand2(cmdname, &ocmd); } else { entry->cmd->OnRootConsoleCommand(cmdname, cmd); } return; } } ConsolePrint("SourceMod Menu:"); ConsolePrint("Usage: sm <command> [arguments]"); List<ConsoleEntry *>::iterator iter; ConsoleEntry *pEntry; for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++) { pEntry = (*iter); DrawGenericOption(pEntry->command.c_str(), pEntry->description.c_str()); } }
/* * (Un)mount the device (for tape devices) */ static bool do_mount(DCR *dcr, int mount, int dotimeout) { DEVRES *device = dcr->dev->device; POOL_MEM ocmd(PM_FNAME); POOLMEM *results; char *icmd; int status, tries; berrno be; Dsm_check(200); if (mount) { icmd = device->mount_command; } else { icmd = device->unmount_command; } dcr->dev->edit_mount_codes(ocmd, icmd); Dmsg2(100, "do_mount: cmd=%s mounted=%d\n", ocmd.c_str(), dcr->dev->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_mount run_prog=%s\n", ocmd.c_str()); while ((status = run_program_full_output(ocmd.c_str(), dcr->dev->max_open_wait / 2, results)) != 0) { if (tries-- > 0) { continue; } Dmsg5(100, "Device %s cannot be %smounted. stat=%d result=%s ERR=%s\n", dcr->dev->print_name(), (mount ? "" : "un"), status, results, be.bstrerror(status)); Mmsg(dcr->dev->errmsg, _("Device %s cannot be %smounted. ERR=%s\n"), dcr->dev->print_name(), (mount ? "" : "un"), be.bstrerror(status)); free_pool_memory(results); Dmsg0(200, "============ mount=0\n"); Dsm_check(200); return false; } free_pool_memory(results); Dmsg1(200, "============ mount=%d\n", mount); return true; }
/* Update the free space on the device */ bool DEVICE::update_freespace() { POOL_MEM ocmd(PM_FNAME); POOLMEM* results; char* icmd; int timeout; uint64_t free; char ed1[50]; bool ok = false; int status; if (!is_dvd() || is_freespace_ok()) { return true; } /* The device must be mounted in order to dvd-freespace to work */ mount(1); Dsm_check(400); icmd = device->free_space_command; if (!icmd) { free_space = 0; free_space_errno = 0; clear_freespace_ok(); /* No valid freespace */ clear_media(); Dmsg2(29, "ERROR: update_free_space_dev: free_space=%s, free_space_errno=%d (!icmd)\n", edit_uint64(free_space, ed1), free_space_errno); Mmsg(errmsg, _("No FreeSpace command defined.\n")); return false; } edit_mount_codes(ocmd, icmd); Dmsg1(29, "update_freespace: cmd=%s\n", ocmd.c_str()); results = get_pool_memory(PM_MESSAGE); /* Try at most 3 times to get the free space on the device. This should perhaps be configurable. */ timeout = 3; while (1) { berrno be; Dmsg1(20, "Run freespace prog=%s\n", ocmd.c_str()); status = run_program_full_output(ocmd.c_str(), max_open_wait/2, results); Dmsg2(500, "Freespace status=%d result=%s\n", status, results); if (status == 0) { free = str_to_int64(results); Dmsg1(400, "Free space program run: Freespace=%s\n", results); if (free >= 0) { free_space = free; free_space_errno = 0; set_freespace_ok(); /* have valid freespace */ set_media(); Mmsg(errmsg, ""); ok = true; break; } } free_space = 0; free_space_errno = EPIPE; clear_freespace_ok(); /* no valid freespace */ Mmsg2(errmsg, _("Cannot run free space command. Results=%s ERR=%s\n"), results, be.bstrerror(status)); if (--timeout > 0) { Dmsg4(40, "Cannot get free space on device %s. free_space=%s, " "free_space_errno=%d ERR=%s\n", print_name(), edit_uint64(free_space, ed1), free_space_errno, errmsg); bmicrosleep(1, 0); continue; } dev_errno = free_space_errno; Dmsg4(40, "Cannot get free space on device %s. free_space=%s, " "free_space_errno=%d ERR=%s\n", print_name(), edit_uint64(free_space, ed1), free_space_errno, errmsg); break; } free_pool_memory(results); Dmsg4(29, "leave update_freespace: free_space=%s freespace_ok=%d free_space_errno=%d have_media=%d\n", edit_uint64(free_space, ed1), !!is_freespace_ok(), free_space_errno, !!have_media()); Dsm_check(400); return ok; }
/* * Note!!!! Part numbers now begin at 1. The part number is * suppressed from the first part, which is just the Volume * name. Each subsequent part is the Volumename.partnumber. * * Write a part (Vol, Vol.2, ...) from the spool to the DVD * This routine does not update the part number, so normally, you * should call open_next_part() * * It is also called from truncate_dvd to "blank" the medium, as * well as from block.c when the DVD is full to write the last part. */ bool dvd_write_part(DCR *dcr) { DEVICE *dev = dcr->dev; POOL_MEM archive_name(PM_FNAME); /* * Don't write empty part files. * This is only useful when growisofs does not support write beyond * the 4GB boundary. * Example : * - 3.9 GB on the volume, dvd-freespace reports 0.4 GB free * - Write 0.2 GB on the volume, Bacula thinks it could still * append data, it creates a new empty part. * - dvd-freespace reports 0 GB free, as the 4GB boundary has * been crossed * - Bacula thinks he must finish to write to the device, so it * tries to write the last part (0-byte), but dvd-writepart fails... * * There is one exception: when recycling a volume, we write a blank part * file, so, then, we need to accept to write it. */ if (dev->part_size == 0 && !dev->truncating) { Dmsg2(29, "dvd_write_part: device is %s, won't write blank part %d\n", dev->print_name(), dev->part); /* Delete spool file */ make_spooled_dvd_filename(dev, archive_name); unlink(archive_name.c_str()); dev->set_part_spooled(false); Dmsg1(29, "========= unlink(%s)\n", archive_name.c_str()); Dsm_check(400); return true; } POOL_MEM ocmd(PM_FNAME); POOL_MEM results(PM_MESSAGE); char* icmd; int status; int timeout; char ed1[50]; dev->clear_freespace_ok(); /* need to update freespace */ Dsm_check(400); Dmsg3(29, "dvd_write_part: device is %s, part is %d, is_mounted=%d\n", dev->print_name(), dev->part, dev->is_mounted()); icmd = dev->device->write_part_command; dev->edit_mount_codes(ocmd, icmd); /* * original line follows * timeout = dev->max_open_wait + (dev->max_part_size/(1350*1024/2)); * I modified this for a longer timeout; pre-formatting, blanking and * writing can take quite a while */ /* Explanation of the timeout value, when writing the first part, * by Arno Lehmann : * 9 GB, write speed 1x: 6990 seconds (almost 2 hours...) * Overhead: 900 seconds (starting, initializing, finalizing,probably * reloading 15 minutes) * Sum: 15780. * A reasonable last-exit timeout would be 16000 seconds. Quite long - * almost 4.5 hours, but hopefully, that timeout will only ever be needed * in case of a serious emergency. */ if (dev->part == 1) { timeout = 16000; } else { timeout = dev->max_open_wait + (dev->part_size/(1350*1024/4)); } Dmsg2(20, "Write part: cmd=%s timeout=%d\n", ocmd.c_str(), timeout); status = run_program_full_output(ocmd.c_str(), timeout, results.addr()); Dmsg2(20, "Write part status=%d result=%s\n", status, results.c_str()); dev->blank_dvd = false; if (status != 0) { Jmsg2(dcr->jcr, M_FATAL, 0, _("Error writing part %d to the DVD: ERR=%s\n"), dev->part, results.c_str()); Mmsg1(dev->errmsg, _("Error while writing current part to the DVD: %s"), results.c_str()); Dmsg1(100, "%s\n", dev->errmsg); dev->dev_errno = EIO; if (!dev->truncating) { dcr->mark_volume_in_error(); } Dsm_check(400); return false; } Jmsg(dcr->jcr, M_INFO, 0, _("Part %d (%lld bytes) written to DVD.\n"), dev->part, dev->part_size); Dmsg3(400, "dvd_write_part: Part %d (%lld bytes) written to DVD\nResults: %s\n", dev->part, dev->part_size, results.c_str()); dev->num_dvd_parts++; /* there is now one more part on DVD */ dev->VolCatInfo.VolCatParts = dev->num_dvd_parts; dcr->VolCatInfo.VolCatParts = dev->num_dvd_parts; Dmsg1(100, "Update num_parts=%d\n", dev->num_dvd_parts); /* Delete spool file */ make_spooled_dvd_filename(dev, archive_name); unlink(archive_name.c_str()); dev->set_part_spooled(false); Dmsg1(29, "========= unlink(%s)\n", archive_name.c_str()); Dsm_check(400); /* growisofs umounted the device, so remount it (it will update the free space) */ dev->clear_mounted(); dev->mount(1); Jmsg(dcr->jcr, M_INFO, 0, _("Remaining free space %s on %s\n"), edit_uint64_with_commas(dev->free_space, ed1), dev->print_name()); Dsm_check(400); return true; }
/* * (Un)mount the device (For a FILE device) */ static bool do_mount(DCR *dcr, bool mount, int dotimeout) { DEVRES *device = dcr->dev->device; 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; } dcr->dev->edit_mount_codes(ocmd, icmd); Dmsg2(100, "do_mount: cmd=%s mounted=%d\n", ocmd.c_str(), dcr->dev->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_mount run_prog=%s\n", ocmd.c_str()); while ((status = run_program_full_output(ocmd.c_str(), dcr->dev->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", dcr->dev->print_name()); do_mount(dcr, 0, 0); } bmicrosleep(1, 0); continue; } Dmsg5(100, "Device %s cannot be %smounted. status=%d result=%s ERR=%s\n", dcr->dev->print_name(), (mount ? "" : "un"), status, results, be.bstrerror(status)); Mmsg(dcr->dev->errmsg, _("Device %s cannot be %smounted. ERR=%s\n"), dcr->dev->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; dcr->dev->dev_errno = errno; Dmsg3(100, "do_mount: failed to open dir %s (dev=%s), ERR=%s\n", device->mount_point, dcr->dev->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)) { dcr->dev->dev_errno = EIO; Dmsg2(129, "do_mount: failed to find suitable file in dir %s (dev=%s)\n", device->mount_point, dcr->dev->print_name()); break; } if (!bstrcmp(result->d_name, ".") && !bstrcmp(result->d_name, "..") && !bstrcmp(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(100, "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 */ free_pool_memory(results); Dmsg0(200, "== error mount=1 wanted unmount\n"); return false; } } get_out: free_pool_memory(results); Dmsg0(200, "============ mount=0\n"); Dsm_check(200); return false; } free_pool_memory(results); Dmsg1(200, "============ mount=%d\n", mount); return true; }
/* Update the free space on the device */ bool DEVICE::update_freespace() { POOL_MEM ocmd(PM_FNAME); POOLMEM* results; char* icmd; char* p; uint64_t free, total; char ed1[50]; bool ok = false; int status; berrno be; if (!is_file()) { Mmsg(errmsg, ""); return true; } /* The device must be mounted in order for freespace to work */ if (requires_mount()) { mount(1); } if (get_os_device_freespace()) { Dmsg4(20, "get_os_device_freespace: free_space=%s freespace_ok=%d free_space_errno=%d have_media=%d\n", edit_uint64(free_space, ed1), !!is_freespace_ok(), free_space_errno, !!have_media()); return true; } icmd = device->free_space_command; if (!icmd) { set_freespace(0, 0, 0, false); Dmsg2(20, "ERROR: update_free_space_dev: free_space=%s, free_space_errno=%d (!icmd)\n", edit_uint64(free_space, ed1), free_space_errno); Mmsg(errmsg, _("No FreeSpace command defined.\n")); return false; } edit_mount_codes(ocmd, icmd); Dmsg1(20, "update_freespace: cmd=%s\n", ocmd.c_str()); results = get_pool_memory(PM_MESSAGE); Dmsg1(20, "Run freespace prog=%s\n", ocmd.c_str()); status = run_program_full_output(ocmd.c_str(), max_open_wait/2, results); Dmsg2(20, "Freespace status=%d result=%s\n", status, results); /* Should report "1223232 12323232\n" "free total\n" */ if (status == 0) { free = str_to_int64(results) * 1024; p = results; if (skip_nonspaces(&p)) { total = str_to_int64(p) * 1024; } else { total = 0; } Dmsg1(400, "Free space program run: Freespace=%s\n", results); if (free >= 0) { set_freespace(free, total, 0, true); /* have valid freespace */ Mmsg(errmsg, ""); ok = true; } } else { set_freespace(0, 0, EPIPE, false); /* no valid freespace */ Mmsg2(errmsg, _("Cannot run free space command. Results=%s ERR=%s\n"), results, be.bstrerror(status)); dev_errno = free_space_errno; Dmsg4(20, "Cannot get free space on device %s. free_space=%s, " "free_space_errno=%d ERR=%s\n", print_name(), edit_uint64(free_space, ed1), free_space_errno, errmsg); } free_pool_memory(results); Dmsg4(20, "leave update_freespace: free_space=%s freespace_ok=%d free_space_errno=%d have_media=%d\n", edit_uint64(free_space, ed1), !!is_freespace_ok(), free_space_errno, !!have_media()); return ok; }