home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 13 / CDA13.ISO / MISC / SRC / INSTALL / MKSWAP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-23  |  5.7 KB  |  275 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.  * (C) 1996 Red Hat Software - Modified by Erik Troan for Red Hat Software 
  8.  *     still GPLed, of course
  9.  */
  10.  
  11. /*
  12.  * 20.12.91  -    time began. Got VM working yesterday by doing this by hand.
  13.  *
  14.  * Usuage: mkswap [-c] device [size-in-blocks]
  15.  *
  16.  *    -c for readablility checking (use it unless you are SURE!)
  17.  *
  18.  * The device may be a block device or a 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.  
  25. #include <errno.h>
  26. #include <fcntl.h>
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <sys/ioctl.h>
  31. #include <sys/stat.h>
  32. #include <unistd.h>
  33.  
  34. #include <linux/mm.h>
  35.  
  36. #include "devices.h"
  37. #include "install.h"
  38. #include "log.h"
  39. #include "mkswap.h"
  40. #include "newt.h"
  41. #include "windows.h"
  42.  
  43. #ifndef __linux__
  44. # define volatile
  45. #endif
  46.  
  47. #define TEST_BUFFER_PAGES 8
  48.  
  49. static int DEV = -1;
  50. static long PAGES = 0;
  51. static int check = 0;
  52. static int badpages = 0;
  53.  
  54. static long bit_test_and_set (unsigned int *addr, unsigned int nr)
  55. {
  56.     unsigned int r, m;
  57.  
  58.     addr += nr / (8 * sizeof(int));
  59.     r = *addr;
  60.     m = 1 << (nr & (8 * sizeof(int) - 1));
  61.     *addr = r | m;
  62.     return (r & m) != 0;
  63. }
  64.  
  65. static int bit_test_and_clear (unsigned int *addr, unsigned int nr)
  66. {
  67.     unsigned int r, m;
  68.  
  69.     addr += nr / (8 * sizeof(int));
  70.     r = *addr;
  71.     m = 1 << (nr & (8 * sizeof(int) - 1));
  72.     *addr = r & ~m;
  73.     return (r & m) != 0;
  74. }
  75.  
  76. int check_blocks(int * signature_page)
  77. {
  78.     unsigned int current_page;
  79.     int do_seek = 1;
  80.     static char buffer[PAGE_SIZE];
  81.  
  82.     current_page = 0;
  83.     while (current_page < PAGES) {
  84.         if (!check) {
  85.             bit_test_and_set(signature_page,current_page++);
  86.             continue;
  87.         }
  88.         if (do_seek && lseek(DEV,current_page*PAGE_SIZE,SEEK_SET) !=
  89.         current_page*PAGE_SIZE) {
  90.             logMessage("mkswap: seek failed in check_blocks");
  91.             return INST_ERROR;
  92.         }
  93.         if ((do_seek = (PAGE_SIZE != read(DEV, buffer, PAGE_SIZE)))) {
  94.             bit_test_and_clear(signature_page,current_page++);
  95.             badpages++;
  96.             continue;
  97.         }
  98.         bit_test_and_set(signature_page,current_page++);
  99.     }
  100.     if (badpages)
  101.         logMessage("\t%d bad page%s\n",badpages,(badpages>1)?"s":"");
  102.  
  103.     return 0;
  104. }
  105.  
  106. static long valid_offset (int fd, int offset)
  107. {
  108.     char ch;
  109.  
  110.     if (lseek (fd, offset, 0) < 0)
  111.         return 0;
  112.     if (read (fd, &ch, 1) < 1)
  113.         return 0;
  114.     return 1;
  115. }
  116.  
  117. static int count_blocks (int fd)
  118. {
  119.     int high, low;
  120.  
  121.     low = 0;
  122.     for (high = 1; valid_offset (fd, high); high *= 2)
  123.         low = high;
  124.     while (low < high - 1)
  125.     {
  126.         const int mid = (low + high) / 2;
  127.  
  128.         if (valid_offset (fd, mid))
  129.             low = mid;
  130.         else
  131.             high = mid;
  132.     }
  133.     valid_offset (fd, 0);
  134.     return (low + 1);
  135. }
  136.  
  137. static int get_size(const char  *file, long int * sizeptr)
  138. {
  139.     int    fd;
  140.     int    size;
  141.  
  142.     fd = open(file, O_RDWR);
  143.     if (fd < 0) {
  144.         logMessage("mkswap: failed to get size of device %s", file);
  145.         return INST_ERROR;
  146.     }
  147.     if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
  148.         close(fd);
  149.         *sizeptr = size * 512;
  150.         return 0;
  151.     }
  152.         
  153.     *sizeptr = count_blocks(fd);
  154.     close(fd);
  155.  
  156.     return 0;;
  157. }
  158.  
  159. int enableswap(char * device_name, int size, int checkBlocks) {
  160.     struct stat statbuf;
  161.     int goodpages;
  162.     int signature_page[PAGE_SIZE/sizeof(int)];
  163.     char devicefile[100];
  164.  
  165.     check = checkBlocks;
  166.  
  167.     if (testing) {
  168.         messageWindow("Testing", "I would make and enable swap on %s",
  169.               device_name);
  170.         return 0;
  171.     }
  172.  
  173.     memset(signature_page,0,PAGE_SIZE);
  174.  
  175.     sprintf(devicefile, "/tmp/%s", device_name);
  176.     if (devMakeInode(device_name, devicefile)) {
  177.         return INST_ERROR;
  178.     }
  179.  
  180.     if (size)
  181.         PAGES = size;
  182.     else {
  183.         if (get_size(devicefile, &PAGES)) {
  184.             unlink(devicefile);
  185.             return INST_ERROR;
  186.         }
  187.  
  188.         PAGES = PAGES / PAGE_SIZE;
  189.     }
  190.  
  191.     if (PAGES<10) {
  192.         logMessage("mkswap: error: swap area needs to be at least "
  193.                 "%ldkB", 10 * PAGE_SIZE / 1024);
  194.         unlink(devicefile);
  195.         return INST_ERROR;
  196.     }
  197.  
  198.     if (PAGES > 8 * (PAGE_SIZE - 10)) {
  199.             PAGES = 8 * (PAGE_SIZE - 10);
  200.         logMessage("mkswap: warning: truncating %s swap to %ldkB",
  201.             device_name, PAGES * PAGE_SIZE / 1024);
  202.     }
  203.  
  204.     DEV = open(devicefile,O_RDWR);
  205.     if (DEV < 0 || fstat(DEV, &statbuf) < 0) {
  206.         logMessage("mkswap: failed to open device: %s\n", device_name);
  207.         unlink(devicefile);
  208.         return INST_ERROR;
  209.     }
  210.     if (!S_ISBLK(statbuf.st_mode))
  211.         check=0;
  212.     else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) {
  213.         logMessage("mkswap: will not try to make swapdevice on '%s'");
  214.         close(DEV);
  215.         unlink(devicefile);
  216.         return INST_ERROR;
  217.     }
  218.  
  219.     winStatus(32, 3, "Swap", "Initializing swap space...");
  220.     if (check_blocks(signature_page)) {
  221.         close(DEV);
  222.         unlink(devicefile);
  223.         newtPopWindow();
  224.         return INST_ERROR;
  225.     }
  226.  
  227.     if (!bit_test_and_clear(signature_page,0)) {
  228.         logMessage("mkswap: first page unreadable");
  229.         close(DEV);
  230.         unlink(devicefile);
  231.         newtPopWindow();
  232.         return INST_ERROR;
  233.     }
  234.  
  235.     goodpages = PAGES - badpages - 1;
  236.     if (goodpages <= 0) {
  237.         logMessage("mkswap: unable to set up swap-space: unreadable");
  238.         close(DEV);
  239.         unlink(devicefile);
  240.         newtPopWindow();
  241.         return INST_ERROR;
  242.     }
  243.  
  244.     logMessage("setting up swapspace, device = %s, size = %d bytes",
  245.         device_name, goodpages*PAGE_SIZE);
  246.     strncpy((char*)signature_page+PAGE_SIZE-10,"SWAP-SPACE",10);
  247.     if (lseek(DEV, 0, SEEK_SET)) {
  248.         logMessage("mkswap: unable to rewind swap-device");
  249.         close(DEV);
  250.         unlink(devicefile);
  251.         newtPopWindow();
  252.         return INST_ERROR;
  253.     }
  254.  
  255.     if (PAGE_SIZE != write(DEV, signature_page, PAGE_SIZE)) {
  256.         logMessage("mkswap: unable to write signature page");
  257.         close(DEV);
  258.         unlink(devicefile);
  259.         newtPopWindow();
  260.         return INST_ERROR;
  261.     }
  262.  
  263.     close(DEV);
  264.  
  265.     if (swapon(devicefile)) {
  266.         logMessage("mkswap: swapon() failed: %s\n", strerror(errno));
  267.     }
  268.  
  269.     unlink(devicefile);
  270.  
  271.     newtPopWindow();
  272.  
  273.     return 0;
  274. }
  275.