void list_disk_geometry(struct fdisk_context *cxt) { char *id = NULL; uint64_t bytes = cxt->total_sectors * cxt->sector_size; char *strsz = size_to_human_string(SIZE_SUFFIX_SPACE | SIZE_SUFFIX_3LETTER, bytes); fdisk_colon(cxt, _("Disk %s: %s, %ju bytes, %ju sectors"), cxt->dev_path, strsz, bytes, (uintmax_t) cxt->total_sectors); free(strsz); if (fdisk_require_geometry(cxt) || fdisk_context_use_cylinders(cxt)) fdisk_colon(cxt, _("Geometry: %d heads, %llu sectors/track, %llu cylinders"), cxt->geom.heads, cxt->geom.sectors, cxt->geom.cylinders); fdisk_colon(cxt, _("Units: %s of %d * %ld = %ld bytes"), fdisk_context_get_unit(cxt, PLURAL), fdisk_context_get_units_per_sector(cxt), cxt->sector_size, fdisk_context_get_units_per_sector(cxt) * cxt->sector_size); fdisk_colon(cxt, _("Sector size (logical/physical): %lu bytes / %lu bytes"), cxt->sector_size, cxt->phy_sector_size); fdisk_colon(cxt, _("I/O size (minimum/optimal): %lu bytes / %lu bytes"), cxt->min_io_size, cxt->io_size); if (cxt->alignment_offset) fdisk_colon(cxt, _("Alignment offset: %lu bytes"), cxt->alignment_offset); if (fdisk_dev_has_disklabel(cxt)) fdisk_colon(cxt, _("Disklabel type: %s"), cxt->label->name); if (fdisk_get_disklabel_id(cxt, &id) == 0 && id) fdisk_colon(cxt, _("Disk identifier: %s"), id); }
/* add a new line to @tb, the content is based on @st */ static int add_line_from_stat(struct libscols_table *tb, struct libscols_line *parent, int parent_fd, struct stat *st, const char *name) { struct libscols_line *ln; char modbuf[11], *p; mode_t mode = st->st_mode; int rc = 0; ln = scols_table_new_line(tb, parent); if (!ln) err(EXIT_FAILURE, "failed to create output line"); /* MODE; local buffer, use scols_line_set_data() that calls strdup() */ xstrmode(mode, modbuf); if (scols_line_set_data(ln, COL_MODE, modbuf)) goto fail; /* SIZE; already allocated string, use scols_line_refer_data() */ p = size_to_human_string(0, st->st_size); if (!p || scols_line_refer_data(ln, COL_SIZE, p)) goto fail; /* NAME */ if (scols_line_set_data(ln, COL_NAME, name)) goto fail; /* colors */ if (scols_table_colors_wanted(tb)) { struct libscols_cell *ce = scols_line_get_cell(ln, COL_NAME); if (S_ISDIR(mode)) scols_cell_set_color(ce, "blue"); else if (S_ISLNK(mode)) scols_cell_set_color(ce, "cyan"); else if (S_ISBLK(mode)) scols_cell_set_color(ce, "magenta"); else if ((mode & S_IXOTH) || (mode & S_IXGRP) || (mode & S_IXUSR)) scols_cell_set_color(ce, "green"); } if (S_ISDIR(st->st_mode)) { int fd; if (parent_fd >= 0) fd = openat(parent_fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC); else fd = open(name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC); if (fd >= 0) { rc = add_children(tb, ln, fd); close(fd); } } return rc; fail: err(EXIT_FAILURE, "failed to create cell data"); return -1; }
/* returns: 0 = success, 1 = unsupported, < 0 = error */ static int fstrim_filesystem(const char *path, struct fstrim_range *rangetpl, int verbose, int dryrun) { int fd, rc; struct stat sb; struct fstrim_range range; /* kernel modifies the range */ memcpy(&range, rangetpl, sizeof(range)); fd = open(path, O_RDONLY); if (fd < 0) { warn(_("cannot open %s"), path); rc = -errno; goto done; } if (fstat(fd, &sb) == -1) { warn(_("stat of %s failed"), path); rc = -errno; goto done; } if (!S_ISDIR(sb.st_mode)) { warnx(_("%s: not a directory"), path); rc = -EINVAL; goto done; } if (dryrun) { printf(_("%s (dry run)\n"), path); rc = 0; goto done; } errno = 0; if (ioctl(fd, FITRIM, &range)) { rc = errno == EOPNOTSUPP || errno == ENOTTY ? 1 : -errno; if (rc != 1) warn(_("%s: FITRIM ioctl failed"), path); goto done; } if (verbose) { char *str = size_to_human_string( SIZE_SUFFIX_3LETTER | SIZE_SUFFIX_SPACE, (uint64_t) range.len); /* TRANSLATORS: The standard value here is a very large number. */ printf(_("%s: %s (%" PRIu64 " bytes) trimmed\n"), path, str, (uint64_t) range.len); free(str); } rc = 0; done: if (fd >= 0) close(fd); return rc; }
int fdisk_info_new_partition( struct fdisk_context *cxt, int num, sector_t start, sector_t stop, struct fdisk_parttype *t) { int rc; char *str = size_to_human_string(SIZE_SUFFIX_3LETTER | SIZE_SUFFIX_SPACE, (uint64_t)(stop - start + 1) * cxt->sector_size); rc = fdisk_sinfo(cxt, FDISK_INFO_SUCCESS, _("Created a new partition %d of type '%s' and of size %s."), num, t ? t->name : _("Unknown"), str); free(str); return rc; }
void list_disk_geometry(struct fdisk_context *cxt) { char *id = NULL; struct fdisk_label *lb = fdisk_get_label(cxt, NULL); uint64_t bytes = fdisk_get_nsectors(cxt) * fdisk_get_sector_size(cxt); char *strsz = size_to_human_string(SIZE_SUFFIX_SPACE | SIZE_SUFFIX_3LETTER, bytes); color_scheme_enable("header", UL_COLOR_BOLD); fdisk_info(cxt, _("Disk %s: %s, %ju bytes, %ju sectors"), fdisk_get_devname(cxt), strsz, bytes, (uintmax_t) fdisk_get_nsectors(cxt)); color_disable(); free(strsz); if (lb && (fdisk_label_require_geometry(lb) || fdisk_use_cylinders(cxt))) fdisk_info(cxt, _("Geometry: %d heads, %llu sectors/track, %llu cylinders"), fdisk_get_geom_heads(cxt), fdisk_get_geom_sectors(cxt), fdisk_get_geom_cylinders(cxt)); fdisk_info(cxt, _("Units: %s of %d * %ld = %ld bytes"), fdisk_get_unit(cxt, FDISK_PLURAL), fdisk_get_units_per_sector(cxt), fdisk_get_sector_size(cxt), fdisk_get_units_per_sector(cxt) * fdisk_get_sector_size(cxt)); fdisk_info(cxt, _("Sector size (logical/physical): %lu bytes / %lu bytes"), fdisk_get_sector_size(cxt), fdisk_get_physector_size(cxt)); fdisk_info(cxt, _("I/O size (minimum/optimal): %lu bytes / %lu bytes"), fdisk_get_minimal_iosize(cxt), fdisk_get_optimal_iosize(cxt)); if (fdisk_get_alignment_offset(cxt)) fdisk_info(cxt, _("Alignment offset: %lu bytes"), fdisk_get_alignment_offset(cxt)); if (fdisk_has_label(cxt)) fdisk_info(cxt, _("Disklabel type: %s"), fdisk_label_get_name(lb)); if (fdisk_get_disklabel_id(cxt, &id) == 0 && id) fdisk_info(cxt, _("Disk identifier: %s"), id); }
void ipc_print_size(int unit, char *msg, uint64_t size, const char *end, int width) { char format[32]; if (!msg) /* NULL */ ; else if (msg[strlen(msg) - 1] == '=') printf("%s", msg); else if (unit == IPC_UNIT_BYTES) printf(_("%s (bytes) = "), msg); else if (unit == IPC_UNIT_KB) printf(_("%s (kbytes) = "), msg); else printf("%s = ", msg); switch (unit) { case IPC_UNIT_DEFAULT: case IPC_UNIT_BYTES: sprintf(format, "%%%dju", width); printf(format, size); break; case IPC_UNIT_KB: sprintf(format, "%%%dju", width); printf(format, size / 1024); break; case IPC_UNIT_HUMAN: { char *tmp; sprintf(format, "%%%ds", width); printf(format, (tmp = size_to_human_string(SIZE_SUFFIX_1LETTER, size))); free(tmp); break; } default: /* impossible occurred */ abort(); } if (end) printf("%s", end); }
static void dig_holes(int fd, off_t off, off_t len) { off_t end = len ? off + len : 0; off_t hole_start = 0, hole_sz = 0; uintmax_t ct = 0; size_t bufsz; char *buf; struct stat st; #if defined(POSIX_FADV_SEQUENTIAL) && defined(HAVE_POSIX_FADVISE) off_t cache_start = off; /* * We don't want to call POSIX_FADV_DONTNEED to discard cached * data in PAGE_SIZE steps. IMHO it's overkill (too many syscalls). * * Let's assume that 1MiB (on system with 4K page size) is just * a good compromise. * -- kzak Feb-2014 */ const size_t cachesz = getpagesize() * 256; #endif if (fstat(fd, &st) != 0) err(EXIT_FAILURE, _("stat of %s failed"), filename); bufsz = st.st_blksize; if (lseek(fd, off, SEEK_SET) < 0) err(EXIT_FAILURE, _("seek on %s failed"), filename); /* buffer + extra space for is_nul() sentinel */ buf = xmalloc(bufsz + sizeof(uintptr_t)); #if defined(POSIX_FADV_SEQUENTIAL) && defined(HAVE_POSIX_FADVISE) posix_fadvise(fd, off, 0, POSIX_FADV_SEQUENTIAL); #endif while (end == 0 || off < end) { ssize_t rsz; rsz = pread(fd, buf, bufsz, off); if (rsz < 0 && errno) err(EXIT_FAILURE, _("%s: read failed"), filename); if (end && rsz > 0 && off > end - rsz) rsz = end - off; if (rsz <= 0) break; if (is_nul(buf, rsz)) { if (!hole_sz) { /* new hole detected */ int rc = skip_hole(fd, &off); if (rc == 0) continue; /* hole skipped */ else if (rc == 1) break; /* end of file */ hole_start = off; } hole_sz += rsz; } else if (hole_sz) { xfallocate(fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE, hole_start, hole_sz); ct += hole_sz; hole_sz = hole_start = 0; } #if defined(POSIX_FADV_DONTNEED) && defined(HAVE_POSIX_FADVISE) /* discard cached data */ if (off - cache_start > (off_t) cachesz) { size_t clen = off - cache_start; clen = (clen / cachesz) * cachesz; posix_fadvise(fd, cache_start, clen, POSIX_FADV_DONTNEED); cache_start = cache_start + clen; } #endif off += rsz; } if (hole_sz) { xfallocate(fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE, hole_start, hole_sz); ct += hole_sz; } free(buf); if (verbose) { char *str = size_to_human_string(SIZE_SUFFIX_3LETTER | SIZE_SUFFIX_SPACE, ct); fprintf(stdout, _("%s: %s (%ju bytes) converted to sparse holes.\n"), filename, str, ct); free(str); } }
/** * fdisk_partition_to_string: * @pa: partition * @cxt: context * @id: field (FDISK_FIELD_*) * @data: returns string with allocated data * * Returns info about partition converted to printable string. * * For example * <informalexample> * <programlisting> * struct fdisk_parition *pa; * * fdisk_get_partition(cxt, 0, &pa); * fdisk_partition_to_string(pa, FDISK_FIELD_UUID, &data); * printf("first partition uuid: %s\n", data); * free(data); * fdisk_unref_partition(pa); * </programlisting> * </informalexample> * * returns UUID for the first partition. * * Returns: 0 on success, otherwise, a corresponding error. */ int fdisk_partition_to_string(struct fdisk_partition *pa, struct fdisk_context *cxt, int id, char **data) { char *p = NULL; int rc = 0; uint64_t x; if (!pa || !cxt || !data) return -EINVAL; switch (id) { case FDISK_FIELD_DEVICE: if (pa->freespace) p = strdup(_("Free space")); else if (fdisk_partition_has_partno(pa) && cxt->dev_path) { if (cxt->label->flags & FDISK_LABEL_FL_INCHARS_PARTNO) rc = asprintf(&p, "%c", (int) pa->partno + 'a'); else p = fdisk_partname(cxt->dev_path, pa->partno + 1); } break; case FDISK_FIELD_BOOT: p = fdisk_partition_is_bootable(pa) ? strdup("*") : NULL; break; case FDISK_FIELD_START: if (fdisk_partition_has_start(pa)) { x = fdisk_cround(cxt, pa->start); rc = pa->start_post ? asprintf(&p, "%ju%c", x, pa->start_post) : asprintf(&p, "%ju", x); } break; case FDISK_FIELD_END: if (fdisk_partition_has_end(pa)) { x = fdisk_cround(cxt, fdisk_partition_get_end(pa)); rc = pa->end_post ? asprintf(&p, "%ju%c", x, pa->end_post) : asprintf(&p, "%ju", x); } break; case FDISK_FIELD_SIZE: if (fdisk_partition_has_size(pa)) { uint64_t sz = pa->size * cxt->sector_size; switch (cxt->sizeunit) { case FDISK_SIZEUNIT_BYTES: rc = asprintf(&p, "%ju", sz); break; case FDISK_SIZEUNIT_HUMAN: if (fdisk_is_details(cxt)) rc = pa->size_post ? asprintf(&p, "%ju%c", sz, pa->size_post) : asprintf(&p, "%ju", sz); else { p = size_to_human_string(SIZE_SUFFIX_1LETTER, sz); if (!p) rc = -ENOMEM; } break; } } break; case FDISK_FIELD_CYLINDERS: rc = asprintf(&p, "%ju", (uintmax_t) fdisk_cround(cxt, fdisk_partition_has_size(pa) ? pa->size : 0)); break; case FDISK_FIELD_SECTORS: rc = asprintf(&p, "%ju", fdisk_partition_has_size(pa) ? (uintmax_t) pa->size : 0); break; case FDISK_FIELD_BSIZE: rc = asprintf(&p, "%ju", pa->bsize); break; case FDISK_FIELD_FSIZE: rc = asprintf(&p, "%ju", pa->fsize); break; case FDISK_FIELD_CPG: rc = asprintf(&p, "%ju", pa->cpg); break; case FDISK_FIELD_TYPE: p = pa->type && pa->type->name ? strdup(_(pa->type->name)) : NULL; break; case FDISK_FIELD_TYPEID: if (pa->type && fdisk_parttype_get_string(pa->type)) rc = asprintf(&p, "%s", fdisk_parttype_get_string(pa->type)); else if (pa->type) rc = asprintf(&p, "%x", fdisk_parttype_get_code(pa->type)); break; case FDISK_FIELD_UUID: p = pa->uuid && *pa->uuid? strdup(pa->uuid) : NULL; break; case FDISK_FIELD_NAME: p = pa->name && *pa->name ? strdup(pa->name) : NULL; break; case FDISK_FIELD_ATTR: p = pa->attrs && *pa->attrs ? strdup(pa->attrs) : NULL; break; case FDISK_FIELD_SADDR: p = pa->start_chs && *pa->start_chs ? strdup(pa->start_chs) : NULL; break; case FDISK_FIELD_EADDR: p = pa->end_chs && *pa->end_chs? strdup(pa->end_chs) : NULL; break; default: return -EINVAL; } if (rc < 0) { rc = -ENOMEM; free(p); p = NULL; } else if (rc > 0) rc = 0; *data = p; return rc; }
void list_freespace(struct fdisk_context *cxt) { struct fdisk_table *tb = NULL; struct fdisk_partition *pa = NULL; struct fdisk_iter *itr = NULL; struct libscols_table *out = NULL; const char *bold = NULL; size_t i; uintmax_t sumsize = 0, bytes = 0; char *strsz; static const char *colnames[] = { N_("Start"), N_("End"), N_("Sectors"), N_("Size") }; static const int colids[] = { FDISK_FIELD_START, FDISK_FIELD_END, FDISK_FIELD_SECTORS, FDISK_FIELD_SIZE }; if (fdisk_get_freespaces(cxt, &tb)) goto done; itr = fdisk_new_iter(FDISK_ITER_FORWARD); if (!itr) { fdisk_warn(cxt, _("failed to allocate iterator")); goto done; } out = scols_new_table(); if (!out) { fdisk_warn(cxt, _("failed to allocate output table")); goto done; } if (colors_wanted()) { scols_table_enable_colors(out, 1); bold = color_scheme_get_sequence("header", UL_COLOR_BOLD); } for (i = 0; i < ARRAY_SIZE(colnames); i++) { struct libscols_column *co = scols_table_new_column(out, _(colnames[i]), 5, SCOLS_FL_RIGHT); if (!co) goto done; if (bold) scols_cell_set_color(scols_column_get_header(co), bold); } /* fill-in output table */ while (fdisk_table_next_partition(tb, itr, &pa) == 0) { struct libscols_line *ln = scols_table_new_line(out, NULL); char *data; if (!ln) { fdisk_warn(cxt, _("failed to allocate output line")); goto done; } for (i = 0; i < ARRAY_SIZE(colids); i++) { if (fdisk_partition_to_string(pa, cxt, colids[i], &data)) continue; scols_line_refer_data(ln, i, data); } if (fdisk_partition_has_size(pa)) sumsize += fdisk_partition_get_size(pa); } bytes = sumsize * fdisk_get_sector_size(cxt); strsz = size_to_human_string(SIZE_SUFFIX_SPACE | SIZE_SUFFIX_3LETTER, bytes); color_scheme_enable("header", UL_COLOR_BOLD); fdisk_info(cxt, _("Unpartitioned space %s: %s, %ju bytes, %ju sectors"), fdisk_get_devname(cxt), strsz, bytes, sumsize); color_disable(); free(strsz); fdisk_info(cxt, _("Units: %s of %d * %ld = %ld bytes"), fdisk_get_unit(cxt, FDISK_PLURAL), fdisk_get_units_per_sector(cxt), fdisk_get_sector_size(cxt), fdisk_get_units_per_sector(cxt) * fdisk_get_sector_size(cxt)); fdisk_info(cxt, _("Sector size (logical/physical): %lu bytes / %lu bytes"), fdisk_get_sector_size(cxt), fdisk_get_physector_size(cxt)); /* print */ if (!scols_table_is_empty(out)) { fdisk_info(cxt, ""); /* line break */ scols_print_table(out); } done: scols_unref_table(out); fdisk_unref_table(tb); fdisk_free_iter(itr); }
int main(int argc, char **argv) { struct mkswap_control ctl = { .fd = -1 }; int c; uint64_t sz; int version = SWAP_VERSION; char *block_count = NULL, *strsz = NULL; #ifdef HAVE_LIBUUID const char *opt_uuid = NULL; uuid_t uuid_dat; #endif static const struct option longopts[] = { { "check", no_argument, 0, 'c' }, { "force", no_argument, 0, 'f' }, { "pagesize", required_argument, 0, 'p' }, { "label", required_argument, 0, 'L' }, { "swapversion", required_argument, 0, 'v' }, { "uuid", required_argument, 0, 'U' }, { "version", no_argument, 0, 'V' }, { "help", no_argument, 0, 'h' }, { NULL, 0, 0, 0 } }; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); atexit(close_stdout); while((c = getopt_long(argc, argv, "cfp:L:v:U:Vh", longopts, NULL)) != -1) { switch (c) { case 'c': ctl.check = 1; break; case 'f': ctl.force = 1; break; case 'p': ctl.user_pagesize = strtou32_or_err(optarg, _("parsing page size failed")); break; case 'L': ctl.opt_label = optarg; break; case 'v': version = strtos32_or_err(optarg, _("parsing version number failed")); if (version != SWAP_VERSION) errx(EXIT_FAILURE, _("swapspace version %d is not supported"), version); break; case 'U': #ifdef HAVE_LIBUUID opt_uuid = optarg; #else warnx(_("warning: ignoring -U (UUIDs are unsupported by %s)"), program_invocation_short_name); #endif break; case 'V': printf(UTIL_LINUX_VERSION); exit(EXIT_SUCCESS); case 'h': usage(stdout); default: usage(stderr); } } if (optind < argc) ctl.devname = argv[optind++]; if (optind < argc) block_count = argv[optind++]; if (optind != argc) { warnx(_("only one device argument is currently supported")); usage(stderr); } #ifdef HAVE_LIBUUID if(opt_uuid) { if (uuid_parse(opt_uuid, uuid_dat) != 0) errx(EXIT_FAILURE, _("error: parsing UUID failed")); } else uuid_generate(uuid_dat); ctl.uuid = uuid_dat; #endif init_signature_page(&ctl); /* get pagesize and allocate signature page */ if (!ctl.devname) { warnx(_("error: Nowhere to set up swap on?")); usage(stderr); } if (block_count) { /* this silly user specified the number of blocks explicitly */ uint64_t blks = strtou64_or_err(block_count, _("invalid block count argument")); ctl.npages = blks / (ctl.pagesize / 1024); } sz = get_size(&ctl); if (!ctl.npages) ctl.npages = sz; else if (ctl.npages > sz && !ctl.force) errx(EXIT_FAILURE, _("error: " "size %llu KiB is larger than device size %ju KiB"), ctl.npages * (ctl.pagesize / 1024), sz * (ctl.pagesize / 1024)); if (ctl.npages < MIN_GOODPAGES) errx(EXIT_FAILURE, _("error: swap area needs to be at least %ld KiB"), (long)(MIN_GOODPAGES * ctl.pagesize / 1024)); if (ctl.npages > UINT32_MAX) { /* true when swap is bigger than 17.59 terabytes */ ctl.npages = UINT32_MAX; warnx(_("warning: truncating swap area to %llu KiB"), ctl.npages * ctl.pagesize / 1024); } if (is_mounted(ctl.devname)) errx(EXIT_FAILURE, _("error: " "%s is mounted; will not make swapspace"), ctl.devname); open_device(&ctl); if (ctl.check) check_blocks(&ctl); wipe_device(&ctl); assert(ctl.hdr); ctl.hdr->version = version; ctl.hdr->last_page = ctl.npages - 1; ctl.hdr->nr_badpages = ctl.nbadpages; if ((ctl.npages - MIN_GOODPAGES) < ctl.nbadpages) errx(EXIT_FAILURE, _("Unable to set up swap-space: unreadable")); sz = (ctl.npages - ctl.nbadpages - 1) * ctl.pagesize; strsz = size_to_human_string(SIZE_SUFFIX_SPACE | SIZE_SUFFIX_3LETTER, sz); printf(_("Setting up swapspace version %d, size = %s (%ju bytes)\n"), version, strsz, sz); free(strsz); set_signature(&ctl); set_uuid_and_label(&ctl); write_header_to_device(&ctl); deinit_signature_page(&ctl); #ifdef HAVE_LIBSELINUX if (S_ISREG(ctl.devstat.st_mode) && is_selinux_enabled() > 0) { security_context_t context_string; security_context_t oldcontext; context_t newcontext; if (fgetfilecon(ctl.fd, &oldcontext) < 0) { if (errno != ENODATA) err(EXIT_FAILURE, _("%s: unable to obtain selinux file label"), ctl.devname); if (matchpathcon(ctl.devname, ctl.devstat.st_mode, &oldcontext)) errx(EXIT_FAILURE, _("unable to matchpathcon()")); } if (!(newcontext = context_new(oldcontext))) errx(EXIT_FAILURE, _("unable to create new selinux context")); if (context_type_set(newcontext, SELINUX_SWAPFILE_TYPE)) errx(EXIT_FAILURE, _("couldn't compute selinux context")); context_string = context_str(newcontext); if (strcmp(context_string, oldcontext)!=0) { if (fsetfilecon(ctl.fd, context_string)) err(EXIT_FAILURE, _("unable to relabel %s to %s"), ctl.devname, context_string); } context_free(newcontext); freecon(oldcontext); } #endif /* * A subsequent swapon() will fail if the signature * is not actually on disk. (This is a kernel bug.) * The fsync() in close_fd() will take care of writing. */ if (close_fd(ctl.fd) != 0) err(EXIT_FAILURE, _("write failed")); return EXIT_SUCCESS; }