Home | History | Annotate | Line # | Download | only in edahdi
edahdi.c revision 1.4
      1  1.4   he /*	$NetBSD: edahdi.c,v 1.4 2004/11/12 10:18:46 he Exp $	*/
      2  1.1  leo 
      3  1.1  leo /*
      4  1.1  leo  * Copyright (c) 1996 Leo Weppelman, Waldi Ravens.
      5  1.1  leo  * All rights reserved.
      6  1.1  leo  *
      7  1.1  leo  * Redistribution and use in source and binary forms, with or without
      8  1.1  leo  * modification, are permitted provided that the following conditions
      9  1.1  leo  * are met:
     10  1.1  leo  * 1. Redistributions of source code must retain the above copyright
     11  1.1  leo  *    notice, this list of conditions and the following disclaimer.
     12  1.1  leo  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1  leo  *    notice, this list of conditions and the following disclaimer in the
     14  1.1  leo  *    documentation and/or other materials provided with the distribution.
     15  1.2  leo  * 3. All advertising materials mentioning features or use of this software
     16  1.1  leo  *    must display the following acknowledgement:
     17  1.1  leo  *      This product includes software developed by
     18  1.1  leo  *			Leo Weppelman and Waldi Ravens.
     19  1.2  leo  * 4. The name of the author may not be used to endorse or promote products
     20  1.2  leo  *    derived from this software without specific prior written permission.
     21  1.1  leo  *
     22  1.1  leo  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     23  1.1  leo  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     24  1.1  leo  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     25  1.1  leo  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     26  1.1  leo  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     27  1.1  leo  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28  1.1  leo  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29  1.1  leo  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30  1.1  leo  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     31  1.1  leo  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32  1.1  leo  */
     33  1.1  leo 
     34  1.1  leo /*
     35  1.1  leo  * This code implements a simple editor for partition id's on disks containing
     36  1.1  leo  * AHDI partition info.
     37  1.1  leo  *
     38  1.1  leo  * Credits for the code handling disklabels goes to Waldi Ravens.
     39  1.1  leo  *
     40  1.1  leo  */
     41  1.1  leo #include <sys/types.h>
     42  1.1  leo #include <sys/param.h>
     43  1.1  leo #include <sys/stat.h>
     44  1.1  leo #include <sys/disklabel.h>
     45  1.1  leo 
     46  1.1  leo #include <machine/ahdilabel.h>
     47  1.1  leo 
     48  1.1  leo #include <fcntl.h>
     49  1.1  leo #include <stdlib.h>
     50  1.1  leo #include <curses.h>
     51  1.1  leo #include <termios.h>
     52  1.1  leo #include <unistd.h>
     53  1.1  leo #include <stdio.h>
     54  1.1  leo #include <string.h>
     55  1.1  leo #include <err.h>
     56  1.1  leo #include <ctype.h>
     57  1.1  leo 
     58  1.1  leo /*
     59  1.1  leo  * Internal partition tables:
     60  1.1  leo  */
     61  1.1  leo typedef struct {
     62  1.1  leo 	char	id[4];
     63  1.1  leo 	u_int	start;
     64  1.1  leo 	u_int	end;
     65  1.1  leo 	u_int	rsec;
     66  1.1  leo 	u_int	rent;
     67  1.1  leo 	int	mod;
     68  1.1  leo } part_t;
     69  1.1  leo 
     70  1.1  leo typedef struct {
     71  1.1  leo 	int	nparts;
     72  1.1  leo 	part_t	*parts;
     73  1.1  leo } ptable_t;
     74  1.1  leo 
     75  1.1  leo /*
     76  1.1  leo  * I think we can savely assume a fixed blocksize - AHDI won't support
     77  1.1  leo  * something different...
     78  1.1  leo  */
     79  1.1  leo #define BLPM		((1024 * 1024) / DEV_BSIZE)
     80  1.1  leo 
     81  1.1  leo /*
     82  1.1  leo  * #Partition entries shown on the screen at once
     83  1.1  leo  */
     84  1.1  leo #define MAX_PSHOWN	16	/* #partitions shown on screen	*/
     85  1.1  leo 
     86  1.1  leo /*
     87  1.1  leo  * Tokens:
     88  1.1  leo  */
     89  1.1  leo #define	T_INVAL		0
     90  1.1  leo #define	T_QUIT		1
     91  1.1  leo #define	T_WRITE		2
     92  1.1  leo #define	T_NEXT		3
     93  1.1  leo #define	T_PREV		4
     94  1.1  leo #define	T_NUMBER	5
     95  1.1  leo #define	T_EOF		6
     96  1.1  leo 
     97  1.1  leo /*
     98  1.1  leo  * Terminal capability strings (Ok, 1 to start with ;-) )
     99  1.1  leo  */
    100  1.1  leo char	*Clr_screen = "";
    101  1.1  leo 
    102  1.1  leo void	ahdi_cksum __P((void *));
    103  1.1  leo u_int	ahdi_getparts __P((int, ptable_t *, u_int, u_int));
    104  1.1  leo int	bsd_label __P((int, u_int));
    105  1.1  leo int	dkcksum __P((struct disklabel *));
    106  1.1  leo int	edit_parts __P((int, ptable_t *));
    107  1.1  leo void   *disk_read __P((int, u_int, u_int));
    108  1.1  leo void	disk_write __P((int, u_int, u_int, void  *));
    109  1.1  leo char   *get_id __P((void));
    110  1.1  leo void	get_termcap __P((void));
    111  1.1  leo int	lex __P((int *));
    112  1.1  leo int	show_parts __P((ptable_t *, int));
    113  1.1  leo void	update_disk __P((ptable_t *, int, int));
    114  1.1  leo 
    115  1.1  leo int
    116  1.1  leo main(argc, argv)
    117  1.1  leo int	argc;
    118  1.1  leo char	*argv[];
    119  1.1  leo {
    120  1.1  leo 	int		fd;
    121  1.1  leo 	ptable_t	ptable;
    122  1.1  leo 	int		rv;
    123  1.1  leo 	struct stat	st;
    124  1.1  leo 
    125  1.1  leo 	if (argc != 2) {
    126  1.1  leo 		char	*prog = strrchr(argv[0], '/');
    127  1.1  leo 
    128  1.1  leo 		if (prog == NULL)
    129  1.1  leo 			prog = argv[0];
    130  1.1  leo 		else prog++;
    131  1.1  leo 		fprintf(stderr, "Usage: %s <raw_disk_device>", prog);
    132  1.1  leo 		exit(1);
    133  1.1  leo 	}
    134  1.1  leo 	if ((fd = open(argv[1], O_RDWR)) < 0)
    135  1.1  leo 		err(1, "Cannot open '%s'.", argv[1]);
    136  1.1  leo 	if (fstat(fd, &st) < 0)
    137  1.1  leo 		err(1, "Cannot stat '%s'.", argv[1]);
    138  1.1  leo 	if (!S_ISCHR(st.st_mode))
    139  1.1  leo 		errx(1, "'%s' must be a character special device.", argv[1]);
    140  1.1  leo 
    141  1.1  leo 	if ((rv = bsd_label(fd, LABELSECTOR)) < 0)
    142  1.1  leo 		errx(1, "I/O error");
    143  1.1  leo 	if (rv == 0) {
    144  1.1  leo 		warnx("Disk has no ahdi partitions");
    145  1.1  leo 		return (2);
    146  1.1  leo 	}
    147  1.1  leo 
    148  1.1  leo 	get_termcap();
    149  1.1  leo 
    150  1.1  leo 	ptable.nparts = 0;
    151  1.1  leo 	ptable.parts  = NULL;
    152  1.1  leo 
    153  1.1  leo 	if ((ahdi_getparts(fd, &ptable, AHDI_BBLOCK, AHDI_BBLOCK) != 0)
    154  1.1  leo 		|| (ptable.nparts == 0))
    155  1.1  leo 		exit (1);
    156  1.1  leo 
    157  1.1  leo 	edit_parts(fd, &ptable);
    158  1.1  leo 	return (0);
    159  1.1  leo }
    160  1.1  leo 
    161  1.1  leo int
    162  1.1  leo edit_parts(fd, ptable)
    163  1.1  leo 	int		fd;
    164  1.1  leo 	ptable_t	*ptable;
    165  1.1  leo {
    166  1.1  leo 	int	scr_base = 0;
    167  1.1  leo 	int	value;
    168  1.1  leo 	char	*error, *new_id;
    169  1.1  leo 
    170  1.1  leo 	for (;;) {
    171  1.1  leo 		error = NULL;
    172  1.3  leo 		tputs(Clr_screen, 1, putchar);
    173  1.1  leo 		show_parts(ptable, scr_base);
    174  1.1  leo 
    175  1.1  leo 		printf("\n\n");
    176  1.1  leo 		printf("q    : quit - don't update the disk\n");
    177  1.1  leo 		printf("w    : write changes to disk\n");
    178  1.1  leo 		printf(">    : next screen of partitions\n");
    179  1.1  leo 		printf("<    : previous screen of partitions\n");
    180  1.1  leo 		printf("<nr> : modify id of partition <nr>\n");
    181  1.1  leo 		printf("\n\nCommand? ");
    182  1.1  leo 		fflush(stdout);
    183  1.1  leo 
    184  1.1  leo 		switch (lex(&value)) {
    185  1.1  leo 		    case T_EOF:
    186  1.1  leo 			exit(0);
    187  1.1  leo 
    188  1.1  leo 		    case T_INVAL:
    189  1.1  leo 			error = "Invalid command";
    190  1.1  leo 			break;
    191  1.1  leo 		    case T_QUIT :
    192  1.1  leo 			for (value = 0; value < ptable->nparts; value++) {
    193  1.1  leo 				if (ptable->parts[value].mod) {
    194  1.1  leo 					printf("\nThere are unwritten changes."
    195  1.1  leo 						" Quit anyway? [n] ");
    196  1.1  leo 					value = getchar();
    197  1.1  leo 					if ((value == 'y') || (value == 'Y'))
    198  1.1  leo 							exit (0);
    199  1.1  leo 					while (value != '\n')
    200  1.1  leo 						value = getchar();
    201  1.1  leo 					break;
    202  1.1  leo 				}
    203  1.1  leo 			}
    204  1.1  leo 			if (value == ptable->nparts)
    205  1.1  leo 				exit(0);
    206  1.1  leo 			break;
    207  1.1  leo 		    case T_WRITE:
    208  1.1  leo 			error = "No changes to write";
    209  1.1  leo 			for (value = 0; value < ptable->nparts; value++) {
    210  1.1  leo 				if (ptable->parts[value].mod) {
    211  1.1  leo 					update_disk(ptable, fd, value);
    212  1.1  leo 					error = "";
    213  1.1  leo 				}
    214  1.1  leo 			}
    215  1.1  leo 			break;
    216  1.1  leo 		    case T_NEXT :
    217  1.1  leo 			if ((scr_base + MAX_PSHOWN) < ptable->nparts)
    218  1.1  leo 				scr_base += MAX_PSHOWN;
    219  1.1  leo 			break;
    220  1.1  leo 		    case T_PREV :
    221  1.1  leo 			scr_base -= MAX_PSHOWN;
    222  1.1  leo 			if (scr_base < 0)
    223  1.1  leo 				scr_base = 0;
    224  1.1  leo 			break;
    225  1.1  leo 		    case T_NUMBER:
    226  1.1  leo 			if (value >= ptable->nparts) {
    227  1.1  leo 				error = "Not that many partitions";
    228  1.1  leo 				break;
    229  1.1  leo 			}
    230  1.1  leo 			if ((new_id = get_id()) == NULL) {
    231  1.1  leo 				error = "Invalid id";
    232  1.1  leo 				break;
    233  1.1  leo 			}
    234  1.1  leo 			strncpy(ptable->parts[value].id, new_id, 3);
    235  1.1  leo 			ptable->parts[value].mod = 1;
    236  1.1  leo 			scr_base = (value / MAX_PSHOWN) * MAX_PSHOWN;
    237  1.1  leo 			break;
    238  1.1  leo 		    default :
    239  1.1  leo 			error = "Internal error - unknown token";
    240  1.1  leo 			break;
    241  1.1  leo 		}
    242  1.1  leo 		if (error != NULL) {
    243  1.1  leo 			printf("\n\n%s", error);
    244  1.1  leo 			fflush(stdout);
    245  1.1  leo 			sleep(2);
    246  1.1  leo 		}
    247  1.1  leo 	}
    248  1.1  leo }
    249  1.1  leo 
    250  1.1  leo int
    251  1.1  leo show_parts(ptable, nr)
    252  1.1  leo 	ptable_t	*ptable;
    253  1.1  leo 	int		nr;
    254  1.1  leo {
    255  1.1  leo 	int	i;
    256  1.1  leo 	part_t	*p;
    257  1.1  leo 	u_int	megs;
    258  1.1  leo 
    259  1.1  leo 	if (nr >= ptable->nparts)
    260  1.1  leo 		return (0);	/* Nothing to show */
    261  1.1  leo 	printf("\n\n");
    262  1.1  leo 	printf("nr      root  desc   id     start       end    MBs\n");
    263  1.1  leo 
    264  1.1  leo 	p = &ptable->parts[nr];
    265  1.1  leo 	i = nr;
    266  1.1  leo 	for(; (i < ptable->nparts) && ((i - nr) < MAX_PSHOWN); i++, p++) {
    267  1.1  leo 		megs = ((p->end - p->start + 1) + (BLPM >> 1)) / BLPM;
    268  1.1  leo 		printf("%2d%s %8u  %4u  %s  %8u  %8u  (%3u)\n", i,
    269  1.1  leo 			p->mod ? "*" : " ",
    270  1.1  leo 			p->rsec, p->rent, p->id, p->start, p->end, megs);
    271  1.1  leo 	}
    272  1.1  leo 	return (1);
    273  1.1  leo }
    274  1.1  leo 
    275  1.1  leo int
    276  1.1  leo lex(value)
    277  1.1  leo 	int	*value;
    278  1.1  leo {
    279  1.1  leo 	char	c[1];
    280  1.1  leo 	int	rv, nch;
    281  1.1  leo 
    282  1.1  leo 	rv = T_INVAL;
    283  1.1  leo 
    284  1.1  leo 	*value = 0;
    285  1.1  leo 	for (;;) {
    286  1.1  leo 		if ((nch = read (0, c, 1)) != 1) {
    287  1.1  leo 			if (nch == 0)
    288  1.1  leo 				return (T_EOF);
    289  1.1  leo 			else return (rv);
    290  1.1  leo 		}
    291  1.1  leo 		switch (*c) {
    292  1.1  leo 			case 'q':
    293  1.1  leo 				rv = T_QUIT;
    294  1.1  leo 				goto out;
    295  1.1  leo 			case 'w':
    296  1.1  leo 				rv = T_WRITE;
    297  1.1  leo 				goto out;
    298  1.1  leo 			case '>':
    299  1.1  leo 				rv = T_NEXT;
    300  1.1  leo 				goto out;
    301  1.1  leo 			case '<':
    302  1.1  leo 				rv = T_PREV;
    303  1.1  leo 				goto out;
    304  1.1  leo 			default :
    305  1.4   he 				if (isspace((unsigned char)*c)) {
    306  1.1  leo 					if (rv == T_INVAL)
    307  1.1  leo 						break;
    308  1.1  leo 					goto out;
    309  1.1  leo 				}
    310  1.4   he 				else if (isdigit((unsigned char)*c)) {
    311  1.1  leo 					*value = (10 * *value) + *c - '0';
    312  1.1  leo 					rv = T_NUMBER;
    313  1.1  leo 				}
    314  1.1  leo 				goto out;
    315  1.1  leo 		}
    316  1.1  leo 	}
    317  1.1  leo 	/* NOTREACHED */
    318  1.1  leo out:
    319  1.1  leo 	/*
    320  1.1  leo 	 * Flush rest of line before returning
    321  1.1  leo 	 */
    322  1.1  leo 	while (read (0, c, 1) == 1)
    323  1.1  leo 		if ((*c == '\n') || (*c == '\r'))
    324  1.1  leo 			break;
    325  1.1  leo 	return (rv);
    326  1.1  leo }
    327  1.1  leo 
    328  1.1  leo char *
    329  1.1  leo get_id()
    330  1.1  leo {
    331  1.1  leo 	static char	buf[5];
    332  1.1  leo 	       int	n;
    333  1.1  leo 	printf("\nEnter new id: ");
    334  1.1  leo 	if (fgets(buf, sizeof(buf), stdin) == NULL)
    335  1.1  leo 		return (NULL);
    336  1.1  leo 	for (n = 0; n < 3; n++) {
    337  1.4   he 		if (!isalpha((unsigned char)buf[n]))
    338  1.1  leo 			return (NULL);
    339  1.4   he 		buf[n] = toupper((unsigned char)buf[n]);
    340  1.1  leo 	}
    341  1.1  leo 	buf[3] = '\0';
    342  1.1  leo 	return (buf);
    343  1.1  leo }
    344  1.1  leo 
    345  1.1  leo int
    346  1.1  leo bsd_label(fd, offset)
    347  1.1  leo 	int		fd;
    348  1.1  leo 	u_int		offset;
    349  1.1  leo {
    350  1.1  leo 	u_char		*bblk;
    351  1.1  leo 	u_int		nsec;
    352  1.1  leo 	int		rv;
    353  1.1  leo 
    354  1.1  leo 	nsec = (BBMINSIZE + (DEV_BSIZE - 1)) / DEV_BSIZE;
    355  1.1  leo 	bblk = disk_read(fd, offset, nsec);
    356  1.1  leo 	if (bblk) {
    357  1.1  leo 		u_int	*end, *p;
    358  1.1  leo 
    359  1.1  leo 		end = (u_int *)&bblk[BBMINSIZE - sizeof(struct disklabel)];
    360  1.1  leo 		rv  = 1;
    361  1.1  leo 		for (p = (u_int *)bblk; p < end; ++p) {
    362  1.1  leo 			struct disklabel *dl = (struct disklabel *)&p[1];
    363  1.1  leo 			if (  (  (p[0] == NBDAMAGIC && offset == 0)
    364  1.1  leo 			      || (p[0] == AHDIMAGIC && offset != 0)
    365  1.1  leo 			      || (u_char *)dl - bblk == 7168
    366  1.1  leo 			      )
    367  1.1  leo 			   && dl->d_npartitions <= MAXPARTITIONS
    368  1.1  leo 			   && dl->d_magic2 == DISKMAGIC
    369  1.1  leo 			   && dl->d_magic  == DISKMAGIC
    370  1.1  leo 			   && dkcksum(dl)  == 0
    371  1.1  leo 			   )	{
    372  1.1  leo 				rv = 0;
    373  1.1  leo 				break;
    374  1.1  leo 			}
    375  1.1  leo 		}
    376  1.1  leo 		free(bblk);
    377  1.1  leo 	}
    378  1.1  leo 	else rv = -1;
    379  1.1  leo 
    380  1.1  leo 	return(rv);
    381  1.1  leo }
    382  1.1  leo 
    383  1.1  leo int
    384  1.1  leo dkcksum(dl)
    385  1.1  leo 	struct disklabel *dl;
    386  1.1  leo {
    387  1.1  leo 	u_short	*start, *end, sum = 0;
    388  1.1  leo 
    389  1.1  leo 	start = (u_short *)dl;
    390  1.1  leo 	end   = (u_short *)&dl->d_partitions[dl->d_npartitions];
    391  1.1  leo 	while (start < end)
    392  1.1  leo 		sum ^= *start++;
    393  1.1  leo 	return(sum);
    394  1.1  leo }
    395  1.1  leo 
    396  1.1  leo void
    397  1.1  leo ahdi_cksum(buf)
    398  1.1  leo void	*buf;
    399  1.1  leo {
    400  1.1  leo 	unsigned short	*p = (unsigned short *)buf;
    401  1.1  leo 	unsigned short	csum = 0;
    402  1.1  leo 	int		i;
    403  1.1  leo 
    404  1.1  leo 	p[255] = 0;
    405  1.1  leo 	for(i = 0; i < 256; i++)
    406  1.1  leo 		csum += *p++;
    407  1.1  leo 	*--p = (0x1234 - csum) & 0xffff;
    408  1.1  leo }
    409  1.1  leo 
    410  1.1  leo 
    411  1.1  leo u_int
    412  1.1  leo ahdi_getparts(fd, ptable, rsec, esec)
    413  1.1  leo 	int			fd;
    414  1.1  leo 	ptable_t		*ptable;
    415  1.1  leo 	u_int			rsec,
    416  1.1  leo 				esec;
    417  1.1  leo {
    418  1.1  leo 	struct ahdi_part	*part, *end;
    419  1.1  leo 	struct ahdi_root	*root;
    420  1.1  leo 	u_int			rv;
    421  1.1  leo 
    422  1.1  leo 	root = disk_read(fd, rsec, 1);
    423  1.1  leo 	if (!root) {
    424  1.1  leo 		rv = rsec + (rsec == 0);
    425  1.1  leo 		goto done;
    426  1.1  leo 	}
    427  1.1  leo 
    428  1.1  leo 	if (rsec == AHDI_BBLOCK)
    429  1.1  leo 		end = &root->ar_parts[AHDI_MAXRPD];
    430  1.1  leo 	else end = &root->ar_parts[AHDI_MAXARPD];
    431  1.1  leo 	for (part = root->ar_parts; part < end; ++part) {
    432  1.1  leo 		u_int	id = *((u_int32_t *)&part->ap_flg);
    433  1.1  leo 		if (!(id & 0x01000000))
    434  1.1  leo 			continue;
    435  1.1  leo 		if ((id &= 0x00ffffff) == AHDI_PID_XGM) {
    436  1.1  leo 			u_int	offs = part->ap_st + esec;
    437  1.1  leo 			rv = ahdi_getparts(fd, ptable, offs,
    438  1.1  leo 					esec == AHDI_BBLOCK ? offs : esec);
    439  1.1  leo 			if (rv)
    440  1.1  leo 				goto done;
    441  1.1  leo 		} else {
    442  1.1  leo 			part_t	*p;
    443  1.1  leo 			u_int	i = ++ptable->nparts;
    444  1.1  leo 			ptable->parts = realloc(ptable->parts,
    445  1.1  leo 						i * sizeof *ptable->parts);
    446  1.1  leo 			if (ptable->parts == NULL) {
    447  1.1  leo 				fprintf(stderr, "Allocation error\n");
    448  1.1  leo 				rv = 1;
    449  1.1  leo 				goto done;
    450  1.1  leo 			}
    451  1.1  leo 			p = &ptable->parts[--i];
    452  1.1  leo 			*((u_int32_t *)&p->id) = id << 8;
    453  1.1  leo 			p->start = part->ap_st + rsec;
    454  1.1  leo 			p->end   = p->start + part->ap_size - 1;
    455  1.1  leo 			p->rsec  = rsec;
    456  1.1  leo 			p->rent  = part - root->ar_parts;
    457  1.1  leo 			p->mod   = 0;
    458  1.1  leo 		}
    459  1.1  leo 	}
    460  1.1  leo 	rv = 0;
    461  1.1  leo done:
    462  1.1  leo 	free(root);
    463  1.1  leo 	return(rv);
    464  1.1  leo }
    465  1.1  leo 
    466  1.1  leo void *
    467  1.1  leo disk_read(fd, start, count)
    468  1.1  leo 	int	fd;
    469  1.1  leo 	u_int	start,
    470  1.1  leo 		count;
    471  1.1  leo {
    472  1.1  leo 	char	*buffer;
    473  1.1  leo 	off_t	offset;
    474  1.1  leo 	size_t	size;
    475  1.1  leo 
    476  1.1  leo 	size   = count * DEV_BSIZE;
    477  1.1  leo 	offset = start * DEV_BSIZE;
    478  1.1  leo 	if ((buffer = malloc(size)) == NULL)
    479  1.1  leo 		errx(1, "No memory");
    480  1.1  leo 
    481  1.1  leo 	if (lseek(fd, offset, SEEK_SET) != offset) {
    482  1.1  leo 		free(buffer);
    483  1.1  leo 		err(1, "Seek error");
    484  1.1  leo 	}
    485  1.1  leo 	if (read(fd, buffer, size) != size) {
    486  1.1  leo 		free(buffer);
    487  1.1  leo 		err(1, "Read error");
    488  1.1  leo 		exit(1);
    489  1.1  leo 	}
    490  1.1  leo 	return(buffer);
    491  1.1  leo }
    492  1.1  leo 
    493  1.1  leo void
    494  1.1  leo update_disk(ptable, fd, pno)
    495  1.1  leo 	ptable_t	*ptable;
    496  1.1  leo 	int		fd, pno;
    497  1.1  leo {
    498  1.1  leo 	struct ahdi_root	*root;
    499  1.1  leo 	struct ahdi_part	*apart;
    500  1.1  leo 	part_t			*lpart;
    501  1.1  leo 	u_int			rsec;
    502  1.1  leo 	int			i;
    503  1.1  leo 
    504  1.1  leo 	rsec = ptable->parts[pno].rsec;
    505  1.1  leo 	root = disk_read(fd, rsec, 1);
    506  1.1  leo 
    507  1.1  leo 	/*
    508  1.1  leo 	 * Look for additional mods on the same sector
    509  1.1  leo 	 */
    510  1.1  leo 	for (i = 0; i < ptable->nparts; i++) {
    511  1.1  leo 		lpart = &ptable->parts[i];
    512  1.1  leo 		if (lpart->mod && (lpart->rsec == rsec)) {
    513  1.1  leo 			apart = &root->ar_parts[lpart->rent];
    514  1.1  leo 
    515  1.1  leo 			/* Paranoia.... */
    516  1.1  leo 			if ((lpart->end - lpart->start + 1) != apart->ap_size)
    517  1.1  leo 				errx(1, "Updating wrong partition!");
    518  1.1  leo 			apart->ap_id[0] = lpart->id[0];
    519  1.1  leo 			apart->ap_id[1] = lpart->id[1];
    520  1.1  leo 			apart->ap_id[2] = lpart->id[2];
    521  1.1  leo 			lpart->mod = 0;
    522  1.1  leo 		}
    523  1.1  leo 	}
    524  1.1  leo 	if (rsec == 0)
    525  1.1  leo 		ahdi_cksum(root);
    526  1.1  leo 	disk_write(fd, rsec, 1, root);
    527  1.1  leo 	free(root);
    528  1.1  leo }
    529  1.1  leo 
    530  1.1  leo void
    531  1.1  leo disk_write(fd, start, count, buf)
    532  1.1  leo 	int	fd;
    533  1.1  leo 	u_int	start,
    534  1.1  leo 		count;
    535  1.1  leo 	void	*buf;
    536  1.1  leo {
    537  1.1  leo 	off_t	offset;
    538  1.1  leo 	size_t	size;
    539  1.1  leo 
    540  1.1  leo 	size   = count * DEV_BSIZE;
    541  1.1  leo 	offset = start * DEV_BSIZE;
    542  1.1  leo 
    543  1.1  leo 	if (lseek(fd, offset, SEEK_SET) != offset)
    544  1.1  leo 		err(1, "Seek error");
    545  1.1  leo 	if (write(fd, buf, size) != size)
    546  1.1  leo 		err(1, "Write error");
    547  1.1  leo }
    548  1.1  leo 
    549  1.1  leo void
    550  1.1  leo get_termcap()
    551  1.1  leo {
    552  1.1  leo 	char	*term, tbuf[1024], buf[1024], *p;
    553  1.1  leo 
    554  1.1  leo 	if ((term = getenv("TERM")) == NULL)
    555  1.1  leo 		warnx("No TERM environment variable!");
    556  1.1  leo 	else {
    557  1.1  leo 		if (tgetent(tbuf, term) != 1)
    558  1.1  leo 			errx(1, "Tgetent failure.");
    559  1.1  leo 		p = buf;
    560  1.1  leo 		if (tgetstr("cl", &p)) {
    561  1.1  leo 			if ((Clr_screen = malloc(strlen(buf) + 1)) == NULL)
    562  1.1  leo 				errx(1, "Malloc failure.");
    563  1.1  leo 			strcpy(Clr_screen, buf);
    564  1.1  leo 		}
    565  1.1  leo 	}
    566  1.1  leo }
    567