discover/device-handler.h \
discover/discover-server.c \
discover/discover-server.h \
+ discover/devmapper.c \
+ discover/devmapper.h \
discover/event.c \
discover/event.h \
discover/params.c \
$(core_lib) \
$(UDEV_LIBS)
+discover_pb_discover_LDFLAGS = \
+ $(AM_LDFLAGS) \
+ -ldevmapper
+
discover_pb_discover_CPPFLAGS = \
$(AM_CPPFLAGS) \
-DLOCAL_STATE_DIR='"$(localstatedir)"' \
#include "device-handler.h"
#include "discover-server.h"
+#include "devmapper.h"
#include "user-event.h"
#include "platform.h"
#include "event.h"
struct discover_device **devices;
unsigned int n_devices;
+ struct ramdisk_device **ramdisks;
+ unsigned int n_ramdisks;
+
struct waitset *waitset;
struct waiter *timeout_waiter;
bool autoboot_enabled;
void device_handler_reinit(struct device_handler *handler)
{
struct discover_boot_option *opt, *tmp;
+ struct ramdisk_device *ramdisk;
unsigned int i;
device_handler_cancel_default(handler);
list_init(&handler->unresolved_boot_options);
/* drop all devices */
- for (i = 0; i < handler->n_devices; i++)
+ for (i = 0; i < handler->n_devices; i++) {
discover_server_notify_device_remove(handler->server,
handler->devices[i]->device);
+ ramdisk = handler->devices[i]->ramdisk;
+ talloc_free(handler->devices[i]);
+ talloc_free(ramdisk);
+ }
talloc_free(handler->devices);
handler->devices = NULL;
handler->n_devices = 0;
+ talloc_free(handler->ramdisks);
+ handler->ramdisks = NULL;
+ handler->n_ramdisks = 0;
device_handler_reinit_sources(handler);
}
} device_type_map[] = {
{ IPMI_BOOTDEV_NETWORK, DEVICE_TYPE_NETWORK },
{ IPMI_BOOTDEV_DISK, DEVICE_TYPE_DISK },
+ { IPMI_BOOTDEV_DISK, DEVICE_TYPE_USB },
{ IPMI_BOOTDEV_CDROM, DEVICE_TYPE_OPTICAL },
};
network_register_device(handler->network, device);
}
+void device_handler_add_ramdisk(struct device_handler *handler,
+ const char *path)
+{
+ struct ramdisk_device *dev;
+ unsigned int i;
+
+ if (!path)
+ return;
+
+ for (i = 0; i < handler->n_ramdisks; i++)
+ if (!strcmp(handler->ramdisks[i]->path, path))
+ return;
+
+ dev = talloc_zero(handler, struct ramdisk_device);
+ if (!dev) {
+ pb_log("Failed to allocate memory to track %s\n", path);
+ return;
+ }
+
+ dev->path = talloc_strdup(handler, path);
+
+ handler->ramdisks = talloc_realloc(handler, handler->ramdisks,
+ struct ramdisk_device *,
+ handler->n_ramdisks + 1);
+ if (!handler->ramdisks) {
+ pb_log("Failed to reallocate memory"
+ "- ramdisk tracking inconsistent!\n");
+ return;
+ }
+
+ handler->ramdisks[i] = dev;
+ i = handler->n_ramdisks++;
+}
+
+struct ramdisk_device *device_handler_get_ramdisk(
+ struct device_handler *handler)
+{
+ unsigned int i;
+ char *name;
+ dev_t id;
+
+ /* Check if free ramdisk exists */
+ for (i = 0; i < handler->n_ramdisks; i++)
+ if (!handler->ramdisks[i]->snapshot &&
+ !handler->ramdisks[i]->origin &&
+ !handler->ramdisks[i]->base)
+ return handler->ramdisks[i];
+
+ /* Otherwise create a new one */
+ name = talloc_asprintf(handler, "/dev/ram%d",
+ handler->n_ramdisks);
+ if (!name) {
+ pb_debug("Failed to allocate memory to name /dev/ram%d",
+ handler->n_ramdisks);
+ return NULL;
+ }
+
+ id = makedev(1, handler->n_ramdisks);
+ if (mknod(name, S_IFBLK, id)) {
+ if (errno == EEXIST) {
+ /* We haven't yet received updates for existing
+ * ramdisks - add and use this one */
+ pb_debug("Using untracked ramdisk %s\n", name);
+ } else {
+ pb_log("Failed to create new ramdisk %s: %s\n",
+ name, strerror(errno));
+ return NULL;
+ }
+ }
+ device_handler_add_ramdisk(handler, name);
+ talloc_free(name);
+
+ return handler->ramdisks[i];
+}
+
+void device_handler_release_ramdisk(struct discover_device *device)
+{
+ struct ramdisk_device *ramdisk = device->ramdisk;
+
+ talloc_free(ramdisk->snapshot);
+ talloc_free(ramdisk->origin);
+ talloc_free(ramdisk->base);
+
+ ramdisk->snapshot = ramdisk->origin = ramdisk->base = NULL;
+ ramdisk->sectors = 0;
+
+ device->ramdisk = NULL;
+}
+
/* Start discovery on a hotplugged device. The device will be in our devices
* array, but has only just been initialised by the hotplug source.
*/
handler->dry_run);
}
-static const char *fs_parameters(unsigned int rw_flags, const char *fstype)
+static const char *fs_parameters(struct discover_device *dev,
+ unsigned int rw_flags)
{
+ const char *fstype = discover_device_get_param(dev, "ID_FS_TYPE");
+
+ /* XFS journals are not cross-endian compatible; don't try recovery
+ * even if we have a snapshot */
+ if (!strncmp(fstype, "xfs", strlen("xfs")))
+ return "norecovery";
+
+ /* If we have a snapshot available allow touching the filesystem */
+ if (dev->ramdisk)
+ return "";
+
if ((rw_flags | MS_RDONLY) != MS_RDONLY)
return "";
- /* Avoid writing back to the disk on journaled filesystems */
+ /* Avoid writes due to journal replay if we don't have a snapshot */
if (!strncmp(fstype, "ext4", strlen("ext4")))
return "norecovery";
- if (!strncmp(fstype, "xfs", strlen("xfs")))
- return "norecovery";
return "";
}
+static inline const char *get_device_path(struct discover_device *dev)
+{
+ return dev->ramdisk ? dev->ramdisk->snapshot : dev->device_path;
+}
+
static bool check_existing_mount(struct discover_device *dev)
{
struct stat devstat, mntstat;
+ const char *device_path;
struct mntent *mnt;
FILE *fp;
int rc;
- rc = stat(dev->device_path, &devstat);
+ device_path = get_device_path(dev);
+
+ rc = stat(device_path, &devstat);
if (rc) {
pb_debug("%s: stat failed: %s\n", __func__, strerror(errno));
return false;
static int mount_device(struct discover_device *dev)
{
- const char *fstype;
+ const char *fstype, *device_path;
int rc;
if (!dev->device_path)
goto err_free;
}
+ device_path = get_device_path(dev);
+
pb_log("mounting device %s read-only\n", dev->device_path);
errno = 0;
- rc = mount(dev->device_path, dev->mount_path, fstype,
+ rc = mount(device_path, dev->mount_path, fstype,
MS_RDONLY | MS_SILENT,
- fs_parameters(MS_RDONLY, fstype));
+ fs_parameters(dev, MS_RDONLY));
if (!rc) {
dev->mounted = true;
dev->mounted_rw = false;
}
pb_log("couldn't mount device %s: mount failed: %s\n",
- dev->device_path, strerror(errno));
+ device_path, strerror(errno));
+
+ /* If mount fails clean up any snapshot */
+ devmapper_destroy_snapshot(dev);
pb_rmdir_recursive(mount_base(), dev->mount_path);
err_free:
static int umount_device(struct discover_device *dev)
{
+ const char *device_path;
int rc;
if (!dev->mounted || !dev->unmount)
return 0;
- pb_log("unmounting device %s\n", dev->device_path);
+ device_path = get_device_path(dev);
+
+ pb_log("unmounting device %s\n", device_path);
rc = umount(dev->mount_path);
if (rc)
return -1;
dev->mounted = false;
+ devmapper_destroy_snapshot(dev);
pb_rmdir_recursive(mount_base(), dev->mount_path);
int device_request_write(struct discover_device *dev, bool *release)
{
- const char *fstype;
+ const char *fstype, *device_path;
+ const struct config *config;
int rc;
*release = false;
+ config = config_get();
+ if (!config->allow_writes)
+ return -1;
+
if (!dev->mounted)
return -1;
fstype = discover_device_get_param(dev, "ID_FS_TYPE");
- pb_log("remounting device %s read-write\n", dev->device_path);
+ device_path = get_device_path(dev);
+
+ pb_log("remounting device %s read-write\n", device_path);
rc = umount(dev->mount_path);
if (rc) {
- pb_log("Failed to unmount %s\n", dev->mount_path);
+ pb_log("Failed to unmount %s: %s\n",
+ dev->mount_path, strerror(errno));
return -1;
}
- rc = mount(dev->device_path, dev->mount_path, fstype,
+
+ rc = mount(device_path, dev->mount_path, fstype,
MS_SILENT,
- fs_parameters(MS_REMOUNT, fstype));
+ fs_parameters(dev, MS_REMOUNT));
if (rc)
goto mount_ro;
return 0;
mount_ro:
- pb_log("Unable to remount device %s read-write\n", dev->device_path);
- rc = mount(dev->device_path, dev->mount_path, fstype,
+ pb_log("Unable to remount device %s read-write: %s\n",
+ device_path, strerror(errno));
+ if (mount(device_path, dev->mount_path, fstype,
MS_RDONLY | MS_SILENT,
- fs_parameters(MS_RDONLY, fstype));
- if (rc)
- pb_log("Unable to recover mount for %s\n", dev->device_path);
+ fs_parameters(dev, MS_RDONLY)))
+ pb_log("Unable to recover mount for %s: %s\n",
+ device_path, strerror(errno));
return -1;
}
void device_release_write(struct discover_device *dev, bool release)
{
- const char *fstype;
+ const char *fstype, *device_path;
+ int rc = 0;
if (!release)
return;
+ device_path = get_device_path(dev);
+
fstype = discover_device_get_param(dev, "ID_FS_TYPE");
- pb_log("remounting device %s read-only\n", dev->device_path);
- mount(dev->device_path, dev->mount_path, "",
- MS_REMOUNT | MS_RDONLY | MS_SILENT,
- fs_parameters(MS_RDONLY, fstype));
- dev->mounted_rw = false;
+ pb_log("remounting device %s read-only\n", device_path);
+
+ if (umount(dev->mount_path)) {
+ pb_log("Failed to unmount %s\n", dev->mount_path);
+ return;
+ }
+ dev->mounted_rw = dev->mounted = false;
+
+ if (dev->ramdisk) {
+ devmapper_merge_snapshot(dev);
+ /* device_path becomes stale after merge */
+ device_path = get_device_path(dev);
+ }
+
+ mount(device_path, dev->mount_path, fstype,
+ MS_RDONLY | MS_SILENT,
+ fs_parameters(dev, MS_RDONLY));
+ if (rc)
+ pb_log("Failed to remount %s read-only: %s\n",
+ device_path, strerror(errno));
+ else
+ dev->mounted = true;
}
#else
char *mount_path;
const char *device_path;
+ struct ramdisk_device *ramdisk;
bool mounted;
bool mounted_rw;
bool unmount;
void *test_data;
};
+struct ramdisk_device {
+ const char *path;
+ char *snapshot;
+ char *origin;
+ char *base;
+ unsigned int sectors;
+};
+
struct device_handler *device_handler_init(struct discover_server *server,
struct waitset *waitset, int dry_run);
const char *id);
void device_handler_add_device(struct device_handler *handler,
struct discover_device *device);
+void device_handler_add_ramdisk(struct device_handler *handler,
+ const char *path);
+struct ramdisk_device *device_handler_get_ramdisk(
+ struct device_handler *handler);
+void device_handler_release_ramdisk(struct discover_device *device);
int device_handler_discover(struct device_handler *handler,
struct discover_device *dev);
int device_handler_dhcp(struct device_handler *handler,
--- /dev/null
+#include <talloc/talloc.h>
+#include <types/types.h>
+#include <log/log.h>
+#include <errno.h>
+#include <string.h>
+
+#include "libdevmapper.h"
+#include "devmapper.h"
+#include "platform.h"
+
+#define MERGE_INTERVAL_US 200000
+
+struct target {
+ long unsigned int start_sector;
+ long unsigned int end_sector;
+ char *ttype;
+ char *params;
+};
+
+/* Return the number of sectors on a block device. Zero represents an error */
+static unsigned int get_block_sectors(struct discover_device *device)
+{
+ const char *tmp;
+ long unsigned int sectors;
+
+ tmp = discover_device_get_param(device, "ID_PART_ENTRY_SIZE");
+ if (!tmp) {
+ pb_debug("Could not retrieve ID_PART_ENTRY_SIZE for %s\n",
+ device->device_path);
+ return 0;
+ }
+
+ errno = 0;
+ sectors = strtoul(tmp, NULL, 0);
+ if (errno) {
+ pb_debug("Error reading sector count for %s: %s\n",
+ device->device_path, strerror(errno));
+ sectors = 0;
+ }
+
+ return sectors;
+}
+
+/*
+ * The system's libdm may or may not have udev sync support. Tell libdm
+ * to manage the creation of device nodes itself rather than waiting on udev
+ * to do it
+ */
+static inline int set_cookie(struct dm_task *task, uint32_t *cookie)
+{
+ uint16_t udev_rules = 0;
+ *cookie = 0;
+
+ dm_udev_set_sync_support(0);
+ udev_rules |= DM_UDEV_DISABLE_DM_RULES_FLAG |
+ DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG;
+
+ return dm_task_set_cookie(task, cookie, udev_rules);
+}
+
+static bool snapshot_merge_complete(const char *dm_name)
+{
+ long long unsigned int sectors, meta_sectors;
+ char *params = NULL, *target_type = NULL;
+ uint64_t start, length;
+ struct dm_task *task;
+ bool result = true;
+ int n;
+
+ task = dm_task_create(DM_DEVICE_STATUS);
+ if (!task) {
+ pb_log("%s: Error creating task\n", __func__);
+ return result;
+ }
+
+ if (!dm_task_set_name(task, dm_name)) {
+ pb_log("No dm-device named '%s'\n", dm_name);
+ goto out;
+ }
+
+ if (!dm_task_run(task)) {
+ pb_log("Unable to retrieve status for '%s'\n", dm_name);
+ goto out;
+ }
+
+ dm_get_next_target(task, NULL, &start, &length, &target_type, ¶ms);
+
+ if (!params) {
+ pb_log("Unable to retrieve params for '%s'\n", dm_name);
+ goto out;
+ }
+
+ if (!strncmp(params, "Invalid", strlen("Invalid"))) {
+ pb_log("dm-device %s has become invalid\n", dm_name);
+ goto out;
+ }
+
+ /* Merge is complete when metadata sectors are the only sectors
+ * allocated - see Documentation/device-mapper/snapshot.txt */
+ n = sscanf(params, "%llu/%*u %llu", §ors, &meta_sectors);
+ if (n != 2) {
+ pb_log("%s unexpected status: '%s'\n", dm_name, params);
+ goto out;
+ }
+ result = sectors == meta_sectors;
+
+ pb_debug("%s merging; %llu sectors, %llu metadata sectors\n",
+ dm_name, sectors, meta_sectors);
+
+out:
+ /* In case of error or an invalid snapshot return true so callers will
+ * move on and catch the error */
+ dm_task_destroy(task);
+ return result;
+}
+
+/* Resume or suspend dm device */
+static int set_device_active(const char *dm_name, bool active)
+{
+ struct dm_task *task;
+ uint32_t cookie;
+ int rc = -1;
+
+ if (active)
+ task = dm_task_create(DM_DEVICE_RESUME);
+ else
+ task = dm_task_create(DM_DEVICE_SUSPEND);
+
+ if (!task) {
+ pb_log("%s: Could not create dm_task\n", __func__);
+ return rc;
+ }
+
+ if (!dm_task_set_name(task, dm_name)) {
+ pb_log("No dm-device named '%s'\n", dm_name);
+ goto out;
+ }
+
+ if (!set_cookie(task, &cookie))
+ goto out;
+
+ if (!dm_task_run(task)) {
+ pb_log("Unable to %s device '%s'\n",
+ active ? "resume" : "suspend", dm_name);
+ goto out;
+ }
+
+ rc = 0;
+
+ /* Wait for /dev/mapper/ entries to be updated */
+ dm_udev_wait(cookie);
+
+out:
+ dm_task_destroy(task);
+ return rc;
+}
+
+/* Run a DM_DEVICE_CREATE task with provided table (ttype and params) */
+static int run_create_task(const char *dm_name, const struct target *target)
+{
+ struct dm_task *task;
+ uint32_t cookie;
+
+ pb_debug("%s: %lu %lu '%s' '%s'\n", __func__,
+ target->start_sector, target->end_sector,
+ target->ttype, target->params);
+
+ task = dm_task_create(DM_DEVICE_CREATE);
+ if (!task) {
+ pb_log("Error creating new dm-task\n");
+ return -1;
+ }
+
+ if (!dm_task_set_name(task, dm_name))
+ return -1;
+
+ if (!dm_task_add_target(task, target->start_sector, target->end_sector,
+ target->ttype, target->params))
+ return -1;
+
+ if (!dm_task_set_add_node(task, DM_ADD_NODE_ON_CREATE))
+ return -1;
+
+ if (!set_cookie(task, &cookie))
+ return -1;
+
+ if (!dm_task_run(task)) {
+ pb_log("Error executing dm-task\n");
+ return -1;
+ }
+
+ /* Wait for /dev/mapper/ entry to appear */
+ dm_udev_wait(cookie);
+
+ dm_task_destroy(task);
+ return 0;
+}
+
+static int create_base(struct discover_device *device)
+{
+ struct target target;
+ char *name = NULL;
+ int rc = -1;
+
+ if (!device->ramdisk)
+ return rc;
+
+ target.start_sector = 0;
+ target.end_sector = device->ramdisk->sectors;
+
+ target.ttype = talloc_asprintf(device, "linear");
+ target.params = talloc_asprintf(device, "%s 0", device->device_path);
+ if (!target.ttype || !target.params) {
+ pb_log("Failed to allocate map parameters\n");
+ goto out;
+ }
+
+ name = talloc_asprintf(device, "%s-base", device->device->id);
+ if (!name || run_create_task(name, &target))
+ goto out;
+
+ device->ramdisk->base = talloc_asprintf(device, "/dev/mapper/%s-base",
+ device->device->id);
+ if (!device->ramdisk->base) {
+ pb_log("Failed to track new device /dev/mapper/%s-base\n",
+ device->device->id);
+ goto out;
+ }
+
+ rc = 0;
+
+out:
+ talloc_free(name);
+ talloc_free(target.params);
+ talloc_free(target.ttype);
+ return rc;
+}
+
+static int create_origin(struct discover_device *device)
+{
+ struct target target;
+ char *name = NULL;
+ int rc = -1;
+
+ if (!device->ramdisk || !device->ramdisk->base)
+ return -1;
+
+ target.start_sector = 0;
+ target.end_sector = device->ramdisk->sectors;
+
+ target.ttype = talloc_asprintf(device, "snapshot-origin");
+ target.params = talloc_asprintf(device, "%s", device->ramdisk->base);
+ if (!target.ttype || !target.params) {
+ pb_log("Failed to allocate map parameters\n");
+ goto out;
+ }
+
+ name = talloc_asprintf(device, "%s-origin", device->device->id);
+ if (!name || run_create_task(name, &target))
+ goto out;
+
+ device->ramdisk->origin = talloc_asprintf(device,
+ "/dev/mapper/%s-origin",
+ device->device->id);
+ if (!device->ramdisk->origin) {
+ pb_log("Failed to track new device /dev/mapper/%s-origin\n",
+ device->device->id);
+ goto out;
+ }
+
+ rc = 0;
+
+out:
+ talloc_free(name);
+ talloc_free(target.params);
+ talloc_free(target.ttype);
+ return rc;
+}
+
+static int create_snapshot(struct discover_device *device)
+{
+ struct target target;
+ int rc = -1;
+
+ if (!device->ramdisk || !device->ramdisk->base ||
+ !device->ramdisk->origin)
+ return -1;
+
+ target.start_sector = 0;
+ target.end_sector = device->ramdisk->sectors;
+
+ target.ttype = talloc_asprintf(device, "snapshot");
+ target.params = talloc_asprintf(device, "%s %s P 8",
+ device->ramdisk->base, device->ramdisk->path);
+ if (!target.ttype || !target.params) {
+ pb_log("Failed to allocate snapshot parameters\n");
+ goto out;
+ }
+
+ if (run_create_task(device->device->id, &target))
+ goto out;
+
+ device->ramdisk->snapshot = talloc_asprintf(device, "/dev/mapper/%s",
+ device->device->id);
+ if (!device->ramdisk->snapshot) {
+ pb_log("Failed to track new device /dev/mapper/%s\n",
+ device->device->id);
+ goto out;
+ }
+
+ rc = 0;
+
+out:
+ talloc_free(target.params);
+ talloc_free(target.ttype);
+ return rc;
+}
+
+int devmapper_init_snapshot(struct device_handler *handler,
+ struct discover_device *device)
+{
+ struct ramdisk_device *ramdisk;
+
+ if (config_get()->disable_snapshots)
+ return 0;
+
+ ramdisk = device_handler_get_ramdisk(handler);
+ if (!ramdisk) {
+ pb_log("No ramdisk available for snapshot %s\n",
+ device->device->id);
+ return -1;
+ }
+
+ ramdisk->sectors = get_block_sectors(device);
+ if (!ramdisk->sectors) {
+ pb_log("Error retreiving sectors for %s\n",
+ device->device->id);
+ return -1;
+ }
+
+ device->ramdisk = ramdisk;
+
+ /* Create linear map */
+ if (create_base(device)) {
+ pb_log("Error creating linear base\n");
+ goto err;
+ }
+
+ /* Create snapshot-origin */
+ if (create_origin(device)) {
+ pb_log("Error creating snapshot-origin\n");
+ goto err;
+ }
+
+ if (set_device_active(device->ramdisk->origin, false)) {
+ pb_log("Failed to suspend origin\n");
+ goto err;
+ }
+
+ /* Create snapshot */
+ if (create_snapshot(device)) {
+ pb_log("Error creating snapshot\n");
+ goto err;
+ }
+
+ if (set_device_active(device->ramdisk->origin, true)) {
+ pb_log("Failed to resume origin\n");
+ goto err;
+ }
+
+ pb_log("Snapshot successfully created for %s\n", device->device->id);
+
+ return 0;
+
+err:
+ pb_log("Error creating snapshot devices for %s\n", device->device->id);
+ devmapper_destroy_snapshot(device);
+ return -1;
+}
+
+/* Destroy specific dm device */
+static int destroy_device(const char *dm_name)
+{
+ struct dm_task *task;
+ uint32_t cookie;
+ int rc = -1;
+
+ task = dm_task_create(DM_DEVICE_REMOVE);
+ if (!task) {
+ pb_log("%s: could not create dm_task\n", __func__);
+ return -1;
+ }
+
+ if (!dm_task_set_name(task, dm_name)) {
+ pb_log("No dm device named '%s'\n", dm_name);
+ goto out;
+ }
+
+ if (!set_cookie(task, &cookie))
+ goto out;
+
+ if (!dm_task_run(task)) {
+ pb_log("Unable to remove device '%s'\n", dm_name);
+ goto out;
+ }
+
+ rc = 0;
+
+ /* Wait for /dev/mapper/ entries to be removed */
+ dm_udev_wait(cookie);
+
+out:
+ dm_task_destroy(task);
+ return rc;
+}
+
+/* Destroy all dm devices related to a discover_device's snapshot */
+int devmapper_destroy_snapshot(struct discover_device *device)
+{
+ int rc = -1;
+
+ if (!device->ramdisk)
+ return 0;
+
+ if (device->mounted) {
+ pb_log("Can not remove snapshot: %s is mounted\n",
+ device->device->id);
+ return -1;
+ }
+
+ /* Clean up dm devices in order */
+ if (device->ramdisk->snapshot)
+ if (destroy_device(device->ramdisk->snapshot))
+ goto out;
+
+ if (device->ramdisk->origin)
+ if (destroy_device(device->ramdisk->origin))
+ goto out;
+
+ if (device->ramdisk->base)
+ if (destroy_device(device->ramdisk->base))
+ goto out;
+
+ rc = 0;
+out:
+ if (rc)
+ pb_log("Warning: %s snapshot not cleanly removed\n",
+ device->device->id);
+ device_handler_release_ramdisk(device);
+ return rc;
+}
+
+static int reload_snapshot(struct discover_device *device, bool merge)
+{
+ struct target target;
+ struct dm_task *task;
+ int rc = -1;
+
+ target.start_sector = 0;
+ target.end_sector = device->ramdisk->sectors;
+
+ if (merge) {
+ target.ttype = talloc_asprintf(device, "snapshot-merge");
+ target.params = talloc_asprintf(device, "%s %s P 8",
+ device->ramdisk->base, device->ramdisk->path);
+ } else {
+ target.ttype = talloc_asprintf(device, "snapshot-origin");
+ target.params = talloc_asprintf(device, "%s",
+ device->ramdisk->base);
+ }
+ if (!target.ttype || !target.params) {
+ pb_log("%s: failed to allocate parameters\n", __func__);
+ goto err1;
+ }
+
+ task = dm_task_create(DM_DEVICE_RELOAD);
+ if (!task) {
+ pb_log("%s: Error creating task\n", __func__);
+ goto err1;
+ }
+
+ if (!dm_task_set_name(task, device->ramdisk->origin)) {
+ pb_log("No dm-device named '%s'\n", device->ramdisk->origin);
+ goto err2;
+ }
+
+ if (!dm_task_add_target(task, target.start_sector, target.end_sector,
+ target.ttype, target.params)) {
+ pb_log("%s: Failed to set target\n", __func__);
+ goto err2;
+ }
+
+ if (!dm_task_run(task)) {
+ pb_log("Failed to reload %s\n", device->ramdisk->origin);
+ goto err2;
+ }
+
+ rc = 0;
+err2:
+ dm_task_destroy(task);
+err1:
+ talloc_free(target.ttype);
+ talloc_free(target.params);
+ return rc;
+}
+
+int devmapper_merge_snapshot(struct discover_device *device)
+{
+ if (device->mounted) {
+ pb_log("%s: %s still mounted\n", __func__, device->device->id);
+ return -1;
+ }
+
+ /* Suspend origin device */
+ if (set_device_active(device->ramdisk->origin, false)) {
+ pb_log("%s: failed to suspend %s\n",
+ __func__, device->ramdisk->origin);
+ return -1;
+ }
+
+ /* Destroy snapshot */
+ if (destroy_device(device->ramdisk->snapshot)) {
+ /* The state of the snapshot is unknown, but try to
+ * resume to allow the snapshot to be remounted */
+ set_device_active(device->ramdisk->origin, true);
+ return -1;
+ }
+ talloc_free(device->ramdisk->snapshot);
+ device->ramdisk->snapshot = NULL;
+
+ /* Reload origin device for merging */
+ reload_snapshot(device, true);
+
+ /* Resume origin device */
+ set_device_active(device->ramdisk->origin, true);
+
+ /* Block until merge complete */
+ while (!snapshot_merge_complete(device->ramdisk->origin))
+ usleep(MERGE_INTERVAL_US);
+
+ /* Suspend origin device */
+ set_device_active(device->ramdisk->origin, false);
+
+ /* Reload origin device */
+ reload_snapshot(device, false);
+
+ /* Re-create snapshot */
+ if (create_snapshot(device))
+ return -1;
+
+ /* Resume origin device */
+ return set_device_active(device->ramdisk->origin, true);
+}
--- /dev/null
+#ifndef _DEVMAPPER_H
+#define _DEVMAPPER_H
+
+#include "device-handler.h"
+
+int devmapper_init_snapshot(struct device_handler *handler,
+ struct discover_device *device);
+int devmapper_destroy_snapshot(struct discover_device *device);
+int devmapper_merge_snapshot(struct discover_device *device);
+
+#endif /* _DEVMAPPER_H */
"petitboot,bootdevs",
"petitboot,language",
"petitboot,debug?",
+ "petitboot,write?",
+ "petitboot,snapshots?",
NULL,
};
val = get_param(platform, "petitboot,debug?");
config->debug = val && !strcmp(val, "true");
}
+
+ val = get_param(platform, "petitboot,write?");
+ if (val)
+ config->allow_writes = !strcmp(val, "true");
+
+ val = get_param(platform, "petitboot,snapshots?");
+ if (val)
+ config->disable_snapshots = !strcmp(val, "false");
}
static char *iface_config_str(void *ctx, struct interface_config *config)
val = config->lang ?: "";
update_string_config(platform, "petitboot,language", val);
+ if (config->allow_writes == defaults->allow_writes)
+ val = "";
+ else
+ val = config->allow_writes ? "true" : "false";
+ update_string_config(platform, "petitboot,write?", val);
+
update_network_config(platform, config);
update_bootdev_config(platform, config);
if (config->safe_mode)
pb_log(" safe mode: active\n");
+ if (config->disable_snapshots)
+ pb_log(" dm-snapshots disabled\n");
+
for (i = 0; i < config->network.n_interfaces; i++) {
struct interface_config *ifconf =
config->network.interfaces[i];
config->network.n_dns_servers = 0;
config->safe_mode = false;
config->lang = NULL;
+ config->allow_writes = true;
+ config->disable_snapshots = false;
config->n_autoboot_opts = 2;
config->autoboot_opts = talloc_array(config, struct autoboot_option,
#include "pb-discover.h"
#include "device-handler.h"
#include "cdrom.h"
+#include "devmapper.h"
/* We set a default monitor buffer size, as we may not process monitor
* events while performing device discvoery. systemd uses a 128M buffer, so
const char *name)
{
struct discover_device *ddev;
+ unsigned int i = 0;
const char *typestr;
const char *uuid;
const char *path;
const char *node;
const char *prop;
const char *type;
- bool cdrom;
+ const char *devname;
+ const char *ignored_types[] = {
+ "linux_raid_member",
+ "swap",
+ "LVM2_member",
+ NULL,
+ };
+ bool cdrom, usb;
typestr = udev_device_get_devtype(dev);
if (!typestr) {
node = udev_device_get_devnode(dev);
path = udev_device_get_devpath(dev);
- if (path && (strstr(path, "virtual/block/loop")
- || strstr(path, "virtual/block/ram"))) {
+ if (path && strstr(path, "virtual/block/loop")) {
pb_log("SKIP: %s: ignored (path=%s)\n", name, path);
return 0;
}
+ if (path && strstr(path, "virtual/block/ram")) {
+ device_handler_add_ramdisk(udev->handler, node);
+ return 0;
+ }
+
cdrom = node && !!udev_device_get_property_value(dev, "ID_CDROM");
if (cdrom) {
/* CDROMs require a little initialisation, to get
}
}
+ /* If our environment's udev can recognise them explictly skip any
+ * device mapper devices we encounter */
+ devname = udev_device_get_property_value(dev, "DM_NAME");
+ if (devname) {
+ pb_debug("SKIP: dm-device %s\n", devname);
+ return 0;
+ }
+
type = udev_device_get_property_value(dev, "ID_FS_TYPE");
if (!type) {
pb_log("SKIP: %s: no ID_FS_TYPE property\n", name);
return 0;
}
+ while (ignored_types[i]) {
+ if (!strncmp(type, ignored_types[i], strlen(ignored_types[i]))) {
+ pb_log("SKIP: %s: ignore '%s' filesystem\n", name, type);
+ return 0;
+ }
+ i++;
+ }
+
/* We may see multipath devices; they'll have the same uuid as an
* existing device, so only parse the first. */
uuid = udev_device_get_property_value(dev, "ID_FS_UUID");
prop = udev_device_get_property_value(dev, "ID_FS_LABEL");
if (prop)
ddev->label = talloc_strdup(ddev, prop);
- ddev->device->type = cdrom ? DEVICE_TYPE_OPTICAL : DEVICE_TYPE_DISK;
+
+ usb = !!udev_device_get_property_value(dev, "ID_USB_DRIVER");
+ if (cdrom)
+ ddev->device->type = DEVICE_TYPE_OPTICAL;
+ else
+ ddev->device->type = usb ? DEVICE_TYPE_USB : DEVICE_TYPE_DISK;
udev_setup_device_params(dev, ddev);
+ /* Create a snapshot for all disks, unless it is an assembled RAID array */
+ if ((ddev->device->type == DEVICE_TYPE_DISK ||
+ ddev->device->type == DEVICE_TYPE_USB) &&
+ !udev_device_get_property_value(dev, "MD_LEVEL"))
+ devmapper_init_snapshot(udev->handler, ddev);
+
device_handler_discover(udev->handler, ddev);
return 0;
lib/fold/fold.h \
lib/fold/fold.c \
lib/i18n/i18n.h \
+ lib/i18n/i18n.c \
lib/log/log.h \
lib/log/log.c \
lib/list/list.c \
assert(bytes != (size_t)-1);
- /* we'll get a zero size for the nul terminator */
- if (!bytes) {
+ /* we'll get a zero size for the nul terminator, or (size_t) -2
+ * if we've reached the end of the buffer */
+ if (!bytes || bytes == (size_t) -2) {
line_cb(arg, start, end - start);
break;
}
--- /dev/null
+/*
+ * Copyright (C) 2013 IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define _XOPEN_SOURCE
+
+#include <string.h>
+#include <stdlib.h>
+#include <wchar.h>
+
+#include <i18n/i18n.h>
+
+/* Return the number of columns required to display a localised string */
+int strncols(const char *str)
+{
+ int wlen, ncols;
+ wchar_t *wstr;
+
+ wlen = mbstowcs(NULL, str, 0);
+ if (wlen <= 0)
+ return wlen;
+
+ wstr = malloc(sizeof(wchar_t) * wlen + 1);
+ if (!wstr)
+ return -1;
+
+ wlen = mbstowcs(wstr, str, wlen);
+ if (wlen <= 0) {
+ free(wstr);
+ return wlen;
+ }
+
+ ncols = wcswidth(wstr, wlen);
+
+ free(wstr);
+ return ncols;
+}
#define _(x) gettext(x)
+int strncols(const char *str);
+
#endif /* I18N_H */
dest->ipmi_bootdev = src->ipmi_bootdev;
dest->ipmi_bootdev_persistent = src->ipmi_bootdev_persistent;
+ dest->allow_writes = src->allow_writes;
+
if (src->lang && strlen(src->lang))
dest->lang = talloc_strdup(dest, src->lang);
else
len += 4 + 4; /* ipmi_bootdev, ipmi_bootdev_persistent */
+ len += 4; /* allow_writes */
+
len += 4 + optional_strlen(config->lang);
return len;
*(uint32_t *)pos = config->ipmi_bootdev_persistent;
pos += 4;
+ *(uint32_t *)pos = config->allow_writes;
+ pos += 4;
+
pos += pb_protocol_serialise_string(pos, config->lang);
assert(pos <= buf + buf_len);
goto out;
config->ipmi_bootdev_persistent = !!tmp;
+ if (read_u32(&pos, &len, &tmp))
+ goto out;
+ config->allow_writes = !!tmp;
+
if (read_string(config, &pos, &len, &str))
goto out;
switch (type) {
case DEVICE_TYPE_DISK:
return _("Disk");
+ case DEVICE_TYPE_USB:
+ return _("USB");
case DEVICE_TYPE_OPTICAL:
- return _("Optical");
+ return _("CD/DVD");
case DEVICE_TYPE_NETWORK:
return _("Network");
case DEVICE_TYPE_ANY:
switch (type) {
case DEVICE_TYPE_DISK:
return "disk";
+ case DEVICE_TYPE_USB:
+ return "usb";
case DEVICE_TYPE_OPTICAL:
return "optical";
case DEVICE_TYPE_NETWORK:
{
if (!strncmp(str, "disk", strlen("disk")))
return DEVICE_TYPE_DISK;
+ if (!strncmp(str, "usb", strlen("usb")))
+ return DEVICE_TYPE_USB;
if (!strncmp(str, "optical", strlen("optical")))
return DEVICE_TYPE_OPTICAL;
if (!strncmp(str, "network", strlen("network")))
enum device_type {
DEVICE_TYPE_NETWORK,
DEVICE_TYPE_DISK,
+ DEVICE_TYPE_USB,
DEVICE_TYPE_OPTICAL,
DEVICE_TYPE_ANY,
DEVICE_TYPE_UNKNOWN,
unsigned int ipmi_bootdev;
bool ipmi_bootdev_persistent;
+ bool allow_writes;
+
char *lang;
/* not user-settable */
+ bool disable_snapshots;
bool safe_mode;
bool debug;
};
msgstr ""
"Project-Id-Version: petitboot 20140623-g89bd2ed2-dirty\n"
"Report-Msgid-Bugs-To: Geoff Levand <geoff@infradead.org>\n"
-"POT-Creation-Date: 2014-10-13 09:24+1100\n"
+"POT-Creation-Date: 2015-08-19 14:19+1000\n"
"PO-Revision-Date: 2014-06-24 13:56+0800\n"
"Last-Translator: Jeremy Kerr <jk@ozlabs.org>\n"
"Language-Team: German\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
msgid "running boot hooks"
-msgstr "Aktive Boot-Anbindungspunkte (Hooks)"
+msgstr "Aktive Bootanbindungspunkte"
#, c-format
msgid "Couldn't load %s"
msgid "No IP / mask values are set"
msgstr "Keine Werte für IP/Maske festgelegt"
+msgid "Select a boot device to add"
+msgstr "Wählen Sie eine Booteinheit aus, die hinzugefügt werden soll"
+
msgid "Waiting for configuration data..."
msgstr "Warten auf Konfigurationsdaten..."
-msgid "Autoboot:"
-msgstr "Autom. Booten:"
+#, fuzzy
+msgid "Add Device"
+msgstr "Einheit:"
-msgid "Don't autoboot"
-msgstr "Kein automatisches Booten"
+msgid "Clear"
+msgstr "Inhalt löschen"
-msgid "Autoboot from any disk/network device"
-msgstr "Von jeder Platte/Netzeinheit automatisch booten"
+msgid "Clear & Boot Any"
+msgstr "Inhalt löschen & beliebige booten"
-msgid "Only autoboot from a specific disk/network device"
-msgstr "Nur von bestimmter Platte/Netzeinheit autom. booten"
+#, fuzzy
+msgid "Boot Order:"
+msgstr "Bootargumente:"
+
+msgid "(None)"
+msgstr "(Keine Angabe)"
#, c-format
msgid "disk: %s [uuid: %s]"
msgid "net: %s [mac: %s]"
msgstr "Netz: %s [MAC: %s]"
+#, fuzzy
+msgid "Any Device"
+msgstr "Einheit:"
+
#, c-format
-msgid "Unknown UUID: %s"
-msgstr "Unbekannte UUID: %s"
+msgid "Any %s device"
+msgstr "Jede %s-Einheit"
msgid "Timeout:"
msgstr "Zeitlimit:"
msgid "seconds"
msgstr "Sekunden"
+#, c-format
+msgid "%s IPMI boot option: %s"
+msgstr "IPMI-Bootoption für %s: %s"
+
+msgid "Clear option:"
+msgstr "Option 'Inhalt löschen':"
+
msgid "Network:"
msgstr "Netz:"
msgid "Selecting 'OK' will exit safe mode"
msgstr "Durch die Auswahl von 'OK' wird der abgesicherte Modus beendet"
+#, fuzzy
+msgid "Disk R/W:"
+msgstr "Platte"
+
+msgid "Prevent all writes to disk"
+msgstr "Alle Schreibvorgänge auf die Platte verhindern"
+
+msgid "Allow bootloader scripts to modify disks"
+msgstr ""
+"Zulassen, dass mit Scripts des Bootladeprogramms Platten geändert werden"
+
msgid "Petitboot System Configuration"
msgstr "Petitboot-Systemkonfiguration"
"host/pxeconffile or http://host/pxeconffile"
msgstr ""
"Geben Sie hier eine gültige URL ein, um eine ferne Konfigurationsdatei vom "
-"Typ 'pxe-boot' abzurufen, und analysieren sie sie.\n"
+"Typ 'pxe-boot' abzurufen, und analysieren Sie sie.\n"
"\n"
"URLs haben das Format 'Schema://host/path/to/pxeconffile'. Beispiele: tftp://"
"host/pxeconffile oder http://host/pxeconffile"
"Beispiel: root=/dev/sda1 console=hvc0\n"
"\n"
+#, fuzzy
msgid ""
-"Autoboot: There are three possible options for automatic-boot hehaviour:\n"
-"\n"
-"Don't autoboot: boot options will be listed in the petitboot menu, but none "
-"will be booted automatically. User interaction will be required to continue "
+"Autoboot: Specify which devices to autoboot from.\n"
+"\n"
+"By selecting the 'Add Device' button new devices can be added to the "
+"autoboot list, either by UUID, MAC address, or device type. Once added to "
+"the boot order, the priority of devices can be changed with the 'left' and "
+"'right' keys Devices can be individually removed from the boot order with "
+"the minus key. Use this option if you have multiple operating system images "
+"installed.\n"
+"\n"
+"To autoboot from any device, select the 'Clear & Boot Any' button. In this "
+"case, any boot option that is marked as a default (by bootloader "
+"configuration) will be booted automatically after a timeout. Use this option "
+"if you want to quickly boot your system without changing any boot option "
+"settings. This is the typical configuration.\n"
+"\n"
+"To disable autoboot, select the 'Clear' button, which will clear the boot "
+"order. With autoboot disabled, user interaction will be required to continue "
"past the petitboot menu. Use this option if you want the machine to wait for "
"an explicit boot selection, or want to interact with petitboot before "
"booting the system\n"
"\n"
-"Autoboot from any disk/network device: any boot option that is marked as a "
-"default (by bootloader configuration) will be booted automatically after a "
-"timeout. Use this option if you want to quickly boot your system without "
-"changing any boot option settings. This is the typical configuration.\n"
-"\n"
-"Only autoboot from a specific disk/network device: only boot options from a "
-"single device (specifed here) will be booted automatically after a timeout. "
-"Use this option if you have multiple operating system images installed.\n"
-"\n"
"Timeout: Specify the length of time, in seconds, that the main menu will be "
"displayed before the default boot option is started. This option is only "
"displayed if autoboot is enabled.\n"
msgid "Usage"
msgstr "Verwendung"
+
+#~ msgid "Autoboot:"
+#~ msgstr "Autoboot:"
+
+#~ msgid "Don't autoboot"
+#~ msgstr "Don't autoboot"
+
+#~ msgid "Autoboot from any disk/network device"
+#~ msgstr "Autoboot from any disk/network device"
+
+#~ msgid "Only autoboot from a specific disk/network device"
+#~ msgstr "Only autoboot from a specific disk/network device"
+
+#~ msgid "Unknown UUID: %s"
+#~ msgstr "Unknown UUID: %s"
msgstr ""
"Project-Id-Version: petitboot 20140623-g89bd2ed2-dirty\n"
"Report-Msgid-Bugs-To: Geoff Levand <geoff@infradead.org>\n"
-"POT-Creation-Date: 2014-10-13 09:24+1100\n"
+"POT-Creation-Date: 2015-08-19 14:19+1000\n"
"PO-Revision-Date: 2014-06-24 13:56+0800\n"
"Last-Translator: Jeremy Kerr <jk@ozlabs.org>\n"
"Language-Team: English\n"
msgid "No IP / mask values are set"
msgstr "No IP / mask values are set"
+msgid "Select a boot device to add"
+msgstr ""
+
msgid "Waiting for configuration data..."
msgstr "Waiting for configuration data..."
-msgid "Autoboot:"
-msgstr "Autoboot:"
+#, fuzzy
+msgid "Add Device"
+msgstr "Device:"
+
+msgid "Clear"
+msgstr ""
-msgid "Don't autoboot"
-msgstr "Don't autoboot"
+msgid "Clear & Boot Any"
+msgstr ""
-msgid "Autoboot from any disk/network device"
-msgstr "Autoboot from any disk/network device"
+#, fuzzy
+msgid "Boot Order:"
+msgstr "Boot arguments:"
-msgid "Only autoboot from a specific disk/network device"
-msgstr "Only autoboot from a specific disk/network device"
+msgid "(None)"
+msgstr ""
#, c-format
msgid "disk: %s [uuid: %s]"
msgid "net: %s [mac: %s]"
msgstr "net: %s [mac: %s]"
+#, fuzzy
+msgid "Any Device"
+msgstr "Device:"
+
#, c-format
-msgid "Unknown UUID: %s"
-msgstr "Unknown UUID: %s"
+msgid "Any %s device"
+msgstr ""
msgid "Timeout:"
msgstr "Timeout:"
msgid "seconds"
msgstr "seconds"
+#, c-format
+msgid "%s IPMI boot option: %s"
+msgstr ""
+
+msgid "Clear option:"
+msgstr ""
+
msgid "Network:"
msgstr "Network:"
msgid "Selecting 'OK' will exit safe mode"
msgstr "Selecting 'OK' will exit safe mode"
+#, fuzzy
+msgid "Disk R/W:"
+msgstr "Disk"
+
+msgid "Prevent all writes to disk"
+msgstr ""
+
+msgid "Allow bootloader scripts to modify disks"
+msgstr ""
+
msgid "Petitboot System Configuration"
msgstr "Petitboot System Configuration"
"Example: root=/dev/sda1 console=hvc0\n"
"\n"
+#, fuzzy
msgid ""
-"Autoboot: There are three possible options for automatic-boot hehaviour:\n"
-"\n"
-"Don't autoboot: boot options will be listed in the petitboot menu, but none "
-"will be booted automatically. User interaction will be required to continue "
+"Autoboot: Specify which devices to autoboot from.\n"
+"\n"
+"By selecting the 'Add Device' button new devices can be added to the "
+"autoboot list, either by UUID, MAC address, or device type. Once added to "
+"the boot order, the priority of devices can be changed with the 'left' and "
+"'right' keys Devices can be individually removed from the boot order with "
+"the minus key. Use this option if you have multiple operating system images "
+"installed.\n"
+"\n"
+"To autoboot from any device, select the 'Clear & Boot Any' button. In this "
+"case, any boot option that is marked as a default (by bootloader "
+"configuration) will be booted automatically after a timeout. Use this option "
+"if you want to quickly boot your system without changing any boot option "
+"settings. This is the typical configuration.\n"
+"\n"
+"To disable autoboot, select the 'Clear' button, which will clear the boot "
+"order. With autoboot disabled, user interaction will be required to continue "
"past the petitboot menu. Use this option if you want the machine to wait for "
"an explicit boot selection, or want to interact with petitboot before "
"booting the system\n"
"\n"
-"Autoboot from any disk/network device: any boot option that is marked as a "
-"default (by bootloader configuration) will be booted automatically after a "
-"timeout. Use this option if you want to quickly boot your system without "
-"changing any boot option settings. This is the typical configuration.\n"
-"\n"
-"Only autoboot from a specific disk/network device: only boot options from a "
-"single device (specifed here) will be booted automatically after a timeout. "
-"Use this option if you have multiple operating system images installed.\n"
-"\n"
"Timeout: Specify the length of time, in seconds, that the main menu will be "
"displayed before the default boot option is started. This option is only "
"displayed if autoboot is enabled.\n"
msgid "Usage"
msgstr "Usage"
+
+#~ msgid "Autoboot:"
+#~ msgstr "Autoboot:"
+
+#~ msgid "Don't autoboot"
+#~ msgstr "Don't autoboot"
+
+#~ msgid "Autoboot from any disk/network device"
+#~ msgstr "Autoboot from any disk/network device"
+
+#~ msgid "Only autoboot from a specific disk/network device"
+#~ msgstr "Only autoboot from a specific disk/network device"
+
+#~ msgid "Unknown UUID: %s"
+#~ msgstr "Unknown UUID: %s"
msgstr ""
"Project-Id-Version: petitboot 20140623-g89bd2ed2-dirty\n"
"Report-Msgid-Bugs-To: Geoff Levand <geoff@infradead.org>\n"
-"POT-Creation-Date: 2014-10-13 09:24+1100\n"
+"POT-Creation-Date: 2015-08-19 14:19+1000\n"
"PO-Revision-Date: 2014-06-24 13:56+0800\n"
"Last-Translator: Jeremy Kerr <jk@ozlabs.org>\n"
"Language-Team: Spanish\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
msgid "running boot hooks"
msgstr "ejecutando ganchos de arranque"
msgstr "Recuperación de configuración de Petitboot"
msgid "tab=next, shift+tab=previous, x=exit, h=help"
-msgstr "tab=siguiente, shift+tab=anterior, x=salida, h=ayuda"
+msgstr "tab=siguiente, mayús+tab=anterior, x=salir, h=ayuda"
msgid "Boot Option Editor"
msgstr "Editor de opciones de arranque"
msgid "No IP / mask values are set"
msgstr "No se han establecido valores IP / máscara"
+msgid "Select a boot device to add"
+msgstr "Seleccione un dispositivo de arranque para añadirlo"
+
msgid "Waiting for configuration data..."
msgstr "Esperando datos de configuración..."
-msgid "Autoboot:"
-msgstr "Arranque automático:"
+#, fuzzy
+msgid "Add Device"
+msgstr "Dispositivo:"
-msgid "Don't autoboot"
-msgstr "No arrancar automáticamente"
+msgid "Clear"
+msgstr "Borrar"
-msgid "Autoboot from any disk/network device"
-msgstr "Arranque automático desde cualquier dispositivo de disco/red"
+msgid "Clear & Boot Any"
+msgstr "Borrar y realizar cualquier arranque"
-msgid "Only autoboot from a specific disk/network device"
-msgstr "Arranque automático sólo desde un dispositivo de disco/red"
+#, fuzzy
+msgid "Boot Order:"
+msgstr "Argumentos de arranque:"
+
+msgid "(None)"
+msgstr "(Ninguno)"
#, c-format
msgid "disk: %s [uuid: %s]"
msgid "net: %s [mac: %s]"
msgstr "red: %s [mac: %s]"
+#, fuzzy
+msgid "Any Device"
+msgstr "Dispositivo:"
+
#, c-format
-msgid "Unknown UUID: %s"
-msgstr "UUID desconocido: %s"
+msgid "Any %s device"
+msgstr "Cualquier dispositivo %s"
msgid "Timeout:"
-msgstr "Tiempo de espera:"
+msgstr "Tiempo espera:"
msgid "seconds"
msgstr "segundos"
+#, c-format
+msgid "%s IPMI boot option: %s"
+msgstr "Opción de arranque de IPMI %s: %s"
+
+msgid "Clear option:"
+msgstr "Borrar opción:"
+
msgid "Network:"
msgstr "Red:"
msgid "Selecting 'OK' will exit safe mode"
msgstr "Si selecciona 'Aceptar' saldrá de la modalidad segura"
+#, fuzzy
+msgid "Disk R/W:"
+msgstr "Disco"
+
+msgid "Prevent all writes to disk"
+msgstr "Impide todas las escrituras en disco"
+
+msgid "Allow bootloader scripts to modify disks"
+msgstr "Permite a los scripts del gestor de arranque modificar los discos"
+
msgid "Petitboot System Configuration"
msgstr "Configuración del sistema de Petitboot"
"Ejemplo: root=/dev/sda1 console=hvc0\n"
"\n"
+#, fuzzy
msgid ""
-"Autoboot: There are three possible options for automatic-boot hehaviour:\n"
-"\n"
-"Don't autoboot: boot options will be listed in the petitboot menu, but none "
-"will be booted automatically. User interaction will be required to continue "
+"Autoboot: Specify which devices to autoboot from.\n"
+"\n"
+"By selecting the 'Add Device' button new devices can be added to the "
+"autoboot list, either by UUID, MAC address, or device type. Once added to "
+"the boot order, the priority of devices can be changed with the 'left' and "
+"'right' keys Devices can be individually removed from the boot order with "
+"the minus key. Use this option if you have multiple operating system images "
+"installed.\n"
+"\n"
+"To autoboot from any device, select the 'Clear & Boot Any' button. In this "
+"case, any boot option that is marked as a default (by bootloader "
+"configuration) will be booted automatically after a timeout. Use this option "
+"if you want to quickly boot your system without changing any boot option "
+"settings. This is the typical configuration.\n"
+"\n"
+"To disable autoboot, select the 'Clear' button, which will clear the boot "
+"order. With autoboot disabled, user interaction will be required to continue "
"past the petitboot menu. Use this option if you want the machine to wait for "
"an explicit boot selection, or want to interact with petitboot before "
"booting the system\n"
"\n"
-"Autoboot from any disk/network device: any boot option that is marked as a "
-"default (by bootloader configuration) will be booted automatically after a "
-"timeout. Use this option if you want to quickly boot your system without "
-"changing any boot option settings. This is the typical configuration.\n"
-"\n"
-"Only autoboot from a specific disk/network device: only boot options from a "
-"single device (specifed here) will be booted automatically after a timeout. "
-"Use this option if you have multiple operating system images installed.\n"
-"\n"
"Timeout: Specify the length of time, in seconds, that the main menu will be "
"displayed before the default boot option is started. This option is only "
"displayed if autoboot is enabled.\n"
msgid "Usage"
msgstr "Uso"
+
+#~ msgid "Autoboot:"
+#~ msgstr "Autoboot:"
+
+#~ msgid "Don't autoboot"
+#~ msgstr "Don't autoboot"
+
+#~ msgid "Autoboot from any disk/network device"
+#~ msgstr "Autoboot from any disk/network device"
+
+#~ msgid "Only autoboot from a specific disk/network device"
+#~ msgstr "Only autoboot from a specific disk/network device"
+
+#~ msgid "Unknown UUID: %s"
+#~ msgstr "Unknown UUID: %s"
msgstr ""
"Project-Id-Version: petitboot 20140623-g89bd2ed2-dirty\n"
"Report-Msgid-Bugs-To: Geoff Levand <geoff@infradead.org>\n"
-"POT-Creation-Date: 2014-10-13 09:24+1100\n"
+"POT-Creation-Date: 2015-08-19 14:19+1000\n"
"PO-Revision-Date: 2014-06-24 13:56+0800\n"
"Last-Translator: Jeremy Kerr <jk@ozlabs.org>\n"
"Language-Team: French\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Plural-Forms: nplurals=2; plural=n>1;\n"
msgid "running boot hooks"
msgstr "exécution points d'ancrage d'amorçage"
msgid "No IP / mask values are set"
msgstr "Aucune valeur IP/de masque définie"
+msgid "Select a boot device to add"
+msgstr "Sélectionner une unité d'amorçage à ajouter"
+
msgid "Waiting for configuration data..."
msgstr "Attente de données de configuration..."
-msgid "Autoboot:"
-msgstr "Amorçage auto :"
+#, fuzzy
+msgid "Add Device"
+msgstr "Unité :"
-msgid "Don't autoboot"
-msgstr "Pas d'amorçage automatique"
+msgid "Clear"
+msgstr "Effacer"
-msgid "Autoboot from any disk/network device"
-msgstr "Amorçage automatique depuis unité de disque/réseau"
+msgid "Clear & Boot Any"
+msgstr "Effacer & amorcer"
-msgid "Only autoboot from a specific disk/network device"
-msgstr "Amorçage auto seulement depuis unité disque/réseau spécifique"
+#, fuzzy
+msgid "Boot Order:"
+msgstr "Arguments d'amorçage :"
+
+msgid "(None)"
+msgstr "(Aucun)"
#, c-format
msgid "disk: %s [uuid: %s]"
msgid "net: %s [mac: %s]"
msgstr "réseau : %s [mac : %s]"
+#, fuzzy
+msgid "Any Device"
+msgstr "Unité :"
+
#, c-format
-msgid "Unknown UUID: %s"
-msgstr "UUID inconnu : %s"
+msgid "Any %s device"
+msgstr "N'importe quelle unité %s"
msgid "Timeout:"
msgstr "Délai attente :"
msgid "seconds"
msgstr "secondes"
+#, c-format
+msgid "%s IPMI boot option: %s"
+msgstr "%s Option d'amorçage IPMI : %s"
+
+msgid "Clear option:"
+msgstr "Option d'effacement :"
+
msgid "Network:"
msgstr "Réseau :"
msgid "Selecting 'OK' will exit safe mode"
msgstr "Sélectionner 'OK' vous fera sortir du mode sans échec"
+#, fuzzy
+msgid "Disk R/W:"
+msgstr "Disque"
+
+msgid "Prevent all writes to disk"
+msgstr "Empêcher toute écriture sur le disque "
+
+msgid "Allow bootloader scripts to modify disks"
+msgstr "Autoriser les scripts de chargeur de démarrage à modifier les disques "
+
msgid "Petitboot System Configuration"
msgstr "Configuration de système Petitboot"
"Exemple : root=/dev/sda1 console=hvc0\n"
"\n"
+#, fuzzy
msgid ""
-"Autoboot: There are three possible options for automatic-boot hehaviour:\n"
-"\n"
-"Don't autoboot: boot options will be listed in the petitboot menu, but none "
-"will be booted automatically. User interaction will be required to continue "
+"Autoboot: Specify which devices to autoboot from.\n"
+"\n"
+"By selecting the 'Add Device' button new devices can be added to the "
+"autoboot list, either by UUID, MAC address, or device type. Once added to "
+"the boot order, the priority of devices can be changed with the 'left' and "
+"'right' keys Devices can be individually removed from the boot order with "
+"the minus key. Use this option if you have multiple operating system images "
+"installed.\n"
+"\n"
+"To autoboot from any device, select the 'Clear & Boot Any' button. In this "
+"case, any boot option that is marked as a default (by bootloader "
+"configuration) will be booted automatically after a timeout. Use this option "
+"if you want to quickly boot your system without changing any boot option "
+"settings. This is the typical configuration.\n"
+"\n"
+"To disable autoboot, select the 'Clear' button, which will clear the boot "
+"order. With autoboot disabled, user interaction will be required to continue "
"past the petitboot menu. Use this option if you want the machine to wait for "
"an explicit boot selection, or want to interact with petitboot before "
"booting the system\n"
"\n"
-"Autoboot from any disk/network device: any boot option that is marked as a "
-"default (by bootloader configuration) will be booted automatically after a "
-"timeout. Use this option if you want to quickly boot your system without "
-"changing any boot option settings. This is the typical configuration.\n"
-"\n"
-"Only autoboot from a specific disk/network device: only boot options from a "
-"single device (specifed here) will be booted automatically after a timeout. "
-"Use this option if you have multiple operating system images installed.\n"
-"\n"
"Timeout: Specify the length of time, in seconds, that the main menu will be "
"displayed before the default boot option is started. This option is only "
"displayed if autoboot is enabled.\n"
msgid "Usage"
msgstr "Utilisation"
+
+#~ msgid "Autoboot:"
+#~ msgstr "Autoboot:"
+
+#~ msgid "Don't autoboot"
+#~ msgstr "Don't autoboot"
+
+#~ msgid "Autoboot from any disk/network device"
+#~ msgstr "Autoboot from any disk/network device"
+
+#~ msgid "Only autoboot from a specific disk/network device"
+#~ msgstr "Only autoboot from a specific disk/network device"
+
+#~ msgid "Unknown UUID: %s"
+#~ msgstr "Unknown UUID: %s"
msgstr ""
"Project-Id-Version: petitboot 20140623-g89bd2ed2-dirty\n"
"Report-Msgid-Bugs-To: Geoff Levand <geoff@infradead.org>\n"
-"POT-Creation-Date: 2014-10-13 09:24+1100\n"
+"POT-Creation-Date: 2015-08-19 14:19+1000\n"
"PO-Revision-Date: 2014-06-24 13:56+0800\n"
"Last-Translator: Jeremy Kerr <jk@ozlabs.org>\n"
"Language-Team: Italian\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
msgid "running boot hooks"
msgstr "esecuzione di hook di avvio"
msgid "No IP / mask values are set"
msgstr "Non è stato impostato alcun valore di IP/maschera"
+msgid "Select a boot device to add"
+msgstr "Selezionare un dispositivo di avvio da aggiungere"
+
msgid "Waiting for configuration data..."
msgstr "In attesa dei dati di configurazione..."
-msgid "Autoboot:"
-msgstr "Avvio automatico:"
+#, fuzzy
+msgid "Add Device"
+msgstr "Dispositivo:"
-msgid "Don't autoboot"
-msgstr "Non eseguire l'avvio automatico"
+msgid "Clear"
+msgstr "Ripulisci"
-msgid "Autoboot from any disk/network device"
-msgstr "Avvia automaticamente da qualsiasi dispositivo di rete/disco"
+msgid "Clear & Boot Any"
+msgstr "Ripulisci e avvia tutto"
-msgid "Only autoboot from a specific disk/network device"
-msgstr "Avvia automaticamente solo da uno specifico dispositivo di rete/disco"
+#, fuzzy
+msgid "Boot Order:"
+msgstr "Argomenti avvio:"
+
+msgid "(None)"
+msgstr "(Nessuno)"
#, c-format
msgid "disk: %s [uuid: %s]"
msgid "net: %s [mac: %s]"
msgstr "rete: %s [mac: %s]"
+#, fuzzy
+msgid "Any Device"
+msgstr "Dispositivo:"
+
#, c-format
-msgid "Unknown UUID: %s"
-msgstr "UUID sconosciuto: %s"
+msgid "Any %s device"
+msgstr "Qualsiasi dispositivo %s"
msgid "Timeout:"
msgstr "Timeout:"
msgid "seconds"
msgstr "secondi"
+#, c-format
+msgid "%s IPMI boot option: %s"
+msgstr "Opzione di avvio IPMI %s: %s"
+
+msgid "Clear option:"
+msgstr "Ripulisci opzione:"
+
msgid "Network:"
msgstr "Rete:"
msgid "Selecting 'OK' will exit safe mode"
msgstr "Selezionando 'OK' si uscirà in modalità sicura"
+#, fuzzy
+msgid "Disk R/W:"
+msgstr "Disco"
+
+msgid "Prevent all writes to disk"
+msgstr "Impedisci tutte le scritture su disco"
+
+msgid "Allow bootloader scripts to modify disks"
+msgstr "Consenti script bootloader per modificare i dischi"
+
msgid "Petitboot System Configuration"
msgstr "Configurazione di sistema Petitboot"
"Esempio: root=/dev/sda1 console=hvc0\n"
"\n"
+#, fuzzy
msgid ""
-"Autoboot: There are three possible options for automatic-boot hehaviour:\n"
-"\n"
-"Don't autoboot: boot options will be listed in the petitboot menu, but none "
-"will be booted automatically. User interaction will be required to continue "
+"Autoboot: Specify which devices to autoboot from.\n"
+"\n"
+"By selecting the 'Add Device' button new devices can be added to the "
+"autoboot list, either by UUID, MAC address, or device type. Once added to "
+"the boot order, the priority of devices can be changed with the 'left' and "
+"'right' keys Devices can be individually removed from the boot order with "
+"the minus key. Use this option if you have multiple operating system images "
+"installed.\n"
+"\n"
+"To autoboot from any device, select the 'Clear & Boot Any' button. In this "
+"case, any boot option that is marked as a default (by bootloader "
+"configuration) will be booted automatically after a timeout. Use this option "
+"if you want to quickly boot your system without changing any boot option "
+"settings. This is the typical configuration.\n"
+"\n"
+"To disable autoboot, select the 'Clear' button, which will clear the boot "
+"order. With autoboot disabled, user interaction will be required to continue "
"past the petitboot menu. Use this option if you want the machine to wait for "
"an explicit boot selection, or want to interact with petitboot before "
"booting the system\n"
"\n"
-"Autoboot from any disk/network device: any boot option that is marked as a "
-"default (by bootloader configuration) will be booted automatically after a "
-"timeout. Use this option if you want to quickly boot your system without "
-"changing any boot option settings. This is the typical configuration.\n"
-"\n"
-"Only autoboot from a specific disk/network device: only boot options from a "
-"single device (specifed here) will be booted automatically after a timeout. "
-"Use this option if you have multiple operating system images installed.\n"
-"\n"
"Timeout: Specify the length of time, in seconds, that the main menu will be "
"displayed before the default boot option is started. This option is only "
"displayed if autoboot is enabled.\n"
msgid "Usage"
msgstr "Utilizzo"
+
+#~ msgid "Autoboot:"
+#~ msgstr "Autoboot:"
+
+#~ msgid "Don't autoboot"
+#~ msgstr "Don't autoboot"
+
+#~ msgid "Autoboot from any disk/network device"
+#~ msgstr "Autoboot from any disk/network device"
+
+#~ msgid "Only autoboot from a specific disk/network device"
+#~ msgstr "Only autoboot from a specific disk/network device"
+
+#~ msgid "Unknown UUID: %s"
+#~ msgstr "Unknown UUID: %s"
msgstr ""
"Project-Id-Version: petitboot 20140623-g89bd2ed2-dirty\n"
"Report-Msgid-Bugs-To: Geoff Levand <geoff@infradead.org>\n"
-"POT-Creation-Date: 2014-10-13 09:24+1100\n"
+"POT-Creation-Date: 2015-08-19 14:19+1000\n"
"PO-Revision-Date: 2014-06-24 13:56+0800\n"
"Last-Translator: Jeremy Kerr <jk@ozlabs.org>\n"
"Language-Team: Japanese\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
msgid "running boot hooks"
msgstr "ブート・フックを実行しています"
msgid "No IP / mask values are set"
msgstr "IP/マスク値が設定されていません"
+msgid "Select a boot device to add"
+msgstr "追加するブート・デバイスの選択"
+
msgid "Waiting for configuration data..."
msgstr "構成データを待っています..."
-msgid "Autoboot:"
-msgstr "自動ブート:"
+#, fuzzy
+msgid "Add Device"
+msgstr "デバイス: "
-msgid "Don't autoboot"
-msgstr "自動ブートしない"
+msgid "Clear"
+msgstr "消去"
-msgid "Autoboot from any disk/network device"
-msgstr "任意のディスク/ネットワーク・デバイスから自動ブート"
+msgid "Clear & Boot Any"
+msgstr "消去していずれかをブート"
-msgid "Only autoboot from a specific disk/network device"
-msgstr "特定ディスク/ネットワークデバイスからのみ自動ブート"
+#, fuzzy
+msgid "Boot Order:"
+msgstr "ブート引数:"
+
+msgid "(None)"
+msgstr "(なし)"
#, c-format
msgid "disk: %s [uuid: %s]"
msgid "net: %s [mac: %s]"
msgstr "net: %s [mac: %s]"
+#, fuzzy
+msgid "Any Device"
+msgstr "デバイス: "
+
#, c-format
-msgid "Unknown UUID: %s"
-msgstr "ä¸\8dæ\98\8e UUID: %s"
+msgid "Any %s device"
+msgstr "ä»»æ\84\8fã\81® %s ã\83\87ã\83\90ã\82¤ã\82¹"
msgid "Timeout:"
msgstr "タイムアウト:"
msgid "seconds"
msgstr "秒"
+#, c-format
+msgid "%s IPMI boot option: %s"
+msgstr "%s IPMI ブート・オプション: %s"
+
+msgid "Clear option:"
+msgstr "消去オプション:"
+
msgid "Network:"
msgstr "ネットワーク:"
msgid "Selecting 'OK' will exit safe mode"
msgstr "「OK」を選択するとセーフ・モードが終了します"
+#, fuzzy
+msgid "Disk R/W:"
+msgstr "ディスク"
+
+msgid "Prevent all writes to disk"
+msgstr "ディスクへの書き込みをすべて抑止する"
+
+msgid "Allow bootloader scripts to modify disks"
+msgstr "ブート・ローダー・スクリプトでディスクを変更できるようにする"
+
msgid "Petitboot System Configuration"
msgstr "Petitboot システム構成"
#, fuzzy
msgid "down"
-msgstr "ダウン"
+msgstr "ã\83ªã\83³ã\82¯ã\83\80ã\82¦ã\83³"
msgid "Petitboot System Information"
msgstr "Petitboot システム情報"
"例えば、root=/dev/sda1 console=hvc0 のように入力します。\n"
"\n"
+#, fuzzy
msgid ""
-"Autoboot: There are three possible options for automatic-boot hehaviour:\n"
-"\n"
-"Don't autoboot: boot options will be listed in the petitboot menu, but none "
-"will be booted automatically. User interaction will be required to continue "
+"Autoboot: Specify which devices to autoboot from.\n"
+"\n"
+"By selecting the 'Add Device' button new devices can be added to the "
+"autoboot list, either by UUID, MAC address, or device type. Once added to "
+"the boot order, the priority of devices can be changed with the 'left' and "
+"'right' keys Devices can be individually removed from the boot order with "
+"the minus key. Use this option if you have multiple operating system images "
+"installed.\n"
+"\n"
+"To autoboot from any device, select the 'Clear & Boot Any' button. In this "
+"case, any boot option that is marked as a default (by bootloader "
+"configuration) will be booted automatically after a timeout. Use this option "
+"if you want to quickly boot your system without changing any boot option "
+"settings. This is the typical configuration.\n"
+"\n"
+"To disable autoboot, select the 'Clear' button, which will clear the boot "
+"order. With autoboot disabled, user interaction will be required to continue "
"past the petitboot menu. Use this option if you want the machine to wait for "
"an explicit boot selection, or want to interact with petitboot before "
"booting the system\n"
"\n"
-"Autoboot from any disk/network device: any boot option that is marked as a "
-"default (by bootloader configuration) will be booted automatically after a "
-"timeout. Use this option if you want to quickly boot your system without "
-"changing any boot option settings. This is the typical configuration.\n"
-"\n"
-"Only autoboot from a specific disk/network device: only boot options from a "
-"single device (specifed here) will be booted automatically after a timeout. "
-"Use this option if you have multiple operating system images installed.\n"
-"\n"
"Timeout: Specify the length of time, in seconds, that the main menu will be "
"displayed before the default boot option is started. This option is only "
"displayed if autoboot is enabled.\n"
msgid "Usage"
msgstr "使用法"
+
+#~ msgid "Autoboot:"
+#~ msgstr "Autoboot:"
+
+#~ msgid "Don't autoboot"
+#~ msgstr "Don't autoboot"
+
+#~ msgid "Autoboot from any disk/network device"
+#~ msgstr "Autoboot from any disk/network device"
+
+#~ msgid "Only autoboot from a specific disk/network device"
+#~ msgstr "Only autoboot from a specific disk/network device"
+
+#~ msgid "Unknown UUID: %s"
+#~ msgstr "Unknown UUID: %s"
msgstr ""
"Project-Id-Version: petitboot 20140623-g89bd2ed2-dirty\n"
"Report-Msgid-Bugs-To: Geoff Levand <geoff@infradead.org>\n"
-"POT-Creation-Date: 2014-10-13 09:24+1100\n"
+"POT-Creation-Date: 2015-08-19 14:19+1000\n"
"PO-Revision-Date: 2014-06-24 13:56+0800\n"
"Last-Translator: Jeremy Kerr <jk@ozlabs.org>\n"
"Language-Team: Korean\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
msgid "running boot hooks"
msgstr "부트 후크 실행 중"
msgid "No IP / mask values are set"
msgstr "IP/마스크 값이 설정되지 않음"
+msgid "Select a boot device to add"
+msgstr "추가할 부트 장치를 선택하십시오. "
+
msgid "Waiting for configuration data..."
msgstr "구성 데이터 대기 중..."
-msgid "Autoboot:"
-msgstr "자동 부트:"
+#, fuzzy
+msgid "Add Device"
+msgstr "장치: "
-msgid "Don't autoboot"
-msgstr "ì\9e\90ë\8f\99 ë¶\80í\8a¸í\95\98ì§\80 ì\95\8aì\9d\8c"
+msgid "Clear"
+msgstr "ì\84 í\83\9d ì·¨ì\86\8c"
-msgid "Autoboot from any disk/network device"
-msgstr "모든 디스크/네트워크 장치에서 자동 부트"
+msgid "Clear & Boot Any"
+msgstr "선택 취소 & 모든 부트"
-msgid "Only autoboot from a specific disk/network device"
-msgstr "특정 디스크/네트워크 장치에서만 자동 부트"
+#, fuzzy
+msgid "Boot Order:"
+msgstr "부트 인수:"
+
+msgid "(None)"
+msgstr "(없음)"
#, c-format
msgid "disk: %s [uuid: %s]"
msgid "net: %s [mac: %s]"
msgstr "네트: %s [mac: %s]"
+#, fuzzy
+msgid "Any Device"
+msgstr "장치: "
+
#, c-format
-msgid "Unknown UUID: %s"
-msgstr "알 수 없는 UUID: %s"
+msgid "Any %s device"
+msgstr "모든 %s 장치"
msgid "Timeout:"
msgstr "제한시간:"
msgid "seconds"
msgstr "초"
+#, c-format
+msgid "%s IPMI boot option: %s"
+msgstr "%s IPMI 부트 옵션: %s"
+
+msgid "Clear option:"
+msgstr "선택 취소 옵션:"
+
msgid "Network:"
msgstr "네트워크:"
msgid "Selecting 'OK' will exit safe mode"
msgstr "'확인'을 선택하면 안전 모드를 종료합니다."
+#, fuzzy
+msgid "Disk R/W:"
+msgstr "디스크"
+
+msgid "Prevent all writes to disk"
+msgstr "디스크에 대한 모든 쓰기 방지"
+
+msgid "Allow bootloader scripts to modify disks"
+msgstr "부트 로더 스크립트가 디스크를 수정하도록 허용"
+
msgid "Petitboot System Configuration"
msgstr "Petitboot 시스템 구성"
"예: root=/dev/sda1 console=hvc0\n"
"\n"
+#, fuzzy
msgid ""
-"Autoboot: There are three possible options for automatic-boot hehaviour:\n"
-"\n"
-"Don't autoboot: boot options will be listed in the petitboot menu, but none "
-"will be booted automatically. User interaction will be required to continue "
+"Autoboot: Specify which devices to autoboot from.\n"
+"\n"
+"By selecting the 'Add Device' button new devices can be added to the "
+"autoboot list, either by UUID, MAC address, or device type. Once added to "
+"the boot order, the priority of devices can be changed with the 'left' and "
+"'right' keys Devices can be individually removed from the boot order with "
+"the minus key. Use this option if you have multiple operating system images "
+"installed.\n"
+"\n"
+"To autoboot from any device, select the 'Clear & Boot Any' button. In this "
+"case, any boot option that is marked as a default (by bootloader "
+"configuration) will be booted automatically after a timeout. Use this option "
+"if you want to quickly boot your system without changing any boot option "
+"settings. This is the typical configuration.\n"
+"\n"
+"To disable autoboot, select the 'Clear' button, which will clear the boot "
+"order. With autoboot disabled, user interaction will be required to continue "
"past the petitboot menu. Use this option if you want the machine to wait for "
"an explicit boot selection, or want to interact with petitboot before "
"booting the system\n"
"\n"
-"Autoboot from any disk/network device: any boot option that is marked as a "
-"default (by bootloader configuration) will be booted automatically after a "
-"timeout. Use this option if you want to quickly boot your system without "
-"changing any boot option settings. This is the typical configuration.\n"
-"\n"
-"Only autoboot from a specific disk/network device: only boot options from a "
-"single device (specifed here) will be booted automatically after a timeout. "
-"Use this option if you have multiple operating system images installed.\n"
-"\n"
"Timeout: Specify the length of time, in seconds, that the main menu will be "
"displayed before the default boot option is started. This option is only "
"displayed if autoboot is enabled.\n"
msgid "Usage"
msgstr "사용법"
+
+#~ msgid "Autoboot:"
+#~ msgstr "Autoboot:"
+
+#~ msgid "Don't autoboot"
+#~ msgstr "Don't autoboot"
+
+#~ msgid "Autoboot from any disk/network device"
+#~ msgstr "Autoboot from any disk/network device"
+
+#~ msgid "Only autoboot from a specific disk/network device"
+#~ msgstr "Only autoboot from a specific disk/network device"
+
+#~ msgid "Unknown UUID: %s"
+#~ msgstr "Unknown UUID: %s"
msgstr ""
"Project-Id-Version: petitboot 20140623-g89bd2ed2-dirty\n"
"Report-Msgid-Bugs-To: Geoff Levand <geoff@infradead.org>\n"
-"POT-Creation-Date: 2014-10-13 09:24+1100\n"
+"POT-Creation-Date: 2015-08-19 14:19+1000\n"
"PO-Revision-Date: 2014-06-24 13:56+0800\n"
"Last-Translator: Jeremy Kerr <jk@ozlabs.org>\n"
"Language-Team: Portugese (Brazil)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Plural-Forms: nplurals=2; plural=n>1;\n"
msgid "running boot hooks"
msgstr "executando ganchos de inicialização"
msgid "No IP / mask values are set"
msgstr "Nenhum valor de máscara/IP está configurado"
+msgid "Select a boot device to add"
+msgstr "Selecione um dispositivo de inicialização a incluir."
+
msgid "Waiting for configuration data..."
msgstr "Aguardando dados de configuração..."
-msgid "Autoboot:"
-msgstr "Executar a inicialização automática:"
+#, fuzzy
+msgid "Add Device"
+msgstr "Dispositivo:"
-msgid "Don't autoboot"
-msgstr "Não executar a inicialização automática"
+msgid "Clear"
+msgstr "Limpar"
-msgid "Autoboot from any disk/network device"
-msgstr ""
-"Executar a inicialização automática a partir de qualquer dispositivo de "
-"disco/rede"
+msgid "Clear & Boot Any"
+msgstr "Limpar e inicializar qualquer um"
-msgid "Only autoboot from a specific disk/network device"
-msgstr ""
-"Executar a inicialização automática apenas a partir de um dispositivo de "
-"disco/rede específico"
+#, fuzzy
+msgid "Boot Order:"
+msgstr "Argumentos de inicialização:"
+
+msgid "(None)"
+msgstr "(Nenhum)"
#, c-format
msgid "disk: %s [uuid: %s]"
msgid "net: %s [mac: %s]"
msgstr "rede: %s [mac: %s]"
+#, fuzzy
+msgid "Any Device"
+msgstr "Dispositivo:"
+
#, c-format
-msgid "Unknown UUID: %s"
-msgstr "UUID (identificador exclusivo universal) Desconhecido: %s"
+msgid "Any %s device"
+msgstr "Qualquer dispositivo %s"
msgid "Timeout:"
msgstr "Tempo Limite:"
msgid "seconds"
msgstr "segundos"
+#, c-format
+msgid "%s IPMI boot option: %s"
+msgstr "%s Opção de inicialização de IPMI: %s"
+
+msgid "Clear option:"
+msgstr "Limpar opção:"
+
msgid "Network:"
msgstr "Rede:"
msgid "Selecting 'OK' will exit safe mode"
msgstr "Selecionar 'OK' irá sair do modo de segurança"
+#, fuzzy
+msgid "Disk R/W:"
+msgstr "Disco"
+
+msgid "Prevent all writes to disk"
+msgstr "Evitar todas as gravações em disco"
+
+msgid "Allow bootloader scripts to modify disks"
+msgstr "Permitir que scripts de carregador de inicialização modifiquem discos"
+
msgid "Petitboot System Configuration"
msgstr "Configuração do Sistema Petitboot"
"Para configurar o idioma da interface do petitboot, digite L (idioma).\n"
"\n"
"Para localizar opções de inicialização novas ou atualizadas no sistema, "
-"selecione a opção 'Varrer novamentedispositivos'.\n"
+"selecione a opção 'Varrer novamente dispositivos'.\n"
"\n"
"Para recuperar novas opções de inicialização a partir de um arquivo de "
"configuração remoto, selecione a opção 'Recuperar configuração a partir da "
"Exemplo: root=/dev/sda1 console=hvc0\n"
"\n"
+#, fuzzy
msgid ""
-"Autoboot: There are three possible options for automatic-boot hehaviour:\n"
-"\n"
-"Don't autoboot: boot options will be listed in the petitboot menu, but none "
-"will be booted automatically. User interaction will be required to continue "
+"Autoboot: Specify which devices to autoboot from.\n"
+"\n"
+"By selecting the 'Add Device' button new devices can be added to the "
+"autoboot list, either by UUID, MAC address, or device type. Once added to "
+"the boot order, the priority of devices can be changed with the 'left' and "
+"'right' keys Devices can be individually removed from the boot order with "
+"the minus key. Use this option if you have multiple operating system images "
+"installed.\n"
+"\n"
+"To autoboot from any device, select the 'Clear & Boot Any' button. In this "
+"case, any boot option that is marked as a default (by bootloader "
+"configuration) will be booted automatically after a timeout. Use this option "
+"if you want to quickly boot your system without changing any boot option "
+"settings. This is the typical configuration.\n"
+"\n"
+"To disable autoboot, select the 'Clear' button, which will clear the boot "
+"order. With autoboot disabled, user interaction will be required to continue "
"past the petitboot menu. Use this option if you want the machine to wait for "
"an explicit boot selection, or want to interact with petitboot before "
"booting the system\n"
"\n"
-"Autoboot from any disk/network device: any boot option that is marked as a "
-"default (by bootloader configuration) will be booted automatically after a "
-"timeout. Use this option if you want to quickly boot your system without "
-"changing any boot option settings. This is the typical configuration.\n"
-"\n"
-"Only autoboot from a specific disk/network device: only boot options from a "
-"single device (specifed here) will be booted automatically after a timeout. "
-"Use this option if you have multiple operating system images installed.\n"
-"\n"
"Timeout: Specify the length of time, in seconds, that the main menu will be "
"displayed before the default boot option is started. This option is only "
"displayed if autoboot is enabled.\n"
msgid "Usage"
msgstr "Uso"
+
+#~ msgid "Autoboot:"
+#~ msgstr "Autoboot:"
+
+#~ msgid "Don't autoboot"
+#~ msgstr "Don't autoboot"
+
+#~ msgid "Autoboot from any disk/network device"
+#~ msgstr "Autoboot from any disk/network device"
+
+#~ msgid "Only autoboot from a specific disk/network device"
+#~ msgstr "Only autoboot from a specific disk/network device"
+
+#~ msgid "Unknown UUID: %s"
+#~ msgstr "Unknown UUID: %s"
msgstr ""
"Project-Id-Version: petitboot 20140623-g89bd2ed2-dirty\n"
"Report-Msgid-Bugs-To: Geoff Levand <geoff@infradead.org>\n"
-"POT-Creation-Date: 2014-10-13 09:24+1100\n"
+"POT-Creation-Date: 2015-08-19 14:19+1000\n"
"PO-Revision-Date: 2014-06-24 13:56+0800\n"
"Last-Translator: Jeremy Kerr <jk@ozlabs.org>\n"
"Language-Team: Russian\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
msgid "running boot hooks"
msgstr "выполнение привязок загрузки"
msgid "No IP / mask values are set"
msgstr "Не задано значение IP / маски"
+msgid "Select a boot device to add"
+msgstr "Выберите загрузочное устройство для добавления"
+
msgid "Waiting for configuration data..."
msgstr "Ожидание данных конфигурации..."
-msgid "Autoboot:"
-msgstr "Автоматическая загрузка:"
+#, fuzzy
+msgid "Add Device"
+msgstr "Устройство:"
-msgid "Don't autoboot"
-msgstr "Ð\9dе загÑ\80Ñ\83жаÑ\82Ñ\8cÑ\81Ñ\8f авÑ\82омаÑ\82иÑ\87еÑ\81ки"
+msgid "Clear"
+msgstr "Ð\9eÑ\87иÑ\81Ñ\82иÑ\82Ñ\8c"
-msgid "Autoboot from any disk/network device"
-msgstr "Ð\90вÑ\82омаÑ\82иÑ\87еÑ\81ки загÑ\80Ñ\83жаÑ\82Ñ\8cÑ\81Ñ\8f Ñ\81 лÑ\8eбого диÑ\81ка/Ñ\81еÑ\82евого Ñ\83Ñ\81Ñ\82Ñ\80ойÑ\81Ñ\82ва"
+msgid "Clear & Boot Any"
+msgstr "Ð\9eÑ\87иÑ\81Ñ\82иÑ\82Ñ\8c и загÑ\80Ñ\83зиÑ\82Ñ\8c вÑ\81е"
-msgid "Only autoboot from a specific disk/network device"
-msgstr ""
-"Автоматически загружаться только с указанного диска/сетевого устройства"
+#, fuzzy
+msgid "Boot Order:"
+msgstr "Аргументы загрузки:"
+
+msgid "(None)"
+msgstr "(Нет)"
#, c-format
msgid "disk: %s [uuid: %s]"
msgid "net: %s [mac: %s]"
msgstr "сеть: %s [mac: %s]"
+#, fuzzy
+msgid "Any Device"
+msgstr "Устройство:"
+
#, c-format
-msgid "Unknown UUID: %s"
-msgstr "Ð\9dеизвеÑ\81Ñ\82нÑ\8bй UUID: %s"
+msgid "Any %s device"
+msgstr "Ð\9bÑ\8eбое Ñ\83Ñ\81Ñ\82Ñ\80ойÑ\81Ñ\82во %s"
msgid "Timeout:"
msgstr "Тайм-аут:"
msgid "seconds"
msgstr "секунд"
+#, c-format
+msgid "%s IPMI boot option: %s"
+msgstr "Опция загрузки IPMI %s: %s"
+
+msgid "Clear option:"
+msgstr "Опция очистки:"
+
msgid "Network:"
msgstr "Сеть:"
msgstr "Конфигурация статического IP"
msgid "link up"
-msgstr "подклÑ\8eÑ\87иÑ\82Ñ\8cÑ\81Ñ\8f"
+msgstr "линиÑ\8f Ñ\81вÑ\8fзи акÑ\82ивна"
msgid "link down"
-msgstr "оÑ\82клÑ\8eÑ\87иÑ\82Ñ\8cÑ\81Ñ\8f"
+msgstr "линиÑ\8f Ñ\81вÑ\8fзи неакÑ\82ивна"
msgid "IP/mask:"
msgstr "IP/маска:"
msgid "Selecting 'OK' will exit safe mode"
msgstr "После нажатия 'OK' безопасный режим будет выключен"
+#, fuzzy
+msgid "Disk R/W:"
+msgstr "Диск"
+
+msgid "Prevent all writes to disk"
+msgstr "Запретить любую запись на диск"
+
+msgid "Allow bootloader scripts to modify disks"
+msgstr "Разрешить сценарии загрузчика для изменения дисков"
+
msgid "Petitboot System Configuration"
msgstr "Конфигурация Petitboot System"
#, c-format
msgid " mounted at: %s"
-msgstr " Ñ\83Ñ\81Ñ\82ановлено в: %s"
+msgstr " Ñ\82оÑ\87ка монÑ\82иÑ\80ованиÑ\8f: %s"
msgid "Network interfaces"
msgstr "Сетевые интерфейсы"
#. * link status for a network connection.
#, c-format
msgid " link: %s"
-msgstr " связь: %s"
+msgstr " линия связи: %s"
msgid "up"
-msgstr "вкл"
+msgstr "акÑ\82ивна"
#, fuzzy
msgid "down"
-msgstr "вÑ\8bкл"
+msgstr "неакÑ\82ивна"
msgid "Petitboot System Information"
msgstr "Информация о системе Petitboot"
"Пример: root=/dev/sda1 console=hvc0\n"
"\n"
+#, fuzzy
msgid ""
-"Autoboot: There are three possible options for automatic-boot hehaviour:\n"
-"\n"
-"Don't autoboot: boot options will be listed in the petitboot menu, but none "
-"will be booted automatically. User interaction will be required to continue "
+"Autoboot: Specify which devices to autoboot from.\n"
+"\n"
+"By selecting the 'Add Device' button new devices can be added to the "
+"autoboot list, either by UUID, MAC address, or device type. Once added to "
+"the boot order, the priority of devices can be changed with the 'left' and "
+"'right' keys Devices can be individually removed from the boot order with "
+"the minus key. Use this option if you have multiple operating system images "
+"installed.\n"
+"\n"
+"To autoboot from any device, select the 'Clear & Boot Any' button. In this "
+"case, any boot option that is marked as a default (by bootloader "
+"configuration) will be booted automatically after a timeout. Use this option "
+"if you want to quickly boot your system without changing any boot option "
+"settings. This is the typical configuration.\n"
+"\n"
+"To disable autoboot, select the 'Clear' button, which will clear the boot "
+"order. With autoboot disabled, user interaction will be required to continue "
"past the petitboot menu. Use this option if you want the machine to wait for "
"an explicit boot selection, or want to interact with petitboot before "
"booting the system\n"
"\n"
-"Autoboot from any disk/network device: any boot option that is marked as a "
-"default (by bootloader configuration) will be booted automatically after a "
-"timeout. Use this option if you want to quickly boot your system without "
-"changing any boot option settings. This is the typical configuration.\n"
-"\n"
-"Only autoboot from a specific disk/network device: only boot options from a "
-"single device (specifed here) will be booted automatically after a timeout. "
-"Use this option if you have multiple operating system images installed.\n"
-"\n"
"Timeout: Specify the length of time, in seconds, that the main menu will be "
"displayed before the default boot option is started. This option is only "
"displayed if autoboot is enabled.\n"
"или если хотите поработать с petitboot до загрузки системы\n"
"\n"
"Автозагрузка с любого диска/сетевого устройства: любой вариант загрузки с "
-"оÑ\82меÑ\82кой по Ñ\83молÑ\87аниÑ\8e (задаеÑ\82Ñ\81Ñ\8f в наÑ\81Ñ\82Ñ\80ойкаÑ\85 bootloader) будет автоматически "
+"оÑ\82меÑ\82кой по Ñ\83молÑ\87аниÑ\8e (в конÑ\84игÑ\83Ñ\80аÑ\86ии загÑ\80Ñ\83зÑ\87ика) будет автоматически "
"загружен после тайм-аута. Используйте этот вариант в том случае, если хотите "
"быстро загрузить систему без изменения каких-либо настроек варианта "
"загрузки. Является стандартной конфигурацией.\n"
msgid "Usage"
msgstr "Использование"
+
+#~ msgid "Autoboot:"
+#~ msgstr "Autoboot:"
+
+#~ msgid "Don't autoboot"
+#~ msgstr "Don't autoboot"
+
+#~ msgid "Autoboot from any disk/network device"
+#~ msgstr "Autoboot from any disk/network device"
+
+#~ msgid "Only autoboot from a specific disk/network device"
+#~ msgstr "Only autoboot from a specific disk/network device"
+
+#~ msgid "Unknown UUID: %s"
+#~ msgstr "Unknown UUID: %s"
msgstr ""
"Project-Id-Version: petitboot 20140623-g89bd2ed2-dirty\n"
"Report-Msgid-Bugs-To: Geoff Levand <geoff@infradead.org>\n"
-"POT-Creation-Date: 2014-10-13 09:24+1100\n"
+"POT-Creation-Date: 2015-08-19 14:19+1000\n"
"PO-Revision-Date: 2014-06-24 13:56+0800\n"
"Last-Translator: Jeremy Kerr <jk@ozlabs.org>\n"
"Language-Team: Simplified Chinese\n"
msgid "No IP / mask values are set"
msgstr "未设置任何 IP/掩码值"
+msgid "Select a boot device to add"
+msgstr "选择要添加的引导设备"
+
msgid "Waiting for configuration data..."
msgstr "正在等待配置数据..."
-msgid "Autoboot:"
-msgstr "自动引导:"
+#, fuzzy
+msgid "Add Device"
+msgstr "设备:"
-msgid "Don't autoboot"
-msgstr "不自动引导"
+msgid "Clear"
+msgstr "清除"
-msgid "Autoboot from any disk/network device"
-msgstr "从任何磁盘/网络设备自动引导"
+msgid "Clear & Boot Any"
+msgstr "清除并引导任何项"
-msgid "Only autoboot from a specific disk/network device"
-msgstr "仅从特定磁盘/网络设备自动引导"
+#, fuzzy
+msgid "Boot Order:"
+msgstr "引导参数:"
+
+msgid "(None)"
+msgstr "(无)"
#, c-format
msgid "disk: %s [uuid: %s]"
msgid "net: %s [mac: %s]"
msgstr "网路:%s [mac:%s]"
+#, fuzzy
+msgid "Any Device"
+msgstr "设备:"
+
#, c-format
-msgid "Unknown UUID: %s"
-msgstr "未知 UUID:%s"
+msgid "Any %s device"
+msgstr "任何 %s 设备"
msgid "Timeout:"
msgstr "超时:"
msgid "seconds"
msgstr "秒"
+#, c-format
+msgid "%s IPMI boot option: %s"
+msgstr "%s IPMI 引导选项:%s"
+
+msgid "Clear option:"
+msgstr "清除选项:"
+
msgid "Network:"
msgstr "网络:"
msgid "Selecting 'OK' will exit safe mode"
msgstr "选择“确定”将退出安全模式"
+#, fuzzy
+msgid "Disk R/W:"
+msgstr "磁盘"
+
+msgid "Prevent all writes to disk"
+msgstr "阻止对磁盘的所有写入操作"
+
+msgid "Allow bootloader scripts to modify disks"
+msgstr "允许引导程序脚本修改磁盘"
+
msgid "Petitboot System Configuration"
msgstr "Petitboot 系统配置"
#, c-format
msgid "!Invalid option %d"
-msgstr "!无效的选项 %d"
+msgstr "!无效选项 %d"
msgid "Disk"
msgstr "磁盘"
"示例:root=/dev/sda1 console=hvc0\n"
"\n"
+#, fuzzy
msgid ""
-"Autoboot: There are three possible options for automatic-boot hehaviour:\n"
-"\n"
-"Don't autoboot: boot options will be listed in the petitboot menu, but none "
-"will be booted automatically. User interaction will be required to continue "
+"Autoboot: Specify which devices to autoboot from.\n"
+"\n"
+"By selecting the 'Add Device' button new devices can be added to the "
+"autoboot list, either by UUID, MAC address, or device type. Once added to "
+"the boot order, the priority of devices can be changed with the 'left' and "
+"'right' keys Devices can be individually removed from the boot order with "
+"the minus key. Use this option if you have multiple operating system images "
+"installed.\n"
+"\n"
+"To autoboot from any device, select the 'Clear & Boot Any' button. In this "
+"case, any boot option that is marked as a default (by bootloader "
+"configuration) will be booted automatically after a timeout. Use this option "
+"if you want to quickly boot your system without changing any boot option "
+"settings. This is the typical configuration.\n"
+"\n"
+"To disable autoboot, select the 'Clear' button, which will clear the boot "
+"order. With autoboot disabled, user interaction will be required to continue "
"past the petitboot menu. Use this option if you want the machine to wait for "
"an explicit boot selection, or want to interact with petitboot before "
"booting the system\n"
"\n"
-"Autoboot from any disk/network device: any boot option that is marked as a "
-"default (by bootloader configuration) will be booted automatically after a "
-"timeout. Use this option if you want to quickly boot your system without "
-"changing any boot option settings. This is the typical configuration.\n"
-"\n"
-"Only autoboot from a specific disk/network device: only boot options from a "
-"single device (specifed here) will be booted automatically after a timeout. "
-"Use this option if you have multiple operating system images installed.\n"
-"\n"
"Timeout: Specify the length of time, in seconds, that the main menu will be "
"displayed before the default boot option is started. This option is only "
"displayed if autoboot is enabled.\n"
"\n"
"网络选项:\n"
"\n"
-"æ\89\80æ\9c\89æ´»å\8a¨æ\8e¥å\8f£ä¸\8aç\9a\84 DHCPï¼\9aè\87ªå\8a¨å°\86 IP å\9c°å\9d\80å\88\86é\85\8dç»\99æ¯\8f个ç½\91ç»\9cæ\8e¥å\8f£ã\80\82å¦\82æ\9e\9cæ\82¨ç\9a\84ç½\91ç»\9cä¸\8aæ\9c\89 "
-"DHCP 服务器,请使用 此选项。\n"
+"æ\89\80æ\9c\89æ´»å\8a¨æ\8e¥å\8f£ä¸\8aç\9a\84 DHCPï¼\9aè\87ªå\8a¨å°\86 IP å\9c°å\9d\80å\88\86é\85\8dç»\99æ¯\8f个ç½\91ç»\9cæ\8e¥å\8f£ã\80\82å¦\82æ\9e\9cæ\82¨ç\9a\84ç½\91ç»\9cä¸å\98å\9c¨ "
+"DHCP 服务器,请使用此选项。\n"
"\n"
"特定接口上的 DHCP:自动将 IP 地址分配给选择的网络接口。不配置其他接口。如果您"
"在不同的接口上有多个 DHCP 服务器,但在引导期间只想配置单个接口,请选择此选"
msgid "Usage"
msgstr "用法"
+
+#~ msgid "Autoboot:"
+#~ msgstr "Autoboot:"
+
+#~ msgid "Don't autoboot"
+#~ msgstr "Don't autoboot"
+
+#~ msgid "Autoboot from any disk/network device"
+#~ msgstr "Autoboot from any disk/network device"
+
+#~ msgid "Only autoboot from a specific disk/network device"
+#~ msgstr "Only autoboot from a specific disk/network device"
+
+#~ msgid "Unknown UUID: %s"
+#~ msgstr "Unknown UUID: %s"
msgstr ""
"Project-Id-Version: petitboot 20140623-g89bd2ed2-dirty\n"
"Report-Msgid-Bugs-To: Geoff Levand <geoff@infradead.org>\n"
-"POT-Creation-Date: 2014-10-13 09:24+1100\n"
+"POT-Creation-Date: 2015-08-19 14:19+1000\n"
"PO-Revision-Date: 2014-06-24 13:56+0800\n"
"Last-Translator: Jeremy Kerr <jk@ozlabs.org>\n"
"Language-Team: Traditional Chinese\n"
msgid "No IP / mask values are set"
msgstr "未設定任何 IP/遮罩值"
+msgid "Select a boot device to add"
+msgstr "選取要新增的啟動裝置"
+
msgid "Waiting for configuration data..."
msgstr "正在等待配置資料..."
-msgid "Autoboot:"
-msgstr "自動啟動:"
+#, fuzzy
+msgid "Add Device"
+msgstr "裝置:"
-msgid "Don't autoboot"
-msgstr "不自動啟動"
+msgid "Clear"
+msgstr "清除"
-msgid "Autoboot from any disk/network device"
-msgstr "從任何磁碟/網路裝置自動啟動"
+msgid "Clear & Boot Any"
+msgstr "清除並啟動任意項"
-msgid "Only autoboot from a specific disk/network device"
-msgstr "僅從特定的磁碟/網路裝置自動啟動"
+#, fuzzy
+msgid "Boot Order:"
+msgstr "啟動引數:"
+
+msgid "(None)"
+msgstr "(無)"
#, c-format
msgid "disk: %s [uuid: %s]"
msgid "net: %s [mac: %s]"
msgstr "網路:%s [MAC:%s]"
+#, fuzzy
+msgid "Any Device"
+msgstr "裝置:"
+
#, c-format
-msgid "Unknown UUID: %s"
-msgstr "ä¸\8dæ\98\8e UUIDï¼\9a%s"
+msgid "Any %s device"
+msgstr "ä»»ä½\95 %s è£\9dç½®"
msgid "Timeout:"
msgstr "逾時:"
msgid "seconds"
msgstr "秒"
+#, c-format
+msgid "%s IPMI boot option: %s"
+msgstr "%s IPMI 啟動選項:%s"
+
+msgid "Clear option:"
+msgstr "清除選項:"
+
msgid "Network:"
msgstr "網路:"
msgid "Selecting 'OK' will exit safe mode"
msgstr "選取「確定」將會結束安全模式"
+#, fuzzy
+msgid "Disk R/W:"
+msgstr "磁碟"
+
+msgid "Prevent all writes to disk"
+msgstr "阻止全部寫入磁碟"
+
+msgid "Allow bootloader scripts to modify disks"
+msgstr "容許開機載入器 Script 修改磁碟"
+
msgid "Petitboot System Configuration"
msgstr "Petitboot 系統配置"
#, c-format
msgid "!Invalid option %d"
-msgstr "選項 %d 無效!"
+msgstr "!無效選項 %d"
msgid "Disk"
msgstr "磁碟"
"範例:root=/dev/sda1 console=hvc0\n"
"\n"
+#, fuzzy
msgid ""
-"Autoboot: There are three possible options for automatic-boot hehaviour:\n"
-"\n"
-"Don't autoboot: boot options will be listed in the petitboot menu, but none "
-"will be booted automatically. User interaction will be required to continue "
+"Autoboot: Specify which devices to autoboot from.\n"
+"\n"
+"By selecting the 'Add Device' button new devices can be added to the "
+"autoboot list, either by UUID, MAC address, or device type. Once added to "
+"the boot order, the priority of devices can be changed with the 'left' and "
+"'right' keys Devices can be individually removed from the boot order with "
+"the minus key. Use this option if you have multiple operating system images "
+"installed.\n"
+"\n"
+"To autoboot from any device, select the 'Clear & Boot Any' button. In this "
+"case, any boot option that is marked as a default (by bootloader "
+"configuration) will be booted automatically after a timeout. Use this option "
+"if you want to quickly boot your system without changing any boot option "
+"settings. This is the typical configuration.\n"
+"\n"
+"To disable autoboot, select the 'Clear' button, which will clear the boot "
+"order. With autoboot disabled, user interaction will be required to continue "
"past the petitboot menu. Use this option if you want the machine to wait for "
"an explicit boot selection, or want to interact with petitboot before "
"booting the system\n"
"\n"
-"Autoboot from any disk/network device: any boot option that is marked as a "
-"default (by bootloader configuration) will be booted automatically after a "
-"timeout. Use this option if you want to quickly boot your system without "
-"changing any boot option settings. This is the typical configuration.\n"
-"\n"
-"Only autoboot from a specific disk/network device: only boot options from a "
-"single device (specifed here) will be booted automatically after a timeout. "
-"Use this option if you have multiple operating system images installed.\n"
-"\n"
"Timeout: Specify the length of time, in seconds, that the main menu will be "
"displayed before the default boot option is started. This option is only "
"displayed if autoboot is enabled.\n"
"網路選項:\n"
"\n"
"對所有作用中介面使用 DHCP:自動將 IP 位址指派給每一個網路介面。如果您的網路中"
-"有 DHCP 伺服器,請使用此選項。\n"
+"有 DHCP 伺服器請使用此選項。\n"
"\n"
"對特定介面使用 DHCP:自動將 IP 位址指派給選定的網路介面。不配置其他介面。如果"
"您在不同的介面上具有多個 DHCP 伺服器,但在啟動期間只想配置單一介面,請選取此"
msgid "Usage"
msgstr "用法"
+
+#~ msgid "Autoboot:"
+#~ msgstr "Autoboot:"
+
+#~ msgid "Don't autoboot"
+#~ msgstr "Don't autoboot"
+
+#~ msgid "Autoboot from any disk/network device"
+#~ msgstr "Autoboot from any disk/network device"
+
+#~ msgid "Only autoboot from a specific disk/network device"
+#~ msgstr "Only autoboot from a specific disk/network device"
+
+#~ msgid "Unknown UUID: %s"
+#~ msgstr "Unknown UUID: %s"
widget_move(widget_button_base(screen->widgets.ok_b),
y, screen->field_x);
widget_move(widget_button_base(screen->widgets.help_b),
- y, screen->field_x + 10);
+ y, screen->field_x + 14);
widget_move(widget_button_base(screen->widgets.cancel_b),
- y, screen->field_x + 24);
+ y, screen->field_x + 28);
}
static void add_url_screen_setup_widgets(struct add_url_screen *screen)
_("Configuration URL:"));
screen->widgets.url_f = widget_new_textbox(set, 0, 0, 50, NULL);
- screen->widgets.ok_b = widget_new_button(set, 0, 0, 6, _("OK"),
+ screen->widgets.ok_b = widget_new_button(set, 0, 0, 10, _("OK"),
ok_click, screen);
screen->widgets.help_b = widget_new_button(set, 0, 0, 10, _("Help"),
help_click, screen);
#include <assert.h>
#include <string.h>
-#include <stdlib.h>
#include "log/log.h"
#include "talloc/talloc.h"
struct pmenu_item *item,
struct pb_boot_data *bd);
bool need_redraw;
+ bool need_update;
int label_x;
int field_x;
static int boot_editor_post(struct nc_scr *scr)
{
struct boot_editor *boot_editor = boot_editor_from_scr(scr);
- widgetset_post(boot_editor->widgetset);
+
+ if (boot_editor->need_update) {
+ boot_editor_update(boot_editor, boot_editor->cui->sysinfo);
+ boot_editor->need_update = false;
+ } else {
+ widgetset_post(boot_editor->widgetset);
+ }
+
nc_scr_frame_draw(scr);
if (boot_editor->need_redraw) {
redrawwin(scr->main_ncw);
y++;
- widget_move(widget_button_base(boot_editor->widgets.ok_b), y, 9);
- widget_move(widget_button_base(boot_editor->widgets.help_b), y, 19);
- widget_move(widget_button_base(boot_editor->widgets.cancel_b), y, 33);
+ widget_move(widget_button_base(boot_editor->widgets.ok_b), y,
+ boot_editor->field_x);
+ widget_move(widget_button_base(boot_editor->widgets.help_b), y,
+ boot_editor->field_x + 14);
+ widget_move(widget_button_base(boot_editor->widgets.cancel_b), y,
+ boot_editor->field_x + 28);
}
static void boot_editor_widget_focus(struct nc_widget *widget, void *arg)
boot_editor->widgets.args_f = widget_new_textbox(set, 0, 0,
field_size, boot_editor->args);
- boot_editor->widgets.ok_b = widget_new_button(set, 0, 0, 6,
+ boot_editor->widgets.ok_b = widget_new_button(set, 0, 0, 10,
_("OK"), ok_click, boot_editor);
boot_editor->widgets.help_b = widget_new_button(set, 0, 0, 10,
_("Help"), help_click, boot_editor);
{
int height;
+ if (boot_editor->cui->current != boot_editor_scr(boot_editor)) {
+ boot_editor->need_update = true;
+ return;
+ }
+
widgetset_unpost(boot_editor->widgetset);
height = pad_height(sysinfo ? sysinfo->n_blockdevs : 0);
pad_refresh(boot_editor);
}
-/* Return the number of columns required to display a localised string */
-static int strncols(const char *str)
-{
- int i, wlen, ncols = 0;
- wchar_t *wstr;
-
- wlen = mbstowcs(NULL, str, 0);
- if (wlen <= 0)
- return wlen;
-
- wstr = malloc(sizeof(wchar_t) * wlen + 1);
- if (!wstr)
- return -1;
-
- wlen = mbstowcs(wstr, str, wlen);
- if (wlen <= 0) {
- free(wstr);
- return wlen;
- }
-
- /* Processing each character individually lets us use the same
- * check for all languages */
- for (i = 0; i < wlen; i++) {
- ncols += wcwidth(wstr[i]);
- }
-
- free(wstr);
- return ncols;
-}
-
struct boot_editor *boot_editor_init(struct cui *cui,
struct pmenu_item *item,
const struct system_info *sysinfo,
boot_editor->on_exit = on_exit;
boot_editor->state = STATE_EDIT;
boot_editor->need_redraw = false;
+ boot_editor->need_update = false;
int ncols1 = strncols(_("Device tree:"));
int ncols2 = strncols(_("Boot arguments:"));
"Static IP configuration: Allows you to specify an IPv4 address and network \
mask, gateway, and a DNS server or servers for a network interface. Select \
this option if you do not have a DHCP server, or want explicit control of \
-network settings.");
+network settings.\n"
+"\n"
+"Disk R/W: Certain bootloader configurations may request write access to \
+disks to save information or update parameters (eg. GRUB2). "
+"Use this option to control access to disks.\n");
#include "nc-config.h"
#include "nc-widgets.h"
-#define N_FIELDS 32
+#define N_FIELDS 34
extern struct help_text config_help_text;
bool show_help;
bool show_subset;
bool need_redraw;
+ bool need_update;
void (*on_exit)(struct cui *);
struct nc_widget_label *dns_dhcp_help_l;
struct nc_widget_label *dns_help_l;
+ struct nc_widget_label *allow_write_l;
+ struct nc_widget_select *allow_write_f;
+
struct nc_widget_label *safe_mode;
struct nc_widget_button *ok_b;
struct nc_widget_button *help_b;
(void)screen;
}
-static int config_screen_post(struct nc_scr *scr)
-{
- struct config_screen *screen = config_screen_from_scr(scr);
- screen->show_subset = false;
- widgetset_post(screen->widgetset);
- nc_scr_frame_draw(scr);
- if (screen->need_redraw) {
- redrawwin(scr->main_ncw);
- screen->need_redraw = false;
- }
- wrefresh(screen->scr.main_ncw);
- pad_refresh(screen);
- return 0;
-}
-
static int config_screen_unpost(struct nc_scr *scr)
{
struct config_screen *screen = config_screen_from_scr(scr);
struct config *config;
int i, n_boot_opts, rc, idx;
unsigned int *order;
+ bool allow_write;
char mac[20];
config = config_copy(screen, screen->cui->config);
}
}
+ allow_write = widget_select_get_value(screen->widgets.allow_write_f);
+ if (allow_write != config->allow_writes)
+ config->allow_writes = allow_write;
+
config->safe_mode = false;
rc = cui_send_config(screen->cui, config);
talloc_free(config);
y += 1;
widget_move(widget_button_base(screen->widgets.boot_add_b),
- y, screen->field_x);
+ y++, screen->field_x);
widget_move(widget_button_base(screen->widgets.boot_any_b),
- y, screen->field_x + 14);
+ y++, screen->field_x);
widget_move(widget_button_base(screen->widgets.boot_none_b),
- y, screen->field_x + 34);
+ y, screen->field_x);
wf = widget_button_base(screen->widgets.boot_add_b);
if (widget_subset_n_inactive(screen->widgets.boot_order_f))
y += 1;
}
+ layout_pair(screen, y, screen->widgets.allow_write_l,
+ widget_select_base(screen->widgets.allow_write_f));
+ y += widget_height(widget_select_base(screen->widgets.allow_write_f));
+
+ y += 1;
+
widget_move(widget_button_base(screen->widgets.ok_b),
y, screen->field_x);
widget_move(widget_button_base(screen->widgets.help_b),
- y, screen->field_x + 10);
+ y, screen->field_x + 14);
widget_move(widget_button_base(screen->widgets.cancel_b),
- y, screen->field_x + 24);
+ y, screen->field_x + 28);
}
static void config_screen_network_change(void *arg, int value)
char *str, *ip, *mask, *gw;
enum net_conf_type type;
unsigned int i;
+ int add_len, clear_len, any_len, min_len = 20;
build_assert(sizeof(screen->widgets) / sizeof(struct widget *)
== N_FIELDS);
type = screen->net_conf_type;
ifcfg = first_active_interface(config);
- screen->widgets.boot_add_b = widget_new_button(set, 0, 0, 10,
+ add_len = max(min_len, strncols(_("Add Device")));
+ clear_len = max(min_len, strncols(_("Clear")));
+ any_len = max(min_len, strncols(_("Clear & Boot Any")));
+
+ screen->widgets.boot_add_b = widget_new_button(set, 0, 0, add_len,
_("Add Device"),
config_screen_add_device, screen);
- screen->widgets.boot_none_b = widget_new_button(set, 0, 0, 10,
+ screen->widgets.boot_none_b = widget_new_button(set, 0, 0, clear_len,
_("Clear"),
config_screen_autoboot_none, screen);
- screen->widgets.boot_any_b = widget_new_button(set, 0, 0, 16,
+ screen->widgets.boot_any_b = widget_new_button(set, 0, 0, any_len,
_("Clear & Boot Any"),
config_screen_autoboot_any, screen);
widget_subset_add_option(screen->widgets.boot_order_f, label);
}
- for (i = DEVICE_TYPE_NETWORK; i < DEVICE_TYPE_NETWORK + 4; i++) {
+ for (i = DEVICE_TYPE_NETWORK; i < DEVICE_TYPE_UNKNOWN; i++) {
char *label;
if (i == DEVICE_TYPE_ANY)
}
screen->widgets.network_l = widget_new_label(set, 0, 0, _("Network:"));
- screen->widgets.network_f = widget_new_select(set, 0, 0, 50);
+ screen->widgets.network_f = widget_new_select(set, 0, 0,
+ COLS - screen->field_x - 1);
widget_select_add_option(screen->widgets.network_f,
NET_CONF_TYPE_DHCP_ALL,
screen->widgets.safe_mode = widget_new_label(set, 0, 0,
_("Selecting 'OK' will exit safe mode"));
- screen->widgets.ok_b = widget_new_button(set, 0, 0, 6, _("OK"),
+ screen->widgets.allow_write_l = widget_new_label(set, 0, 0,
+ _("Disk R/W:"));
+ screen->widgets.allow_write_f = widget_new_select(set, 0, 0,
+ COLS - screen->field_x - 1);
+
+ widget_select_add_option(screen->widgets.allow_write_f, 0,
+ _("Prevent all writes to disk"),
+ !config->allow_writes);
+
+ widget_select_add_option(screen->widgets.allow_write_f, 1,
+ _("Allow bootloader scripts to modify disks"),
+ config->allow_writes);
+
+ screen->widgets.ok_b = widget_new_button(set, 0, 0, 10, _("OK"),
ok_click, screen);
screen->widgets.help_b = widget_new_button(set, 0, 0, 10, _("Help"),
help_click, screen);
static void config_screen_widget_focus(struct nc_widget *widget, void *arg)
{
struct config_screen *screen = arg;
- int w_y, s_max;
+ int w_y, w_height, w_focus, s_max, adjust;
- w_y = widget_y(widget) + widget_focus_y(widget);
+ w_height = widget_height(widget);
+ w_focus = widget_focus_y(widget);
+ w_y = widget_y(widget) + w_focus;
s_max = getmaxy(screen->scr.sub_ncw) - 1;
if (w_y < screen->scroll_y)
screen->scroll_y = w_y;
- else if (w_y + screen->scroll_y + 1 > s_max)
- screen->scroll_y = 1 + w_y - s_max;
-
- else
+ else if (w_y + screen->scroll_y + 1 > s_max) {
+ /* Fit as much of the widget into the screen as possible */
+ adjust = min(s_max - 1, w_height - w_focus);
+ if (w_y + adjust >= screen->scroll_y + s_max)
+ screen->scroll_y = max(0, 1 + w_y + adjust - s_max);
+ } else
return;
pad_refresh(screen);
const struct config *config,
const struct system_info *sysinfo)
{
+ if (screen->cui->current != config_screen_scr(screen)) {
+ screen->need_update = true;
+ return;
+ }
+
config_screen_draw(screen, config, sysinfo);
pad_refresh(screen);
}
+static int config_screen_post(struct nc_scr *scr)
+{
+ struct config_screen *screen = config_screen_from_scr(scr);
+ screen->show_subset = false;
+
+ if (screen->need_update) {
+ config_screen_draw(screen, screen->cui->config,
+ screen->cui->sysinfo);
+ screen->need_update = false;
+ } else {
+ widgetset_post(screen->widgetset);
+ }
+
+ nc_scr_frame_draw(scr);
+ if (screen->need_redraw) {
+ redrawwin(scr->main_ncw);
+ screen->need_redraw = false;
+ }
+ wrefresh(screen->scr.main_ncw);
+ pad_refresh(screen);
+ return 0;
+}
+
static int config_screen_destroy(void *arg)
{
struct config_screen *screen = arg;
screen->cui = cui;
screen->on_exit = on_exit;
screen->need_redraw = false;
+ screen->need_update = false;
screen->label_x = 2;
screen->field_x = 17;
if (cui->sysinfo_screen)
sysinfo_screen_update(cui->sysinfo_screen, sysinfo);
+ if (cui->subset_screen)
+ subset_screen_update(cui->subset_screen);
+
/* ... and do the same with the config screen... */
if (cui->config_screen)
config_screen_update(cui->config_screen, cui->config, sysinfo);
if (config->lang)
cui_update_language(cui, config->lang);
+ if (cui->subset_screen)
+ subset_screen_update(cui->subset_screen);
+
if (cui->config_screen)
config_screen_update(cui->config_screen, config, cui->sysinfo);
widget_move(widget_button_base(screen->widgets.ok_b),
y, screen->field_x);
widget_move(widget_button_base(screen->widgets.cancel_b),
- y, screen->field_x + 10);
+ y, screen->field_x + 14);
}
static void lang_screen_setup_empty(struct lang_screen *screen)
screen->widgets.safe_mode = widget_new_label(set, 0, 0,
_("Selecting 'OK' will exit safe mode"));
- screen->widgets.ok_b = widget_new_button(set, 0, 0, 6, _("OK"),
+ screen->widgets.ok_b = widget_new_button(set, 0, 0, 10, _("OK"),
ok_click, screen);
screen->widgets.cancel_b = widget_new_button(set, 0, 0, 10, _("Cancel"),
cancel_click, screen);
switch (dev->type) {
case DEVICE_TYPE_OPTICAL:
case DEVICE_TYPE_DISK:
+ case DEVICE_TYPE_USB:
/* Find block info */
for (i = 0; sys && i < sys->n_blockdevs; i++) {
bd = sys->blockdevs[i];
}
if (matched) {
snprintf(buf,sizeof(buf),"[%s: %s / %s]",
- dev->type == DEVICE_TYPE_DISK ?
- _("Disk") : _("CD/DVD"),
+ device_type_display_name(dev->type),
bd->name, bd->uuid);
}
break;
return screen->return_scr;
}
+void subset_screen_update(struct subset_screen *screen)
+{
+ pb_debug("Exiting subset due to update\n");
+ return screen->on_exit(screen->cui);
+}
+
static struct subset_screen *subset_screen_from_scr(struct nc_scr *scr)
{
struct subset_screen *subset_screen;
const struct system_info *sysinfo)
{
sysinfo_screen_populate(screen, sysinfo);
- text_screen_draw(&screen->text_scr);
+
+ if (screen->text_scr.cui->help_screen)
+ screen->text_scr.need_update = true;
+ else
+ text_screen_draw(&screen->text_scr);
}
struct sysinfo_screen *sysinfo_screen_init(struct cui *cui,
static int text_screen_post(struct nc_scr *scr)
{
+ struct text_screen *screen = text_screen_from_scr(scr);
+
+ if (screen->need_update) {
+ text_screen_draw(screen);
+ screen->need_update = false;
+ }
+
nc_scr_frame_draw(scr);
redrawwin(scr->main_ncw);
wrefresh(scr->main_ncw);
screen->cui = cui;
screen->on_exit = on_exit;
+ screen->need_update = false;
screen->scr.frame.ltitle = talloc_strdup(screen, title);
screen->scr.frame.rtitle = NULL;
int n_lines;
int n_alloc_lines;
int scroll_y;
+ bool need_update;
const char *help_title;
const struct help_text *help_text;
void (*on_exit)(struct cui *);
#include <types/types.h>
#include <log/log.h>
#include <util/util.h>
+#include <i18n/i18n.h>
+#include <fold/fold.h>
#include "nc-cui.h"
#include "nc-widgets.h"
char *str;
int val;
FIELD *field;
+ int lines;
} *options;
int top, left, size;
int n_options, selected_option;
static void select_move(struct nc_widget *widget, int y, int x)
{
struct nc_widget_select *select = to_select(widget);
- int i;
+ int i, cur = 0;
- for (i = 0; i < select->n_options; i++)
- field_move(select->options[i].field, y + i, x);
+ for (i = 0; i < select->n_options; i++) {
+ field_move(select->options[i].field, y + cur, x);
+ cur += select->options[i].lines;
+ }
}
static void select_field_focus(struct nc_widget *widget, FIELD *field)
{
struct nc_widget_select *select = to_select(widget);
- int i;
+ int i, cur = 0;
for (i = 0; i < select->n_options; i++) {
- if (field != select->options[i].field)
+ if (field != select->options[i].field) {
+ cur += select->options[i].lines;
continue;
- widget->focus_y = i;
+ }
+ widget->focus_y = cur;
return;
}
}
return select;
}
+static int widget_select_fold_cb(void *arg, const char *buf, int len)
+{
+ struct nc_widget_select *select = arg;
+ char *line, *newstr, *padbuf = NULL;
+ int i, pad;
+
+ if (!len)
+ return 0;
+
+ line = talloc_strndup(select->options, buf, len);
+
+ i = select->n_options - 1;
+ pad = max(0, select->widget.width - strncols(line));
+
+ if (pad) {
+ padbuf = talloc_array(select->options, char, pad + 1);
+ memset(padbuf, ' ', pad);
+ padbuf[pad] = '\0';
+ }
+
+ if (select->options[i].str)
+ newstr = talloc_asprintf_append(select->options[i].str,
+ "%s%s", line,
+ pad ? padbuf : "");
+ else
+ newstr = talloc_asprintf(select->options, "%s%s", line,
+ pad ? padbuf : "");
+
+ select->options[i].str = newstr;
+ select->options[i].lines++;
+
+ talloc_free(padbuf);
+ talloc_free(line);
+ return 0;
+}
+
void widget_select_add_option(struct nc_widget_select *select, int value,
const char *text, bool selected)
{
const char *str;
+ char *full_text;
FIELD *f;
int i;
str = select_unselected_str;
i = select->n_options++;
- select->widget.height = select->n_options;
-
select->options = talloc_realloc(select, select->options,
struct select_option, i + 2);
select->options[i].val = value;
- select->options[i].str = talloc_asprintf(select->options,
- "%s %s", str, text);
+ select->options[i].lines = 0;
+ select->options[i].str = NULL;
- select->options[i].field = f = new_field(1, select->size,
- select->top + i,
- select->left, 0, 0);
+ full_text = talloc_asprintf(select->options, "%s %s", str, text);
+ fold_text(full_text, select->widget.width,
+ widget_select_fold_cb, select);
- field_opts_off(f, O_WRAP | O_EDIT);
+ select->options[i].field = f = new_field(select->options[i].lines,
+ select->size,
+ select->top + select->widget.height,
+ select->left, 0, 0);
+
+ select->widget.height += select->options[i].lines;
+
+ field_opts_off(f, O_EDIT);
set_field_userptr(f, &select->widget);
set_field_buffer(f, 0, select->options[i].str);
widgetset_add_field(select->set, f);
+ talloc_free(full_text);
}
int widget_select_get_value(struct nc_widget_select *select)
int widget_select_height(struct nc_widget_select *select)
{
- return select->n_options;
+ return select->widget.height;
}
void widget_select_on_change(struct nc_widget_select *select,
void (*click)(void *), void *arg)
{
struct nc_widget_button *button;
+ int idx, len, pad1, pad2, bufsz;
char *text;
FIELD *f;
- int idx, len;
+
+ int field_size = size + 2;
button = talloc_zero(set, struct nc_widget_button);
button->widget.height = 1;
- button->widget.width = size;
+ button->widget.width = field_size;
button->widget.x = x;
button->widget.y = y;
- button->widget.field = f = new_field(1, size + 2, y, x, 0, 0);
+ button->widget.field = f = new_field(1, field_size, y, x, 0, 0);
button->widget.process_key = button_process_key;
button->widget.focussed_attr = A_REVERSE;
button->widget.unfocussed_attr = A_NORMAL;
field_opts_off(f, O_EDIT);
set_field_userptr(f, &button->widget);
- /* center str in a size-char buffer, but don't overrun */
- len = strlen(str);
- len = min(len, size);
- idx = (size - len) / 2;
+ /* Center str in the field. This depends on the number of columns used
+ * by the string, not the number of chars in str */
+ len = strncols(str);
+ if (len <= size) {
+ idx = (field_size - len) / 2;
+ } else {
+ idx = 1;
+ pb_log("Warning: '%s' %d columns wide "
+ "but button is %d columns wide\n",
+ str, len, size);
+ }
+
+ pad1 = max(idx - 1, 0);
+ pad2 = max(size - len - pad1, 0);
+ bufsz = 1 + pad1 + strlen(str) + pad2 + 2;
- text = talloc_array(button, char, size + 3);
- memset(text, ' ', size + 2);
- memcpy(text + idx + 1, str, len);
+ text = talloc_array(button, char, bufsz);
+ memset(text, ' ', bufsz);
+ memcpy(text + idx, str, strlen(str));
text[0] = '[';
- text[size + 1] = ']';
- text[size + 2] = '\0';
+ text[bufsz - 2] = ']';
+ text[bufsz - 1] = '\0';
set_field_buffer(f, 0, text);
switch (type) {
case DEVICE_TYPE_DISK:
return "disk";
+ case DEVICE_TYPE_USB:
+ return "usb";
case DEVICE_TYPE_NETWORK:
return "network";
case DEVICE_TYPE_OPTICAL:
config->safe_mode ? "enabled" : "disabled");
print_one_config(ctx, var, "debug", "%s",
config->debug ? "enabled" : "disabled");
+ print_one_config(ctx, var, "dm-snapshots", "%s",
+ config->disable_snapshots ? "disabled" : "enabled");
}
int main(int argc, char **argv)