Ignore:
Timestamp:
Nov 4, 2007, 3:16:40 AM (16 years ago)
Author:
Bruno Cornec
Message:

Update to busybox 1.7.2

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.5/mindi-busybox/util-linux/mkswap.c

    r821 r1765  
    11/* vi: set sw=4 ts=4: */
    2 /*
    3  * mkswap.c - set up a linux swap device
     2/* mkswap.c - format swap device (Linux v1 only)
    43 *
    5  * (C) 1991 Linus Torvalds. This file may be redistributed as per
    6  * the Linux copyright.
     4 * Copyright 2006 Rob Landley <rob@landley.net>
     5 *
     6 * Licensed under GPL version 2, see file LICENSE in this tarball for details.
    77 */
    88
    9 /*
    10  * 20.12.91  -  time began. Got VM working yesterday by doing this by hand.
    11  *
    12  * Usage: mkswap [-c] [-vN] [-f] device [size-in-blocks]
    13  *
    14  *  -c   for readability checking. (Use it unless you are SURE!)
    15  *  -vN  for swap areas version N. (Only N=0,1 known today.)
    16  *      -f   for forcing swap creation even if it would smash partition table.
    17  *
    18  * The device may be a block device or an image of one, but this isn't
    19  * enforced (but it's not much fun on a character device :-).
    20  *
    21  * Patches from jaggy@purplet.demon.co.uk (Mike Jagdis) to make the
    22  * size-in-blocks parameter optional added Wed Feb  8 10:33:43 1995.
    23  *
    24  * Version 1 swap area code (for kernel 2.1.117), aeb, 981010.
    25  *
    26  * Sparc fixes, jj@ultra.linux.cz (Jakub Jelinek), 981201 - mangled by aeb.
    27  * V1_MAX_PAGES fixes, jj, 990325.
    28  *
    29  * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org>
    30  * - added Native Language Support
    31  *
    32  *  from util-linux -- adapted for busybox by
    33  *  Erik Andersen <andersen@codepoet.org>. I ripped out Native Language
    34  *  Support, made some stuff smaller, and fitted for life in busybox.
    35  *
    36  */
     9#include "libbb.h"
    3710
    38 #include "busybox.h"
    39 #include <unistd.h>
    40 #include <string.h>
    41 #include <fcntl.h>
    42 #include <sys/ioctl.h>          /* for _IO */
    43 #include <sys/utsname.h>
    44 #include <asm/page.h>           /* for PAGE_SIZE and PAGE_SHIFT */
    45                 /* we also get PAGE_SIZE via getpagesize() */
    46 
    47 static char *device_name = NULL;
    48 static int DEV = -1;
    49 static long PAGES = 0;
    50 static int check = 0;
    51 static int badpages = 0;
    52 #if ENABLE_FEATURE_MKSWAP_V0
    53 static int version = -1;
    54 #else
    55 #define version 1
    56 /* and make sure that we optimize away anything which would deal with checking
    57  * the kernel revision as we have v1 support only anyway.
    58  */
    59 #undef KERNEL_VERSION
    60 #define KERNEL_VERSION(p,q,r) 1
    61 #define get_linux_version_code() 1
    62 #endif
    63 
    64 /*
    65  * The definition of the union swap_header uses the constant PAGE_SIZE.
    66  * Unfortunately, on some architectures this depends on the hardware model,
    67  * and can only be found at run time -- we use getpagesize().
    68  */
    69 
    70 static int pagesize;
    71 static unsigned int *signature_page;
    72 
    73 static struct swap_header_v1 {
    74     char bootbits[1024];        /* Space for disklabel etc. */
    75     unsigned int swap_version;
    76     unsigned int last_page;
    77     unsigned int nr_badpages;
    78     unsigned int padding[125];
    79     unsigned int badpages[1];
    80 } *p;
    81 
    82 static inline void init_signature_page(void)
    83 {
    84     pagesize = getpagesize();
    85 
    86 #ifdef PAGE_SIZE
    87     if (pagesize != PAGE_SIZE)
    88         bb_error_msg("Assuming pages of size %d", pagesize);
    89 #endif
    90     signature_page = (unsigned int *) xmalloc(pagesize);
    91     memset(signature_page, 0, pagesize);
    92     p = (struct swap_header_v1 *) signature_page;
    93 }
    94 
    95 static inline void write_signature(char *sig)
    96 {
    97     char *sp = (char *) signature_page;
    98 
    99     strncpy(sp + pagesize - 10, sig, 10);
    100 }
    101 
    102 #define V0_MAX_PAGES    (8 * (pagesize - 10))
    103 /* Before 2.2.0pre9 */
    104 #define V1_OLD_MAX_PAGES    ((0x7fffffff / pagesize) - 1)
    105 /* Since 2.2.0pre9:
    106    error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
    107    with variations on
    108     #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
    109     #define SWP_OFFSET(entry) ((entry) >> 8)
    110    on the various architectures. Below the result - yuk.
    111 
    112    Machine  pagesize    SWP_ENTRY   SWP_OFFSET  bound+1 oldbound+2
    113    i386     2^12        o<<8        e>>8        1<<24   1<<19
    114    mips     2^12        o<<15       e>>15       1<<17   1<<19
    115    alpha    2^13        o<<40       e>>40       1<<24   1<<18
    116    m68k     2^12        o<<12       e>>12       1<<20   1<<19
    117    sparc    2^{12,13}   (o&0x3ffff)<<9  (e>>9)&0x3ffff  1<<18   1<<{19,18}
    118    sparc64  2^13        o<<13       e>>13       1<<51   1<<18
    119    ppc      2^12        o<<8        e>>8        1<<24   1<<19
    120    armo     2^{13,14,15}    o<<8        e>>8        1<<24   1<<{18,17,16}
    121    armv     2^12        o<<9        e>>9        1<<23   1<<19
    122 
    123    assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
    124 
    125    The bad part is that we need to know this since the kernel will
    126    refuse a swap space if it is too large.
    127 */
    128 /* patch from jj - why does this differ from the above? */
    129 #if defined(__alpha__)
    130 #define V1_MAX_PAGES           ((1 << 24) - 1)
    131 #elif defined(__mips__)
    132 #define V1_MAX_PAGES           ((1 << 17) - 1)
    133 #elif defined(__sparc_v9__)
    134 #define V1_MAX_PAGES           ((3 << 29) - 1)
    135 #elif defined(__sparc__)
    136 #define V1_MAX_PAGES           (pagesize == 8192 ? ((3 << 29) - 1) : ((1 << 18) - 1))
    137 #else
    138 #define V1_MAX_PAGES           V1_OLD_MAX_PAGES
    139 #endif
    140 /* man page now says:
    141 The maximum useful size of a swap area now depends on the architecture.
    142 It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
    143 128GB on alpha and 3TB on sparc64.
    144 */
    145 
    146 #define MAX_BADPAGES    ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
    147 
    148 static inline void bit_set(unsigned int *addr, unsigned int nr)
    149 {
    150     unsigned int r, m;
    151 
    152     addr += nr / (8 * sizeof(int));
    153 
    154     r = *addr;
    155     m = 1 << (nr & (8 * sizeof(int) - 1));
    156 
    157     *addr = r | m;
    158 }
    159 
    160 static int bit_test_and_clear(unsigned int *addr, unsigned int nr)
    161 {
    162     unsigned int r, m;
    163 
    164     addr += nr / (8 * sizeof(int));
    165 
    166     r = *addr;
    167     m = 1 << (nr & (8 * sizeof(int) - 1));
    168 
    169     *addr = r & ~m;
    170     return (r & m) != 0;
    171 }
    172 
    173 static void page_ok(int page)
    174 {
    175     if (ENABLE_FEATURE_MKSWAP_V0) {
    176         bit_set(signature_page, page);
    177     }
    178 }
    179 
    180 static void check_blocks(void)
    181 {
    182     unsigned int current_page;
    183     int do_seek = 1;
    184     char *buffer;
    185 
    186     buffer = xmalloc(pagesize);
    187     current_page = 0;
    188     while (current_page < PAGES) {
    189         if (!check && version == 0) {
    190             page_ok(current_page++);
    191             continue;
    192         }
    193         if (do_seek && lseek(DEV, current_page * pagesize, SEEK_SET) !=
    194             current_page * pagesize)
    195             bb_error_msg_and_die("seek failed in check_blocks");
    196         if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) {
    197             current_page++;
    198             if (version == 0)
    199                 bit_test_and_clear(signature_page, current_page);
    200             else {
    201                 if (badpages == MAX_BADPAGES)
    202                     bb_error_msg_and_die("too many bad pages");
    203                 p->badpages[badpages] = current_page;
    204             }
    205             badpages++;
    206             continue;
    207         }
    208         page_ok(current_page++);
    209     }
    210     if (ENABLE_FEATURE_CLEAN_UP)
    211         free(buffer);
    212     if (badpages > 0)
    213         printf("%d bad page%s\n", badpages, (badpages==1)?"":"s");
    214 }
    215 
    216 static long valid_offset(int fd, int offset)
    217 {
    218     char ch;
    219 
    220     if (lseek(fd, offset, 0) < 0)
    221         return 0;
    222     if (read(fd, &ch, 1) < 1)
    223         return 0;
    224     return 1;
    225 }
    226 
    227 static int find_size(int fd)
    228 {
    229     unsigned int high, low;
    230 
    231     low = 0;
    232     for (high = 1; high > 0 && valid_offset(fd, high); high *= 2)
    233         low = high;
    234     while (low < high - 1) {
    235         const int mid = (low + high) / 2;
    236 
    237         if (valid_offset(fd, mid))
    238             low = mid;
    239         else
    240             high = mid;
    241     }
    242     return (low + 1);
    243 }
    244 
    245 /* return size in pages, to avoid integer overflow */
    246 static inline long get_size(const char *file)
    247 {
    248     int fd;
    249     long size;
    250 
    251     fd = bb_xopen3(file, O_RDONLY, 0);
    252     if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
    253         size /= pagesize / 512;
    254     } else {
    255         size = find_size(fd) / pagesize;
    256     }
    257     close(fd);
    258     return size;
    259 }
    260 
     11int mkswap_main(int argc, char **argv);
    26112int mkswap_main(int argc, char **argv)
    26213{
    263     char *tmp;
    264     struct stat statbuf;
    265     int sz;
    266     int maxpages;
    267     int goodpages;
    268 #ifdef __sparc__
    269     int force = 0;
    270 #endif
     14    int fd, pagesize;
     15    off_t len;
     16    unsigned int hdr[129];
    27117
    272     init_signature_page();      /* get pagesize */
     18    // No options supported.
    27319
    274     bb_opt_complementally = "?"; /* call bb_show_usage internally */
    275     sz = bb_getopt_ulflags(argc, argv, "+cfv:", &tmp);
    276     if (sz & 1)
    277         check = 1;
    278 #ifdef __sparc__
    279     if (sz & 2)
    280         force = 1;
    281 #endif
    282 #if ENABLE_FEATURE_MKSWAP_V0
    283     if (sz & 4) {
    284         version = bb_xgetlarg(tmp, 10, 0, 1);
    285     } else {
    286         if (get_linux_version_code() < KERNEL_VERSION(2, 1, 117))
    287             version = 0;
    288         else
    289             version = 1;
    290     }
    291 #endif
     20    if (argc != 2) bb_show_usage();
    29221
    293     argv += optind;
    294     argc -= optind;
     22    // Figure out how big the device is and announce our intentions.
    29523
    296     goodpages = pagesize / 1024; /* cache division */
    297     while (argc--) {
    298         if (device_name) {
    299             PAGES = bb_xgetlarg(argv[0], 0, 10, sz * goodpages) / goodpages;
    300             argc = 0; /* ignore any surplus args.. */
    301         } else {
    302             device_name = argv[0];
    303             sz = get_size(device_name);
    304             argv++;
    305         }
    306     }
     24    fd = xopen(argv[1], O_RDWR);
     25    len = fdlength(fd);
     26    pagesize = getpagesize();
     27    printf("Setting up swapspace version 1, size = %"OFF_FMT"d bytes\n",
     28            len - pagesize);
    30729
    308     if (!device_name) {
    309         bb_error_msg_and_die("error: Nowhere to set up swap on?");
    310     }
    311     if (!PAGES) {
    312         PAGES = sz;
    313     }
     30    // Make a header.
    31431
    315 #if 0
    316     maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES);
    317 #else
    318     if (!version)
    319         maxpages = V0_MAX_PAGES;
    320     else if (get_linux_version_code() >= KERNEL_VERSION(2,2,1))
    321         maxpages = V1_MAX_PAGES;
    322     else {
    323         maxpages = V1_OLD_MAX_PAGES;
    324         if (maxpages > V1_MAX_PAGES)
    325             maxpages = V1_MAX_PAGES;
    326     }
    327 #endif
    328     if (PAGES > maxpages) {
    329         PAGES = maxpages;
    330         bb_error_msg("warning: truncating swap area to %ldkB",
    331                 PAGES * goodpages);
    332     }
     32    memset(hdr, 0, sizeof(hdr));
     33    hdr[0] = 1;
     34    hdr[1] = (len / pagesize) - 1;
    33335
    334     DEV = bb_xopen3(device_name, O_RDWR, 0);
    335     if (fstat(DEV, &statbuf) < 0)
    336         bb_perror_msg_and_die("%s", device_name);
    337     if (!S_ISBLK(statbuf.st_mode))
    338         check = 0;
    339     else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
    340         bb_error_msg_and_die("Will not try to make swapdevice on '%s'", device_name);
     36    // Write the header.  Sync to disk because some kernel versions check
     37    // signature on disk (not in cache) during swapon.
    34138
    342 #ifdef __sparc__
    343     if (!force && version == 0) {
    344         /* Don't overwrite partition table unless forced */
    345         unsigned char *buffer = (unsigned char *) signature_page;
    346         unsigned short *q, sum;
     39    xlseek(fd, 1024, SEEK_SET);
     40    xwrite(fd, hdr, sizeof(hdr));
     41    xlseek(fd, pagesize-10, SEEK_SET);
     42    xwrite(fd, "SWAPSPACE2", 10);
     43    fsync(fd);
    34744
    348         if (read(DEV, buffer, 512) != 512)
    349             bb_error_msg_and_die("fatal: first page unreadable");
    350         if (buffer[508] == 0xDA && buffer[509] == 0xBE) {
    351             q = (unsigned short *) (buffer + 510);
    352             for (sum = 0; q >= (unsigned short *) buffer;)
    353                 sum ^= *q--;
    354             if (!sum) {
    355                 bb_error_msg("Device '%s' contains a valid Sun disklabel.\n"
    356 "This probably means creating v0 swap would destroy your partition table\n"
    357 "No swap created. If you really want to create swap v0 on that device, use\n"
    358 "the -f option to force it.", device_name);
    359                 return EXIT_FAILURE;
    360             }
    361         }
    362     }
    363 #endif
     45    if (ENABLE_FEATURE_CLEAN_UP) close(fd);
    36446
    365     if (version == 0 || check)
    366         check_blocks();
    367     if (version == 0 && !bit_test_and_clear(signature_page, 0))
    368         bb_error_msg_and_die("fatal: first page unreadable");
    369     if (version == 1) {
    370         p->swap_version = version;
    371         p->last_page = PAGES - 1;
    372         p->nr_badpages = badpages;
    373     }
    374 
    375     goodpages = PAGES - badpages - 1;
    376     if (goodpages <= 0)
    377         bb_error_msg_and_die("Unable to set up swap-space: unreadable");
    378     printf("Setting up swapspace version %d, size = %ld bytes\n",
    379            version, (long) (goodpages * pagesize));
    380     write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2");
    381 
    382     sz = ((version == 0) ? 0 : 1024); /* offset */
    383     if (lseek(DEV, sz, SEEK_SET) != sz)
    384         bb_error_msg_and_die("unable to rewind swap-device");
    385     goodpages = pagesize - sz; /* cache substraction */
    386     if (write(DEV, (char *) signature_page + sz, goodpages)
    387         != goodpages)
    388         bb_error_msg_and_die("unable to write signature page");
    389 
    390     /*
    391      * A subsequent swapon() will fail if the signature
    392      * is not actually on disk. (This is a kernel bug.)
    393      */
    394     if (fsync(DEV))
    395         bb_error_msg_and_die("fsync failed");
    396     if (ENABLE_FEATURE_CLEAN_UP) {
    397         close(DEV);
    398         free(signature_page);
    399     }
    400     return EXIT_SUCCESS;
     47    return 0;
    40148}
Note: See TracChangeset for help on using the changeset viewer.