home *** CD-ROM | disk | FTP | other *** search
/ Chip 1995 March / CHIP3.mdf / slackwar / a / util / util-lin.2 / util-lin / util-linux-2.2 / disk-utils / mkswap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-22  |  4.5 KB  |  213 lines

  1. /*
  2.  * mkswap.c - set up a linux swap device
  3.  *
  4.  * (C) 1991 Linus Torvalds. This file may be redistributed as per
  5.  * the Linux copyright.
  6.  */
  7.  
  8. /*
  9.  * 20.12.91  -    time began. Got VM working yesterday by doing this by hand.
  10.  *
  11.  * Usuage: mkswap [-c] device [size-in-blocks]
  12.  *
  13.  *    -c for readablility checking (use it unless you are SURE!)
  14.  *
  15.  * The device may be a block device or a image of one, but this isn't
  16.  * enforced (but it's not much fun on a character device :-).
  17.  *
  18.  * Patches from jaggy@purplet.demon.co.uk (Mike Jagdis) to make the
  19.  * size-in-blocks parameter optional added Wed Feb  8 10:33:43 1995.
  20.  */
  21.  
  22. #include <stdio.h>
  23. #include <unistd.h>
  24. #include <string.h>
  25. #include <fcntl.h>
  26. #include <stdlib.h>
  27. #include <sys/stat.h>
  28.  
  29. #include <linux/mm.h>
  30.  
  31. #ifndef __GNUC__
  32. #error "needs gcc for the bitop-__asm__'s"
  33. #endif
  34.  
  35. #ifndef __linux__
  36. #define volatile
  37. #endif
  38.  
  39. #define TEST_BUFFER_PAGES 8
  40.  
  41. static char * program_name = "mkswap";
  42. static char * device_name = NULL;
  43. static int DEV = -1;
  44. static long PAGES = 0;
  45. static int check = 0;
  46. static int badpages = 0;
  47.  
  48. static char signature_page[PAGE_SIZE];
  49.  
  50. #define bitop(name,op) \
  51. static inline int name(char * addr,unsigned int nr) \
  52. { \
  53. int __res; \
  54. __asm__ __volatile__("bt" op " %1,%2; adcl $0,%0" \
  55. :"=g" (__res) \
  56. :"r" (nr),"m" (*(addr)),"0" (0)); \
  57. return __res; \
  58. }
  59.  
  60. bitop(bit,"")
  61. bitop(setbit,"s")
  62. bitop(clrbit,"r")
  63.  
  64. /*
  65.  * Volatile to let gcc know that this doesn't return. When trying
  66.  * to compile this under minix, volatile gives a warning, as
  67.  * exit() isn't defined as volatile under minix.
  68.  */
  69. volatile void fatal_error(const char * fmt_string)
  70. {
  71.     fprintf(stderr,fmt_string,program_name,device_name);
  72.     exit(1);
  73. }
  74.  
  75. #define usage() fatal_error("Usage: %s [-c] /dev/name [blocks]\n")
  76. #define die(str) fatal_error("%s: " str "\n")
  77.  
  78. void check_blocks(void)
  79. {
  80.     unsigned int current_page;
  81.     int do_seek = 1;
  82.     static char buffer[PAGE_SIZE];
  83.  
  84.     current_page = 0;
  85.     while (current_page < PAGES) {
  86.         if (!check) {
  87.             setbit(signature_page,current_page++);
  88.             continue;
  89.         }
  90.         if (do_seek && lseek(DEV,current_page*PAGE_SIZE,SEEK_SET) !=
  91.         current_page*PAGE_SIZE)
  92.             die("seek failed in check_blocks");
  93.         if (do_seek = (PAGE_SIZE != read(DEV, buffer, PAGE_SIZE))) {
  94.             clrbit(signature_page,current_page++);
  95.             badpages++;
  96.             continue;
  97.         }
  98.         setbit(signature_page,current_page++);
  99.     }
  100.     if (badpages)
  101.         printf("%d bad page%s\n",badpages,(badpages>1)?"s":"");
  102. }
  103.  
  104. static long valid_offset (int fd, int offset)
  105. {
  106.     char ch;
  107.  
  108.     if (lseek (fd, offset, 0) < 0)
  109.         return 0;
  110.     if (read (fd, &ch, 1) < 1)
  111.         return 0;
  112.     return 1;
  113. }
  114.  
  115. static int count_blocks (int fd)
  116. {
  117.     int high, low;
  118.  
  119.     low = 0;
  120.     for (high = 1; valid_offset (fd, high); high *= 2)
  121.         low = high;
  122.     while (low < high - 1)
  123.     {
  124.         const int mid = (low + high) / 2;
  125.  
  126.         if (valid_offset (fd, mid))
  127.             low = mid;
  128.         else
  129.             high = mid;
  130.     }
  131.     valid_offset (fd, 0);
  132.     return (low + 1);
  133. }
  134.  
  135. static int get_size(const char  *file)
  136. {
  137.     int    fd;
  138.     int    size;
  139.  
  140.     fd = open(file, O_RDWR);
  141.     if (fd < 0) {
  142.         perror(file);
  143.         exit(1);
  144.     }
  145.     if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
  146.         close(fd);
  147.         return (size * 512);
  148.     }
  149.         
  150.     size = count_blocks(fd);
  151.     close(fd);
  152.     return size;
  153. }
  154.  
  155. int main(int argc, char ** argv)
  156. {
  157.     char * tmp;
  158.     struct stat statbuf;
  159.     int goodpages;
  160.  
  161.     memset(signature_page,0,PAGE_SIZE);
  162.     if (argc && *argv)
  163.         program_name = *argv;
  164.     while (argc-- > 1) {
  165.         argv++;
  166.         if (argv[0][0] != '-')
  167.             if (device_name) {
  168.                 PAGES = strtol(argv[0],&tmp,0)>>2;
  169.                 if (*tmp)
  170.                     usage();
  171.             } else
  172.                 device_name = argv[0];
  173.         else while (*++argv[0])
  174.             switch (argv[0][0]) {
  175.                 case 'c': check=1; break;
  176.                 default: usage();
  177.             }
  178.     }
  179.     if (device_name && !PAGES) {
  180.         PAGES = get_size(device_name) / PAGE_SIZE;
  181.     }
  182.     if (!device_name || PAGES<10)
  183.         usage();
  184.     if (PAGES > 32688) /* 130752 blocks */
  185.             PAGES=32688;
  186. #if 0
  187.     if (PAGES > 32768)
  188.         PAGES=32768;
  189. #endif
  190.     DEV = open(device_name,O_RDWR);
  191.     if (DEV < 0 || fstat(DEV, &statbuf) < 0) {
  192.         perror(device_name);
  193.         exit(1);
  194.     }
  195.     if (!S_ISBLK(statbuf.st_mode))
  196.         check=0;
  197.     else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
  198.         die("Will not try to make swapdevice on '%s'");
  199.     check_blocks();
  200.     if (!clrbit(signature_page,0))
  201.         die("fatal: first page unreadable");
  202.     goodpages = PAGES - badpages - 1;
  203.     if (!goodpages)
  204.         die("Unable to set up swap-space: unreadable");
  205.     printf("Setting up swapspace, size = %d bytes\n",goodpages*PAGE_SIZE);
  206.     strncpy(signature_page+PAGE_SIZE-10,"SWAP-SPACE",10);
  207.     if (lseek(DEV, 0, SEEK_SET))
  208.         die("unable to rewind swap-device");
  209.     if (PAGE_SIZE != write(DEV, signature_page, PAGE_SIZE))
  210.         die("unable to write signature page");
  211.     return 0;
  212. }
  213.