home *** CD-ROM | disk | FTP | other *** search
- /*
- * mkswap.c - set up a linux swap device
- *
- * (C) 1991 Linus Torvalds. This file may be redistributed as per
- * the Linux copyright.
- *
- * (C) 1996 Red Hat Software - Modified by Erik Troan for Red Hat Software
- * still GPLed, of course
- */
-
- /*
- * 20.12.91 - time began. Got VM working yesterday by doing this by hand.
- *
- * Usuage: mkswap [-c] device [size-in-blocks]
- *
- * -c for readablility checking (use it unless you are SURE!)
- *
- * The device may be a block device or a image of one, but this isn't
- * enforced (but it's not much fun on a character device :-).
- *
- * Patches from jaggy@purplet.demon.co.uk (Mike Jagdis) to make the
- * size-in-blocks parameter optional added Wed Feb 8 10:33:43 1995.
- */
-
- #include <errno.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/ioctl.h>
- #include <sys/stat.h>
- #include <sys/swap.h>
- #include <unistd.h>
-
- #include <asm/page.h>
-
- #define BLKGETSIZE 0x1260
-
- #include "devices.h"
- #include "install.h"
- #include "intl.h"
- #include "log.h"
- #include "mkswap.h"
- #include "newt.h"
- #include "windows.h"
-
- #ifndef __linux__
- # define volatile
- #endif
-
- #define TEST_BUFFER_PAGES 8
-
- static int DEV = -1;
- static long PAGES = 0;
- static int check = 0;
- static int badpages = 0;
-
- int canEnableSwap = 1;
-
- static long bit_test_and_set (unsigned int *addr, unsigned int nr)
- {
- unsigned int r, m;
-
- addr += nr / (8 * sizeof(int));
- r = *addr;
- m = 1 << (nr & (8 * sizeof(int) - 1));
- *addr = r | m;
- return (r & m) != 0;
- }
-
- static int bit_test_and_clear (unsigned int *addr, unsigned int nr)
- {
- unsigned int r, m;
-
- addr += nr / (8 * sizeof(int));
- r = *addr;
- m = 1 << (nr & (8 * sizeof(int) - 1));
- *addr = r & ~m;
- return (r & m) != 0;
- }
-
- static int check_blocks(int * signature_page, char * file)
- {
- unsigned int current_page;
- int do_seek = 1;
- static char buffer[PAGE_SIZE];
- newtComponent form = NULL, scale = NULL;
- newtGrid grid;
-
- if (check) {
- form = newtForm(NULL, NULL, 0);
-
- sprintf(buffer, _("Formatting swap space on device %s..."),
- file);
- scale = newtScale(-1, -1, 58, PAGES);
-
- grid = newtCreateGrid(1, 2);
- newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT,
- newtLabel(-1, -1, buffer),
- 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0);
- newtGridSetField(grid, 0, 1, NEWT_GRID_COMPONENT, scale,
- 0, 1, 0, 0, 0, 0);
- newtGridAddComponentsToForm(grid, form, 1);
-
- newtGridWrappedWindow(grid, _("Formatting"));
-
- newtDrawForm(form);
- newtRefresh();
- }
-
- current_page = 0;
- while (current_page < PAGES) {
- if (!check) {
- bit_test_and_set(signature_page,current_page++);
- continue;
- }
-
- newtScaleSet(scale, current_page);
- newtRefresh();
-
- if (do_seek && lseek(DEV,current_page*PAGE_SIZE,SEEK_SET) !=
- current_page*PAGE_SIZE) {
- logMessage("mkswap: seek failed in check_blocks");
- return INST_ERROR;
- }
- if ((do_seek = (PAGE_SIZE != read(DEV, buffer, PAGE_SIZE)))) {
- bit_test_and_clear(signature_page,current_page++);
- badpages++;
- continue;
- }
- bit_test_and_set(signature_page,current_page++);
- }
- if (badpages)
- logMessage("\t%d bad page%s\n",badpages,(badpages>1)?"s":"");
-
- if (check) {
- newtPopWindow();
- newtFormDestroy(form);
- }
-
- return 0;
- }
-
- static long valid_offset (int fd, int offset)
- {
- char ch;
-
- if (lseek (fd, offset, 0) < 0)
- return 0;
- if (read (fd, &ch, 1) < 1)
- return 0;
- return 1;
- }
-
- static int count_blocks (int fd)
- {
- int high, low;
-
- low = 0;
- for (high = 1; valid_offset (fd, high); high *= 2)
- low = high;
- while (low < high - 1)
- {
- const int mid = (low + high) / 2;
-
- if (valid_offset (fd, mid))
- low = mid;
- else
- high = mid;
- }
- valid_offset (fd, 0);
- return (low + 1);
- }
-
- static int get_size(const char *file, long int * sizeptr)
- {
- int fd;
- int size;
-
- fd = open(file, O_RDWR);
- if (fd < 0) {
- logMessage("mkswap: failed to get size of device %s", file);
- return INST_ERROR;
- }
- if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
- close(fd);
- *sizeptr = size * 512;
- return 0;
- }
-
- *sizeptr = count_blocks(fd);
- close(fd);
-
- return 0;;
- }
-
- int enableswap(char * device_name, int size, int checkBlocks) {
- struct stat statbuf;
- int goodpages;
- int signature_page[PAGE_SIZE/sizeof(int)];
- char devicefile[100];
-
- check = checkBlocks;
-
- if (testing) {
- return 0;
- }
-
- memset(signature_page,0,PAGE_SIZE);
-
- if (*device_name == '/') {
- strcpy(devicefile, device_name);
- } else {
- sprintf(devicefile, "/tmp/%s", device_name);
- if (devMakeInode(device_name, devicefile)) {
- return INST_ERROR;
- }
- }
-
- if (size)
- PAGES = size;
- else {
- if (get_size(devicefile, &PAGES)) {
- unlink(devicefile);
- return INST_ERROR;
- }
-
- PAGES = PAGES / PAGE_SIZE;
- }
-
- if (PAGES<10) {
- logMessage("mkswap: error: swap area needs to be at least "
- "%ldkB", 10 * PAGE_SIZE / 1024);
- unlink(devicefile);
- return INST_ERROR;
- }
-
- if (PAGES > 8 * (PAGE_SIZE - 10)) {
- PAGES = 8 * (PAGE_SIZE - 10);
- logMessage("mkswap: warning: truncating %s swap to %ldkB",
- device_name, PAGES * PAGE_SIZE / 1024);
- }
-
- DEV = open(devicefile,O_RDWR);
- if (DEV < 0 || fstat(DEV, &statbuf) < 0) {
- logMessage("mkswap: failed to open device: %s\n", device_name);
- unlink(devicefile);
- return INST_ERROR;
- }
- if (!S_ISBLK(statbuf.st_mode))
- check=0;
- else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) {
- logMessage("mkswap: will not try to make swapdevice on '%s'");
- close(DEV);
- unlink(devicefile);
- return INST_ERROR;
- }
-
- if (check_blocks(signature_page, device_name)) {
- close(DEV);
- unlink(devicefile);
- newtPopWindow();
- return INST_ERROR;
- }
-
- if (!bit_test_and_clear(signature_page,0)) {
- logMessage("mkswap: first page unreadable");
- close(DEV);
- unlink(devicefile);
- newtPopWindow();
- return INST_ERROR;
- }
-
- goodpages = PAGES - badpages - 1;
- if (goodpages <= 0) {
- logMessage("mkswap: unable to set up swap-space: unreadable");
- close(DEV);
- unlink(devicefile);
- newtPopWindow();
- return INST_ERROR;
- }
-
- logMessage("setting up swapspace, device = %s, size = %d bytes",
- device_name, goodpages*PAGE_SIZE);
- strncpy((char*)signature_page+PAGE_SIZE-10,"SWAP-SPACE",10);
- if (lseek(DEV, 0, SEEK_SET)) {
- logMessage("mkswap: unable to rewind swap-device");
- close(DEV);
- unlink(devicefile);
- newtPopWindow();
- return INST_ERROR;
- }
-
- if (PAGE_SIZE != write(DEV, signature_page, PAGE_SIZE)) {
- logMessage("mkswap: unable to write signature page");
- close(DEV);
- unlink(devicefile);
- newtPopWindow();
- return INST_ERROR;
- }
-
- close(DEV);
-
- if (swapon(devicefile, 0)) {
- logMessage("mkswap: swapon() failed: %s\n", strerror(errno));
- }
-
- if (*device_name != '/')
- unlink(devicefile);
-
- return 0;
- }
-
- int activeSwapSpace(struct partitionTable * table, struct fstab * finalFstab,
- int forceFormat) {
- newtComponent form, checkList, okay, cancel, sb, text, answer, label;
- newtComponent check, checkbox, blank;
- newtGrid grid, subgrid, buttons, checkgrid;
- char * states;
- char buf[80];
- int i, j, rc, row;
- struct fstabEntry entry;
- struct fstabEntry ** entries;
- struct fstab fstab;
- static int chkBadBlocks = 0;
- char doCheck = ' ';
-
- if (!canEnableSwap) return INST_NOP;
-
- fstab = copyFstab(finalFstab);
-
- form = newtForm(NULL, NULL, 0);
-
- for (i = j = 0; i < table->count; i++)
- if (table->parts[i].type == PART_SWAP)
- j++;
-
- if (!j) {
- rc = newtWinChoice(_("No Swap Space"), _("Repartition"), _("Continue"),
- _("You don't have any swap space defined. Would "
- "you like to continue, or repartition your disk?"));
- if (rc != 2)
- return INST_CANCEL;
-
- return 0;
- }
-
- if (!forceFormat) {
- if (j > 3) {
- sb = newtVerticalScrollbar(47, 7, 3, 9, 10);
- } else
- sb = NULL;
-
- checkList = newtForm(sb, NULL, 0);
- if (sb) newtFormSetHeight(checkList, j > 3);
-
- text = newtTextboxReflowed(-1, -1, _("What partitions would you like "
- "to use for swap space? This will destroy any "
- "information already on the partition."),
- 52, 0, 15, 0);
-
- label = newtLabel(-1, -1,
- " Device Size (k)");
-
- states = alloca(sizeof(char) * table->count);
- entries = alloca(sizeof(*entries) * table->count);
-
- for (i = 0, row = 0; i < table->count; i++) {
- if (table->parts[i].type != PART_SWAP) continue;
-
- for (j = 0; j < fstab.numEntries; j++)
- if (!strcmp(table->parts[i].device, fstab.entries[j].device))
- break;
-
- if ((j < fstab.numEntries && fstab.entries[j].mntpoint) ||
- !testing)
- states[i] = '*';
- else
- states[i] = ' ';
-
- if (j < fstab.numEntries)
- entries[i] = fstab.entries + j;
- else
- entries[i] = NULL;
-
- sprintf(buf, "/dev/%-5s %9d", table->parts[i].device,
- table->parts[i].size);
- check = newtCheckbox(-1, row++, buf, states[i], NULL,
- &states[i]);
- newtFormAddComponent(checkList, check);
- }
-
- if (row > 3) {
- blank = newtForm(NULL, NULL, 0);
- newtFormSetWidth(blank, 2);
- newtFormSetHeight(blank, 3);
- newtFormSetBackground(blank, NEWT_COLORSET_CHECKBOX);
- checkgrid = newtGridHCloseStacked(
- NEWT_GRID_COMPONENT, checkList,
- NEWT_GRID_COMPONENT, blank,
- NEWT_GRID_COMPONENT, sb, NULL);
- } else {
- checkgrid = newtGridHCloseStacked(NEWT_GRID_COMPONENT, checkList,
- NULL);
- }
-
- checkbox = newtCheckbox(-1, -1, _("Check for bad blocks during format"),
- chkBadBlocks ? '*' : ' ', NULL, &doCheck);
-
- buttons = newtButtonBar(_("Ok"), &okay, _("Back"), &cancel, NULL);
- subgrid = newtCreateGrid(1, 3);
- newtGridSetField(subgrid, 0, 0, NEWT_GRID_COMPONENT, label,
- 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0);
- newtGridSetField(subgrid, 0, 1, NEWT_GRID_SUBGRID, checkgrid,
- 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0);
- newtGridSetField(subgrid, 0, 2, NEWT_GRID_COMPONENT, checkbox,
- 0, 1, 0, 0, NEWT_ANCHOR_LEFT, 0);
- grid = newtGridBasicWindow(text, subgrid, buttons);
- newtGridAddComponentsToForm(grid, form, 1);
- newtGridWrappedWindow(grid, _("Active Swap Space"));
- newtGridFree(grid, 1);
-
- answer = newtRunForm(form);
-
- newtFormDestroy(form);
- newtPopWindow();
-
- chkBadBlocks = (doCheck != ' ');
-
- if (answer == cancel) {
- freeFstab(fstab);
- return INST_CANCEL;
- }
- }
-
- for (i = 0; i < table->count; i++) {
- if (table->parts[i].type != PART_SWAP) continue;
-
- if (forceFormat || states[i] != ' ') {
- if (!forceFormat && entries[i])
- entries[i]->mntpoint = strdup("swap");
- else {
- initFstabEntry(&entry);
- entry.device = strdup(table->parts[i].device);
- entry.size = table->parts[i].size;
- entry.type = table->parts[i].type;
- entry.tagName = table->parts[i].tagName;
- entry.mntpoint = strdup("swap");
-
- addFstabEntry(&fstab, entry);
- }
- } else if (entries[i]) {
- free(entries[i]->mntpoint);
- entries[i]->mntpoint = NULL;
- }
- }
-
- if (canEnableSwap) {
- for (i = 0; i < fstab.numEntries; i++) {
- if (fstab.entries[i].type == PART_SWAP &&
- fstab.entries[i].mntpoint) {
- enableswap(fstab.entries[i].device, 0, chkBadBlocks);
- canEnableSwap = 0;
- }
- }
- }
-
- freeFstab(*finalFstab);
- *finalFstab = copyFstab(&fstab);
- freeFstab(fstab);
-
- return 0;
- }
-