Home | History | Annotate | Line # | Download | only in edahdi
edahdi.c revision 1.2
      1  1.2  leo /*	$NetBSD: edahdi.c,v 1.2 1999/06/01 14:27:39 leo 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 void	outc __P((int));
    113  1.1  leo int	show_parts __P((ptable_t *, int));
    114  1.1  leo void	update_disk __P((ptable_t *, int, int));
    115  1.1  leo 
    116  1.1  leo int
    117  1.1  leo main(argc, argv)
    118  1.1  leo int	argc;
    119  1.1  leo char	*argv[];
    120  1.1  leo {
    121  1.1  leo 	int		fd;
    122  1.1  leo 	ptable_t	ptable;
    123  1.1  leo 	int		rv;
    124  1.1  leo 	struct stat	st;
    125  1.1  leo 
    126  1.1  leo 	if (argc != 2) {
    127  1.1  leo 		char	*prog = strrchr(argv[0], '/');
    128  1.1  leo 
    129  1.1  leo 		if (prog == NULL)
    130  1.1  leo 			prog = argv[0];
    131  1.1  leo 		else prog++;
    132  1.1  leo 		fprintf(stderr, "Usage: %s <raw_disk_device>", prog);
    133  1.1  leo 		exit(1);
    134  1.1  leo 	}
    135  1.1  leo 	if ((fd = open(argv[1], O_RDWR)) < 0)
    136  1.1  leo 		err(1, "Cannot open '%s'.", argv[1]);
    137  1.1  leo 	if (fstat(fd, &st) < 0)
    138  1.1  leo 		err(1, "Cannot stat '%s'.", argv[1]);
    139  1.1  leo 	if (!S_ISCHR(st.st_mode))
    140  1.1  leo 		errx(1, "'%s' must be a character special device.", argv[1]);
    141  1.1  leo 
    142  1.1  leo 	if ((rv = bsd_label(fd, LABELSECTOR)) < 0)
    143  1.1  leo 		errx(1, "I/O error");
    144  1.1  leo 	if (rv == 0) {
    145  1.1  leo 		warnx("Disk has no ahdi partitions");
    146  1.1  leo 		return (2);
    147  1.1  leo 	}
    148  1.1  leo 
    149  1.1  leo 	get_termcap();
    150  1.1  leo 
    151  1.1  leo 	ptable.nparts = 0;
    152  1.1  leo 	ptable.parts  = NULL;
    153  1.1  leo 
    154  1.1  leo 	if ((ahdi_getparts(fd, &ptable, AHDI_BBLOCK, AHDI_BBLOCK) != 0)
    155  1.1  leo 		|| (ptable.nparts == 0))
    156  1.1  leo 		exit (1);
    157  1.1  leo 
    158  1.1  leo 	edit_parts(fd, &ptable);
    159  1.1  leo 	return (0);
    160  1.1  leo }
    161  1.1  leo 
    162  1.1  leo int
    163  1.1  leo edit_parts(fd, ptable)
    164  1.1  leo 	int		fd;
    165  1.1  leo 	ptable_t	*ptable;
    166  1.1  leo {
    167  1.1  leo 	int	scr_base = 0;
    168  1.1  leo 	int	value;
    169  1.1  leo 	char	*error, *new_id;
    170  1.1  leo 
    171  1.1  leo 	for (;;) {
    172  1.1  leo 		error = NULL;
    173  1.1  leo 		tputs(Clr_screen, 1, outc);
    174  1.1  leo 		show_parts(ptable, scr_base);
    175  1.1  leo 
    176  1.1  leo 		printf("\n\n");
    177  1.1  leo 		printf("q    : quit - don't update the disk\n");
    178  1.1  leo 		printf("w    : write changes to disk\n");
    179  1.1  leo 		printf(">    : next screen of partitions\n");
    180  1.1  leo 		printf("<    : previous screen of partitions\n");
    181  1.1  leo 		printf("<nr> : modify id of partition <nr>\n");
    182  1.1  leo 		printf("\n\nCommand? ");
    183  1.1  leo 		fflush(stdout);
    184  1.1  leo 
    185  1.1  leo 		switch (lex(&value)) {
    186  1.1  leo 		    case T_EOF:
    187  1.1  leo 			exit(0);
    188  1.1  leo 
    189  1.1  leo 		    case T_INVAL:
    190  1.1  leo 			error = "Invalid command";
    191  1.1  leo 			break;
    192  1.1  leo 		    case T_QUIT :
    193  1.1  leo 			for (value = 0; value < ptable->nparts; value++) {
    194  1.1  leo 				if (ptable->parts[value].mod) {
    195  1.1  leo 					printf("\nThere are unwritten changes."
    196  1.1  leo 						" Quit anyway? [n] ");
    197  1.1  leo 					value = getchar();
    198  1.1  leo 					if ((value == 'y') || (value == 'Y'))
    199  1.1  leo 							exit (0);
    200  1.1  leo 					while (value != '\n')
    201  1.1  leo 						value = getchar();
    202  1.1  leo 					break;
    203  1.1  leo 				}
    204  1.1  leo 			}
    205  1.1  leo 			if (value == ptable->nparts)
    206  1.1  leo 				exit(0);
    207  1.1  leo 			break;
    208  1.1  leo 		    case T_WRITE:
    209  1.1  leo 			error = "No changes to write";
    210  1.1  leo 			for (value = 0; value < ptable->nparts; value++) {
    211  1.1  leo 				if (ptable->parts[value].mod) {
    212  1.1  leo 					update_disk(ptable, fd, value);
    213  1.1  leo 					error = "";
    214  1.1  leo 				}
    215  1.1  leo 			}
    216  1.1  leo 			break;
    217  1.1  leo 		    case T_NEXT :
    218  1.1  leo 			if ((scr_base + MAX_PSHOWN) < ptable->nparts)
    219  1.1  leo 				scr_base += MAX_PSHOWN;
    220  1.1  leo 			break;
    221  1.1  leo 		    case T_PREV :
    222  1.1  leo 			scr_base -= MAX_PSHOWN;
    223  1.1  leo 			if (scr_base < 0)
    224  1.1  leo 				scr_base = 0;
    225  1.1  leo 			break;
    226  1.1  leo 		    case T_NUMBER:
    227  1.1  leo 			if (value >= ptable->nparts) {
    228  1.1  leo 				error = "Not that many partitions";
    229  1.1  leo 				break;
    230  1.1  leo 			}
    231  1.1  leo 			if ((new_id = get_id()) == NULL) {
    232  1.1  leo 				error = "Invalid id";
    233  1.1  leo 				break;
    234  1.1  leo 			}
    235  1.1  leo 			strncpy(ptable->parts[value].id, new_id, 3);
    236  1.1  leo 			ptable->parts[value].mod = 1;
    237  1.1  leo 			scr_base = (value / MAX_PSHOWN) * MAX_PSHOWN;
    238  1.1  leo 			break;
    239  1.1  leo 		    default :
    240  1.1  leo 			error = "Internal error - unknown token";
    241  1.1  leo 			break;
    242  1.1  leo 		}
    243  1.1  leo 		if (error != NULL) {
    244  1.1  leo 			printf("\n\n%s", error);
    245  1.1  leo 			fflush(stdout);
    246  1.1  leo 			sleep(2);
    247  1.1  leo 		}
    248  1.1  leo 	}
    249  1.1  leo }
    250  1.1  leo 
    251  1.1  leo int
    252  1.1  leo show_parts(ptable, nr)
    253  1.1  leo 	ptable_t	*ptable;
    254  1.1  leo 	int		nr;
    255  1.1  leo {
    256  1.1  leo 	int	i;
    257  1.1  leo 	part_t	*p;
    258  1.1  leo 	u_int	megs;
    259  1.1  leo 
    260  1.1  leo 	if (nr >= ptable->nparts)
    261  1.1  leo 		return (0);	/* Nothing to show */
    262  1.1  leo 	printf("\n\n");
    263  1.1  leo 	printf("nr      root  desc   id     start       end    MBs\n");
    264  1.1  leo 
    265  1.1  leo 	p = &ptable->parts[nr];
    266  1.1  leo 	i = nr;
    267  1.1  leo 	for(; (i < ptable->nparts) && ((i - nr) < MAX_PSHOWN); i++, p++) {
    268  1.1  leo 		megs = ((p->end - p->start + 1) + (BLPM >> 1)) / BLPM;
    269  1.1  leo 		printf("%2d%s %8u  %4u  %s  %8u  %8u  (%3u)\n", i,
    270  1.1  leo 			p->mod ? "*" : " ",
    271  1.1  leo 			p->rsec, p->rent, p->id, p->start, p->end, megs);
    272  1.1  leo 	}
    273  1.1  leo 	return (1);
    274  1.1  leo }
    275  1.1  leo 
    276  1.1  leo int
    277  1.1  leo lex(value)
    278  1.1  leo 	int	*value;
    279  1.1  leo {
    280  1.1  leo 	char	c[1];
    281  1.1  leo 	int	rv, nch;
    282  1.1  leo 
    283  1.1  leo 	rv = T_INVAL;
    284  1.1  leo 
    285  1.1  leo 	*value = 0;
    286  1.1  leo 	for (;;) {
    287  1.1  leo 		if ((nch = read (0, c, 1)) != 1) {
    288  1.1  leo 			if (nch == 0)
    289  1.1  leo 				return (T_EOF);
    290  1.1  leo 			else return (rv);
    291  1.1  leo 		}
    292  1.1  leo 		switch (*c) {
    293  1.1  leo 			case 'q':
    294  1.1  leo 				rv = T_QUIT;
    295  1.1  leo 				goto out;
    296  1.1  leo 			case 'w':
    297  1.1  leo 				rv = T_WRITE;
    298  1.1  leo 				goto out;
    299  1.1  leo 			case '>':
    300  1.1  leo 				rv = T_NEXT;
    301  1.1  leo 				goto out;
    302  1.1  leo 			case '<':
    303  1.1  leo 				rv = T_PREV;
    304  1.1  leo 				goto out;
    305  1.1  leo 			default :
    306  1.1  leo 				if (isspace(*c)) {
    307  1.1  leo 					if (rv == T_INVAL)
    308  1.1  leo 						break;
    309  1.1  leo 					goto out;
    310  1.1  leo 				}
    311  1.1  leo 				else if (isdigit(*c)) {
    312  1.1  leo 					*value = (10 * *value) + *c - '0';
    313  1.1  leo 					rv = T_NUMBER;
    314  1.1  leo 				}
    315  1.1  leo 				goto out;
    316  1.1  leo 		}
    317  1.1  leo 	}
    318  1.1  leo 	/* NOTREACHED */
    319  1.1  leo out:
    320  1.1  leo 	/*
    321  1.1  leo 	 * Flush rest of line before returning
    322  1.1  leo 	 */
    323  1.1  leo 	while (read (0, c, 1) == 1)
    324  1.1  leo 		if ((*c == '\n') || (*c == '\r'))
    325  1.1  leo 			break;
    326  1.1  leo 	return (rv);
    327  1.1  leo }
    328  1.1  leo 
    329  1.1  leo char *
    330  1.1  leo get_id()
    331  1.1  leo {
    332  1.1  leo 	static char	buf[5];
    333  1.1  leo 	       int	n;
    334  1.1  leo 	printf("\nEnter new id: ");
    335  1.1  leo 	if (fgets(buf, sizeof(buf), stdin) == NULL)
    336  1.1  leo 		return (NULL);
    337  1.1  leo 	for (n = 0; n < 3; n++) {
    338  1.1  leo 		if (!isalpha(buf[n]))
    339  1.1  leo 			return (NULL);
    340  1.1  leo 		buf[n] = toupper(buf[n]);
    341  1.1  leo 	}
    342  1.1  leo 	buf[3] = '\0';
    343  1.1  leo 	return (buf);
    344  1.1  leo }
    345  1.1  leo 
    346  1.1  leo int
    347  1.1  leo bsd_label(fd, offset)
    348  1.1  leo 	int		fd;
    349  1.1  leo 	u_int		offset;
    350  1.1  leo {
    351  1.1  leo 	u_char		*bblk;
    352  1.1  leo 	u_int		nsec;
    353  1.1  leo 	int		rv;
    354  1.1  leo 
    355  1.1  leo 	nsec = (BBMINSIZE + (DEV_BSIZE - 1)) / DEV_BSIZE;
    356  1.1  leo 	bblk = disk_read(fd, offset, nsec);
    357  1.1  leo 	if (bblk) {
    358  1.1  leo 		u_int	*end, *p;
    359  1.1  leo 
    360  1.1  leo 		end = (u_int *)&bblk[BBMINSIZE - sizeof(struct disklabel)];
    361  1.1  leo 		rv  = 1;
    362  1.1  leo 		for (p = (u_int *)bblk; p < end; ++p) {
    363  1.1  leo 			struct disklabel *dl = (struct disklabel *)&p[1];
    364  1.1  leo 			if (  (  (p[0] == NBDAMAGIC && offset == 0)
    365  1.1  leo 			      || (p[0] == AHDIMAGIC && offset != 0)
    366  1.1  leo 			      || (u_char *)dl - bblk == 7168
    367  1.1  leo 			      )
    368  1.1  leo 			   && dl->d_npartitions <= MAXPARTITIONS
    369  1.1  leo 			   && dl->d_magic2 == DISKMAGIC
    370  1.1  leo 			   && dl->d_magic  == DISKMAGIC
    371  1.1  leo 			   && dkcksum(dl)  == 0
    372  1.1  leo 			   )	{
    373  1.1  leo 				rv = 0;
    374  1.1  leo 				break;
    375  1.1  leo 			}
    376  1.1  leo 		}
    377  1.1  leo 		free(bblk);
    378  1.1  leo 	}
    379  1.1  leo 	else rv = -1;
    380  1.1  leo 
    381  1.1  leo 	return(rv);
    382  1.1  leo }
    383  1.1  leo 
    384  1.1  leo int
    385  1.1  leo dkcksum(dl)
    386  1.1  leo 	struct disklabel *dl;
    387  1.1  leo {
    388  1.1  leo 	u_short	*start, *end, sum = 0;
    389  1.1  leo 
    390  1.1  leo 	start = (u_short *)dl;
    391  1.1  leo 	end   = (u_short *)&dl->d_partitions[dl->d_npartitions];
    392  1.1  leo 	while (start < end)
    393  1.1  leo 		sum ^= *start++;
    394  1.1  leo 	return(sum);
    395  1.1  leo }
    396  1.1  leo 
    397  1.1  leo void
    398  1.1  leo ahdi_cksum(buf)
    399  1.1  leo void	*buf;
    400  1.1  leo {
    401  1.1  leo 	unsigned short	*p = (unsigned short *)buf;
    402  1.1  leo 	unsigned short	csum = 0;
    403  1.1  leo 	int		i;
    404  1.1  leo 
    405  1.1  leo 	p[255] = 0;
    406  1.1  leo 	for(i = 0; i < 256; i++)
    407  1.1  leo 		csum += *p++;
    408  1.1  leo 	*--p = (0x1234 - csum) & 0xffff;
    409  1.1  leo }
    410  1.1  leo 
    411  1.1  leo 
    412  1.1  leo u_int
    413  1.1  leo ahdi_getparts(fd, ptable, rsec, esec)
    414  1.1  leo 	int			fd;
    415  1.1  leo 	ptable_t		*ptable;
    416  1.1  leo 	u_int			rsec,
    417  1.1  leo 				esec;
    418  1.1  leo {
    419  1.1  leo 	struct ahdi_part	*part, *end;
    420  1.1  leo 	struct ahdi_root	*root;
    421  1.1  leo 	u_int			rv;
    422  1.1  leo 
    423  1.1  leo 	root = disk_read(fd, rsec, 1);
    424  1.1  leo 	if (!root) {
    425  1.1  leo 		rv = rsec + (rsec == 0);
    426  1.1  leo 		goto done;
    427  1.1  leo 	}
    428  1.1  leo 
    429  1.1  leo 	if (rsec == AHDI_BBLOCK)
    430  1.1  leo 		end = &root->ar_parts[AHDI_MAXRPD];
    431  1.1  leo 	else end = &root->ar_parts[AHDI_MAXARPD];
    432  1.1  leo 	for (part = root->ar_parts; part < end; ++part) {
    433  1.1  leo 		u_int	id = *((u_int32_t *)&part->ap_flg);
    434  1.1  leo 		if (!(id & 0x01000000))
    435  1.1  leo 			continue;
    436  1.1  leo 		if ((id &= 0x00ffffff) == AHDI_PID_XGM) {
    437  1.1  leo 			u_int	offs = part->ap_st + esec;
    438  1.1  leo 			rv = ahdi_getparts(fd, ptable, offs,
    439  1.1  leo 					esec == AHDI_BBLOCK ? offs : esec);
    440  1.1  leo 			if (rv)
    441  1.1  leo 				goto done;
    442  1.1  leo 		} else {
    443  1.1  leo 			part_t	*p;
    444  1.1  leo 			u_int	i = ++ptable->nparts;
    445  1.1  leo 			ptable->parts = realloc(ptable->parts,
    446  1.1  leo 						i * sizeof *ptable->parts);
    447  1.1  leo 			if (ptable->parts == NULL) {
    448  1.1  leo 				fprintf(stderr, "Allocation error\n");
    449  1.1  leo 				rv = 1;
    450  1.1  leo 				goto done;
    451  1.1  leo 			}
    452  1.1  leo 			p = &ptable->parts[--i];
    453  1.1  leo 			*((u_int32_t *)&p->id) = id << 8;
    454  1.1  leo 			p->start = part->ap_st + rsec;
    455  1.1  leo 			p->end   = p->start + part->ap_size - 1;
    456  1.1  leo 			p->rsec  = rsec;
    457  1.1  leo 			p->rent  = part - root->ar_parts;
    458  1.1  leo 			p->mod   = 0;
    459  1.1  leo 		}
    460  1.1  leo 	}
    461  1.1  leo 	rv = 0;
    462  1.1  leo done:
    463  1.1  leo 	free(root);
    464  1.1  leo 	return(rv);
    465  1.1  leo }
    466  1.1  leo 
    467  1.1  leo void *
    468  1.1  leo disk_read(fd, start, count)
    469  1.1  leo 	int	fd;
    470  1.1  leo 	u_int	start,
    471  1.1  leo 		count;
    472  1.1  leo {
    473  1.1  leo 	char	*buffer;
    474  1.1  leo 	off_t	offset;
    475  1.1  leo 	size_t	size;
    476  1.1  leo 
    477  1.1  leo 	size   = count * DEV_BSIZE;
    478  1.1  leo 	offset = start * DEV_BSIZE;
    479  1.1  leo 	if ((buffer = malloc(size)) == NULL)
    480  1.1  leo 		errx(1, "No memory");
    481  1.1  leo 
    482  1.1  leo 	if (lseek(fd, offset, SEEK_SET) != offset) {
    483  1.1  leo 		free(buffer);
    484  1.1  leo 		err(1, "Seek error");
    485  1.1  leo 	}
    486  1.1  leo 	if (read(fd, buffer, size) != size) {
    487  1.1  leo 		free(buffer);
    488  1.1  leo 		err(1, "Read error");
    489  1.1  leo 		exit(1);
    490  1.1  leo 	}
    491  1.1  leo 	return(buffer);
    492  1.1  leo }
    493  1.1  leo 
    494  1.1  leo void
    495  1.1  leo update_disk(ptable, fd, pno)
    496  1.1  leo 	ptable_t	*ptable;
    497  1.1  leo 	int		fd, pno;
    498  1.1  leo {
    499  1.1  leo 	struct ahdi_root	*root;
    500  1.1  leo 	struct ahdi_part	*apart;
    501  1.1  leo 	part_t			*lpart;
    502  1.1  leo 	u_int			rsec;
    503  1.1  leo 	int			i;
    504  1.1  leo 
    505  1.1  leo 	rsec = ptable->parts[pno].rsec;
    506  1.1  leo 	root = disk_read(fd, rsec, 1);
    507  1.1  leo 
    508  1.1  leo 	/*
    509  1.1  leo 	 * Look for additional mods on the same sector
    510  1.1  leo 	 */
    511  1.1  leo 	for (i = 0; i < ptable->nparts; i++) {
    512  1.1  leo 		lpart = &ptable->parts[i];
    513  1.1  leo 		if (lpart->mod && (lpart->rsec == rsec)) {
    514  1.1  leo 			apart = &root->ar_parts[lpart->rent];
    515  1.1  leo 
    516  1.1  leo 			/* Paranoia.... */
    517  1.1  leo 			if ((lpart->end - lpart->start + 1) != apart->ap_size)
    518  1.1  leo 				errx(1, "Updating wrong partition!");
    519  1.1  leo 			apart->ap_id[0] = lpart->id[0];
    520  1.1  leo 			apart->ap_id[1] = lpart->id[1];
    521  1.1  leo 			apart->ap_id[2] = lpart->id[2];
    522  1.1  leo 			lpart->mod = 0;
    523  1.1  leo 		}
    524  1.1  leo 	}
    525  1.1  leo 	if (rsec == 0)
    526  1.1  leo 		ahdi_cksum(root);
    527  1.1  leo 	disk_write(fd, rsec, 1, root);
    528  1.1  leo 	free(root);
    529  1.1  leo }
    530  1.1  leo 
    531  1.1  leo void
    532  1.1  leo disk_write(fd, start, count, buf)
    533  1.1  leo 	int	fd;
    534  1.1  leo 	u_int	start,
    535  1.1  leo 		count;
    536  1.1  leo 	void	*buf;
    537  1.1  leo {
    538  1.1  leo 	off_t	offset;
    539  1.1  leo 	size_t	size;
    540  1.1  leo 
    541  1.1  leo 	size   = count * DEV_BSIZE;
    542  1.1  leo 	offset = start * DEV_BSIZE;
    543  1.1  leo 
    544  1.1  leo 	if (lseek(fd, offset, SEEK_SET) != offset)
    545  1.1  leo 		err(1, "Seek error");
    546  1.1  leo 	if (write(fd, buf, size) != size)
    547  1.1  leo 		err(1, "Write error");
    548  1.1  leo }
    549  1.1  leo 
    550  1.1  leo void
    551  1.1  leo get_termcap()
    552  1.1  leo {
    553  1.1  leo 	char	*term, tbuf[1024], buf[1024], *p;
    554  1.1  leo 
    555  1.1  leo 	if ((term = getenv("TERM")) == NULL)
    556  1.1  leo 		warnx("No TERM environment variable!");
    557  1.1  leo 	else {
    558  1.1  leo 		if (tgetent(tbuf, term) != 1)
    559  1.1  leo 			errx(1, "Tgetent failure.");
    560  1.1  leo 		p = buf;
    561  1.1  leo 		if (tgetstr("cl", &p)) {
    562  1.1  leo 			if ((Clr_screen = malloc(strlen(buf) + 1)) == NULL)
    563  1.1  leo 				errx(1, "Malloc failure.");
    564  1.1  leo 			strcpy(Clr_screen, buf);
    565  1.1  leo 		}
    566  1.1  leo 	}
    567  1.1  leo }
    568  1.1  leo 
    569  1.1  leo void
    570  1.1  leo outc(c)
    571  1.1  leo int	c;
    572  1.1  leo {
    573  1.1  leo 	(void)putchar(c);
    574  1.1  leo }
    575