static void check_blocks(void) { unsigned int current_page; int do_seek = 1; char *buffer; buffer = xmalloc(pagesize); current_page = 0; while (current_page < PAGES) { if (!check && version == 0) { page_ok(current_page++); continue; } if (do_seek && lseek(DEV, current_page * pagesize, SEEK_SET) != current_page * pagesize) bb_error_msg_and_die("seek failed in check_blocks"); if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) { current_page++; if (version == 0) bit_test_and_clear(signature_page, current_page); else { if (badpages == MAX_BADPAGES) bb_error_msg_and_die("too many bad pages"); p->badpages[badpages] = current_page; } badpages++; continue; } page_ok(current_page++); } if (ENABLE_FEATURE_CLEAN_UP) free(buffer); if (badpages > 0) printf("%d bad page%s\n", badpages, (badpages==1)?"":"s"); }
static inline void page_bad(int page) { if (version == 0) bit_test_and_clear(signature_page, page); else { if (badpages == MAX_BADPAGES) bb_error_msg_and_die("too many bad pages"); p->badpages[badpages] = page; } badpages++; }
int mkswap_main(int argc, char **argv) { char *tmp; struct stat statbuf; int sz; int maxpages; int goodpages; #ifdef __sparc__ int force = 0; #endif init_signature_page(); /* get pagesize */ bb_opt_complementally = "?"; /* call bb_show_usage internally */ sz = bb_getopt_ulflags(argc, argv, "+cfv:", &tmp); if (sz & 1) check = 1; #ifdef __sparc__ if (sz & 2) force = 1; #endif #if ENABLE_FEATURE_MKSWAP_V0 if (sz & 4) { version = bb_xgetlarg(tmp, 10, 0, 1); } else { if (get_linux_version_code() < KERNEL_VERSION(2, 1, 117)) version = 0; else version = 1; } #endif argv += optind; argc -= optind; goodpages = pagesize / 1024; /* cache division */ while (argc--) { if (device_name) { PAGES = bb_xgetlarg(argv[0], 0, 10, sz * goodpages) / goodpages; argc = 0; /* ignore any surplus args.. */ } else { device_name = argv[0]; sz = get_size(device_name); argv++; } } if (!device_name) { bb_error_msg_and_die("error: Nowhere to set up swap on?"); } if (!PAGES) { PAGES = sz; } #if 0 maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES); #else if (!version) maxpages = V0_MAX_PAGES; else if (get_linux_version_code() >= KERNEL_VERSION(2,2,1)) maxpages = V1_MAX_PAGES; else { maxpages = V1_OLD_MAX_PAGES; if (maxpages > V1_MAX_PAGES) maxpages = V1_MAX_PAGES; } #endif if (PAGES > maxpages) { PAGES = maxpages; bb_error_msg("warning: truncating swap area to %ldkB", PAGES * goodpages); } DEV = bb_xopen3(device_name, O_RDWR, 0); if (fstat(DEV, &statbuf) < 0) bb_perror_msg_and_die("%s", device_name); if (!S_ISBLK(statbuf.st_mode)) check = 0; else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) bb_error_msg_and_die("Will not try to make swapdevice on '%s'", device_name); #ifdef __sparc__ if (!force && version == 0) { /* Don't overwrite partition table unless forced */ unsigned char *buffer = (unsigned char *) signature_page; unsigned short *q, sum; if (read(DEV, buffer, 512) != 512) bb_error_msg_and_die("fatal: first page unreadable"); if (buffer[508] == 0xDA && buffer[509] == 0xBE) { q = (unsigned short *) (buffer + 510); for (sum = 0; q >= (unsigned short *) buffer;) sum ^= *q--; if (!sum) { bb_error_msg("Device '%s' contains a valid Sun disklabel.\n" "This probably means creating v0 swap would destroy your partition table\n" "No swap created. If you really want to create swap v0 on that device, use\n" "the -f option to force it.", device_name); return EXIT_FAILURE; } } } #endif if (version == 0 || check) check_blocks(); if (version == 0 && !bit_test_and_clear(signature_page, 0)) bb_error_msg_and_die("fatal: first page unreadable"); if (version == 1) { p->swap_version = version; p->last_page = PAGES - 1; p->nr_badpages = badpages; } goodpages = PAGES - badpages - 1; if (goodpages <= 0) bb_error_msg_and_die("Unable to set up swap-space: unreadable"); printf("Setting up swapspace version %d, size = %ld bytes\n", version, (long) (goodpages * pagesize)); write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2"); sz = ((version == 0) ? 0 : 1024); /* offset */ if (lseek(DEV, sz, SEEK_SET) != sz) bb_error_msg_and_die("unable to rewind swap-device"); goodpages = pagesize - sz; /* cache substraction */ if (write(DEV, (char *) signature_page + sz, goodpages) != goodpages) bb_error_msg_and_die("unable to write signature page"); /* * A subsequent swapon() will fail if the signature * is not actually on disk. (This is a kernel bug.) */ if (fsync(DEV)) bb_error_msg_and_die("fsync failed"); if (ENABLE_FEATURE_CLEAN_UP) { close(DEV); free(signature_page); } return EXIT_SUCCESS; }
int mkswap_main(int argc, char **argv) { char *tmp; struct stat statbuf; int sz; int maxpages; int goodpages; int offset; int force = 0; init_signature_page(); /* get pagesize */ while (argc-- > 1) { argv++; if (argv[0][0] != '-') { if (device_name) { int blocks_per_page = pagesize / 1024; PAGES = strtol(argv[0], &tmp, 0) / blocks_per_page; if (*tmp) bb_show_usage(); } else device_name = argv[0]; } else { switch (argv[0][1]) { case 'c': check = 1; break; case 'f': force = 1; break; case 'v': version = atoi(argv[0] + 2); break; default: bb_show_usage(); } } } if (!device_name) { bb_error_msg("error: Nowhere to set up swap on?"); bb_show_usage(); } sz = get_size(device_name); if (!PAGES) { PAGES = sz; } else if (PAGES > sz && !force) { bb_error_msg("error: size %ld is larger than device size %d", PAGES * (pagesize / 1024), sz * (pagesize / 1024)); return EXIT_FAILURE; } if (version == -1) { if (PAGES <= V0_MAX_PAGES) version = 0; else if (get_kernel_revision() < MAKE_VERSION(2, 1, 117)) version = 0; else if (pagesize < 2048) version = 0; else version = 1; } if (version != 0 && version != 1) { bb_error_msg("error: unknown version %d", version); bb_show_usage(); } if (PAGES < 10) { bb_error_msg("error: swap area needs to be at least %ldkB", (long) (10 * pagesize / 1024)); bb_show_usage(); } #if 0 maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES); #else if (!version) maxpages = V0_MAX_PAGES; else if (get_kernel_revision() >= MAKE_VERSION(2, 2, 1)) maxpages = V1_MAX_PAGES; else { maxpages = V1_OLD_MAX_PAGES; if (maxpages > V1_MAX_PAGES) maxpages = V1_MAX_PAGES; } #endif if (PAGES > maxpages) { PAGES = maxpages; bb_error_msg("warning: truncating swap area to %ldkB", PAGES * pagesize / 1024); } DEV = open(device_name, O_RDWR); if (DEV < 0 || fstat(DEV, &statbuf) < 0) bb_perror_msg_and_die("%s", device_name); if (!S_ISBLK(statbuf.st_mode)) check = 0; else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) bb_error_msg_and_die("Will not try to make swapdevice on '%s'", device_name); #ifdef __sparc__ if (!force && version == 0) { /* Don't overwrite partition table unless forced */ unsigned char *buffer = (unsigned char *) signature_page; unsigned short *q, sum; if (read(DEV, buffer, 512) != 512) bb_error_msg_and_die("fatal: first page unreadable"); if (buffer[508] == 0xDA && buffer[509] == 0xBE) { q = (unsigned short *) (buffer + 510); for (sum = 0; q >= (unsigned short *) buffer;) sum ^= *q--; if (!sum) { bb_error_msg("Device '%s' contains a valid Sun disklabel.\n" "This probably means creating v0 swap would destroy your partition table\n" "No swap created. If you really want to create swap v0 on that device, use\n" "the -f option to force it.", device_name); return EXIT_FAILURE; } } } #endif if (version == 0 || check) check_blocks(); if (version == 0 && !bit_test_and_clear(signature_page, 0)) bb_error_msg_and_die("fatal: first page unreadable"); if (version == 1) { p->version = version; p->last_page = PAGES - 1; p->nr_badpages = badpages; } goodpages = PAGES - badpages - 1; if (goodpages <= 0) bb_error_msg_and_die("Unable to set up swap-space: unreadable"); printf("Setting up swapspace version %d, size = %ld bytes\n", version, (long) (goodpages * pagesize)); write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2"); offset = ((version == 0) ? 0 : 1024); if (lseek(DEV, offset, SEEK_SET) != offset) bb_error_msg_and_die("unable to rewind swap-device"); if (write(DEV, (char *) signature_page + offset, pagesize - offset) != pagesize - offset) bb_error_msg_and_die("unable to write signature page"); /* * A subsequent swapon() will fail if the signature * is not actually on disk. (This is a kernel bug.) */ if (fsync(DEV)) bb_error_msg_and_die("fsync failed"); return EXIT_SUCCESS; }