sgivol.c revision 1.4.6.1 1 1.4.6.1 lukem /* $NetBSD: sgivol.c,v 1.4.6.1 2002/07/19 01:32:11 lukem Exp $ */
2 1.1 soren
3 1.1 soren /*-
4 1.1 soren * Copyright (c) 2001 The NetBSD Foundation, Inc.
5 1.1 soren * All rights reserved.
6 1.1 soren *
7 1.1 soren * This code is derived from software contributed to The NetBSD Foundation
8 1.1 soren * by Michael Hitch and Hubert Feyrer.
9 1.1 soren *
10 1.1 soren * Redistribution and use in source and binary forms, with or without
11 1.1 soren * modification, are permitted provided that the following conditions
12 1.1 soren * are met:
13 1.1 soren * 1. Redistributions of source code must retain the above copyright
14 1.1 soren * notice, this list of conditions and the following disclaimer.
15 1.1 soren * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 soren * notice, this list of conditions and the following disclaimer in the
17 1.1 soren * documentation and/or other materials provided with the distribution.
18 1.1 soren * 3. All advertising materials mentioning features or use of this software
19 1.1 soren * must display the following acknowledgement:
20 1.1 soren * This product includes software developed by the NetBSD
21 1.1 soren * Foundation, Inc. and its contributors.
22 1.1 soren * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.1 soren * contributors may be used to endorse or promote products derived
24 1.1 soren * from this software without specific prior written permission.
25 1.1 soren *
26 1.1 soren * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.1 soren * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.1 soren * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.1 soren * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.1 soren * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.1 soren * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.1 soren * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.1 soren * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.1 soren * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.1 soren * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.1 soren * POSSIBILITY OF SUCH DAMAGE.
37 1.1 soren */
38 1.1 soren
39 1.2 thorpej #include <sys/types.h>
40 1.2 thorpej #include <sys/ioctl.h>
41 1.2 thorpej #include <sys/disklabel.h>
42 1.2 thorpej #include <sys/stat.h>
43 1.2 thorpej
44 1.4.6.1 lukem #include <errno.h>
45 1.1 soren #include <stdio.h>
46 1.2 thorpej #include <stdlib.h>
47 1.1 soren #include <unistd.h>
48 1.1 soren #include <string.h>
49 1.1 soren #include <fcntl.h>
50 1.1 soren #include <util.h>
51 1.1 soren
52 1.4.6.1 lukem /*
53 1.4.6.1 lukem * Some IRIX man pages refer to the size being a multiple of whole cylinders.
54 1.4.6.1 lukem * Later ones only refer to the size being "typically" 2MB. IRIX fx(1)
55 1.4.6.1 lukem * uses a default drive geometry if one can't be determined, suggesting
56 1.4.6.1 lukem * that "whole cylinder" multiples are not required.
57 1.4.6.1 lukem */
58 1.4.6.1 lukem
59 1.4.6.1 lukem #define SGI_SIZE_VOLHDR 3135 /* XXX This is really arbitrary */
60 1.1 soren
61 1.1 soren int fd;
62 1.1 soren int opt_i; /* Initialize volume header */
63 1.1 soren int opt_r; /* Read a file from volume header */
64 1.1 soren int opt_w; /* Write a file to volume header */
65 1.1 soren int opt_d; /* Delete a file from volume header */
66 1.1 soren int opt_p; /* Modify a partition */
67 1.4.6.1 lukem int opt_q; /* quiet mode */
68 1.4.6.1 lukem int opt_f; /* Don't ask, just do what you're told */
69 1.1 soren int partno, partfirst, partblocks, parttype;
70 1.1 soren struct sgilabel *volhdr;
71 1.2 thorpej int32_t checksum;
72 1.2 thorpej
73 1.2 thorpej const char *vfilename = "";
74 1.2 thorpej const char *ufilename = "";
75 1.1 soren
76 1.1 soren struct disklabel lbl;
77 1.1 soren
78 1.1 soren unsigned char buf[512];
79 1.1 soren
80 1.2 thorpej const char *sgi_types[] = {
81 1.1 soren "Volume Header",
82 1.1 soren "Repl Trks",
83 1.1 soren "Repl Secs",
84 1.1 soren "Raw",
85 1.1 soren "BSD4.2",
86 1.1 soren "SysV",
87 1.1 soren "Volume",
88 1.1 soren "EFS",
89 1.1 soren "LVol",
90 1.1 soren "RLVol",
91 1.1 soren "XFS",
92 1.1 soren "XSFLog",
93 1.1 soren "XLV",
94 1.1 soren "XVM"
95 1.1 soren };
96 1.1 soren
97 1.2 thorpej int main(int, char *[]);
98 1.2 thorpej
99 1.2 thorpej void display_vol(void);
100 1.2 thorpej void init_volhdr(void);
101 1.2 thorpej void read_file(void);
102 1.2 thorpej void write_file(void);
103 1.2 thorpej void delete_file(void);
104 1.2 thorpej void modify_partition(void);
105 1.2 thorpej void write_volhdr(void);
106 1.2 thorpej int allocate_space(int);
107 1.2 thorpej void checksum_vol(void);
108 1.2 thorpej void usage(void);
109 1.2 thorpej
110 1.2 thorpej int
111 1.2 thorpej main(int argc, char *argv[])
112 1.1 soren {
113 1.4.6.1 lukem int ch;
114 1.4.6.1 lukem while ((ch = getopt(argc, argv, "irwpdqf")) != -1) {
115 1.4.6.1 lukem switch (ch) {
116 1.4.6.1 lukem /* -i, -r, -w, -d and -p override each other */
117 1.4.6.1 lukem /* -q implies -f */
118 1.4.6.1 lukem case 'q':
119 1.4.6.1 lukem ++opt_q;
120 1.4.6.1 lukem ++opt_f;
121 1.4.6.1 lukem break;
122 1.4.6.1 lukem case 'f':
123 1.4.6.1 lukem ++opt_f;
124 1.4.6.1 lukem break;
125 1.1 soren case 'i':
126 1.1 soren ++opt_i;
127 1.4.6.1 lukem opt_r = opt_w = opt_d = opt_p = 0;
128 1.1 soren break;
129 1.1 soren case 'r':
130 1.4.6.1 lukem ++opt_r;
131 1.4.6.1 lukem opt_i = opt_w = opt_d = opt_p = 0;
132 1.4.6.1 lukem break;
133 1.1 soren case 'w':
134 1.4.6.1 lukem ++opt_w;
135 1.4.6.1 lukem opt_i = opt_r = opt_d = opt_p = 0;
136 1.1 soren break;
137 1.1 soren case 'd':
138 1.1 soren ++opt_d;
139 1.4.6.1 lukem opt_i = opt_r = opt_w = opt_p = 0;
140 1.4.6.1 lukem break;
141 1.1 soren case 'p':
142 1.1 soren ++opt_p;
143 1.4.6.1 lukem opt_i = opt_r = opt_w = opt_d = 0;
144 1.4.6.1 lukem partno = atoi(argv[0]);
145 1.4.6.1 lukem partfirst = atoi(argv[1]);
146 1.4.6.1 lukem partblocks = atoi(argv[2]);
147 1.4.6.1 lukem parttype = atoi(argv[3]);
148 1.1 soren break;
149 1.4.6.1 lukem case '?':
150 1.1 soren default:
151 1.1 soren usage();
152 1.1 soren }
153 1.1 soren }
154 1.4.6.1 lukem argc -= optind;
155 1.4.6.1 lukem argv += optind;
156 1.1 soren
157 1.4.6.1 lukem if (opt_r || opt_w) {
158 1.4.6.1 lukem if (argc != 3)
159 1.4.6.1 lukem usage();
160 1.4.6.1 lukem vfilename = argv[0];
161 1.4.6.1 lukem ufilename = argv[1];
162 1.4.6.1 lukem argc -= 2;
163 1.4.6.1 lukem argv += 2;
164 1.4.6.1 lukem }
165 1.4.6.1 lukem if (opt_d) {
166 1.4.6.1 lukem if (argc != 2)
167 1.4.6.1 lukem usage();
168 1.4.6.1 lukem vfilename = argv[0];
169 1.4.6.1 lukem argc--;
170 1.4.6.1 lukem argv++;
171 1.4.6.1 lukem }
172 1.1 soren
173 1.4.6.1 lukem if (opt_p) {
174 1.4.6.1 lukem if (argc != 5)
175 1.4.6.1 lukem usage();
176 1.4.6.1 lukem partno = atoi(argv[0]);
177 1.4.6.1 lukem partfirst = atoi(argv[1]);
178 1.4.6.1 lukem partblocks = atoi(argv[2]);
179 1.4.6.1 lukem parttype = atoi(argv[3]);
180 1.4.6.1 lukem argc -= 4;
181 1.4.6.1 lukem argv += 4;
182 1.4.6.1 lukem }
183 1.4.6.1 lukem if (argc != 1)
184 1.4.6.1 lukem usage();
185 1.4.6.1 lukem
186 1.4.6.1 lukem fd = open(argv[0], (opt_i | opt_w | opt_d | opt_p) ? O_RDWR : O_RDONLY);
187 1.1 soren if (fd < 0) {
188 1.4.6.1 lukem sprintf(buf, "/dev/r%s%c", argv[0], 'a' + getrawpartition());
189 1.4.6.1 lukem fd = open(buf, (opt_i | opt_w | opt_d | opt_p)
190 1.4.6.1 lukem ? O_RDWR : O_RDONLY);
191 1.1 soren if (fd < 0) {
192 1.4.6.1 lukem printf("Error opening device %s: %s\n",
193 1.4.6.1 lukem argv[0], strerror(errno));
194 1.1 soren exit(1);
195 1.1 soren }
196 1.1 soren }
197 1.2 thorpej if (read(fd, buf, sizeof(buf)) != sizeof(buf)) {
198 1.1 soren perror("read volhdr");
199 1.1 soren exit(1);
200 1.1 soren }
201 1.2 thorpej if (ioctl(fd, DIOCGDINFO, &lbl) < 0) {
202 1.1 soren perror("DIOCGDINFO");
203 1.1 soren exit(1);
204 1.1 soren }
205 1.1 soren volhdr = (struct sgilabel *)buf;
206 1.1 soren if (opt_i) {
207 1.1 soren init_volhdr();
208 1.1 soren exit(0);
209 1.1 soren }
210 1.1 soren if (volhdr->magic != SGILABEL_MAGIC) {
211 1.4.6.1 lukem printf("No Volume Header found, magic=%x. Use -i first.\n",
212 1.4.6.1 lukem volhdr->magic);
213 1.1 soren exit(1);
214 1.1 soren }
215 1.1 soren if (opt_r) {
216 1.1 soren read_file();
217 1.1 soren exit(0);
218 1.1 soren }
219 1.1 soren if (opt_w) {
220 1.1 soren write_file();
221 1.1 soren exit(0);
222 1.1 soren }
223 1.1 soren if (opt_d) {
224 1.1 soren delete_file();
225 1.1 soren exit(0);
226 1.1 soren }
227 1.1 soren if (opt_p) {
228 1.1 soren modify_partition();
229 1.1 soren exit(0);
230 1.1 soren }
231 1.4.6.1 lukem
232 1.4.6.1 lukem if (!opt_q)
233 1.4.6.1 lukem display_vol();
234 1.1 soren
235 1.1 soren return 0;
236 1.1 soren }
237 1.1 soren
238 1.2 thorpej void
239 1.2 thorpej display_vol(void)
240 1.1 soren {
241 1.2 thorpej int32_t *l;
242 1.2 thorpej int i;
243 1.2 thorpej
244 1.1 soren printf("disklabel shows %d sectors\n", lbl.d_secperunit);
245 1.2 thorpej l = (int32_t *)buf;
246 1.1 soren checksum = 0;
247 1.2 thorpej for (i = 0; i < 512 / 4; ++i)
248 1.2 thorpej checksum += l[i];
249 1.1 soren printf("checksum: %08x%s\n", checksum, checksum == 0 ? "" : " *ERROR*");
250 1.1 soren printf("root part: %d\n", volhdr->root);
251 1.1 soren printf("swap part: %d\n", volhdr->swap);
252 1.2 thorpej printf("bootfile: %s\n", volhdr->bootfile);
253 1.1 soren /* volhdr->devparams[0..47] */
254 1.1 soren printf("\nVolume header files:\n");
255 1.2 thorpej for (i = 0; i < 15; ++i)
256 1.2 thorpej if (volhdr->voldir[i].name[0])
257 1.1 soren printf("%-8s offset %4d blocks, length %8d bytes (%d blocks)\n",
258 1.2 thorpej volhdr->voldir[i].name, volhdr->voldir[i].block,
259 1.2 thorpej volhdr->voldir[i].bytes, (volhdr->voldir[i].bytes + 511 ) / 512);
260 1.1 soren printf("\nSGI partitions:\n");
261 1.2 thorpej for (i = 0; i < MAXPARTITIONS; ++i) {
262 1.2 thorpej if (volhdr->partitions[i].blocks) {
263 1.2 thorpej printf("%2d:%c blocks %8d first %8d type %2d (%s)\n",
264 1.2 thorpej i, i + 'a', volhdr->partitions[i].blocks,
265 1.2 thorpej volhdr->partitions[i].first,
266 1.2 thorpej volhdr->partitions[i].type,
267 1.2 thorpej volhdr->partitions[i].type > 13 ? "???" :
268 1.2 thorpej sgi_types[volhdr->partitions[i].type]);
269 1.2 thorpej }
270 1.2 thorpej }
271 1.1 soren }
272 1.1 soren
273 1.2 thorpej void
274 1.2 thorpej init_volhdr(void)
275 1.1 soren {
276 1.1 soren memset(buf, 0, sizeof(buf));
277 1.1 soren volhdr->magic = SGILABEL_MAGIC;
278 1.1 soren volhdr->root = 0;
279 1.1 soren volhdr->swap = 1;
280 1.2 thorpej strcpy(volhdr->bootfile, "/netbsd");
281 1.4 simonb volhdr->dp.dp_skew = lbl.d_trackskew;
282 1.4 simonb volhdr->dp.dp_gap1 = 1; /* XXX */
283 1.4 simonb volhdr->dp.dp_gap2 = 1; /* XXX */
284 1.4 simonb volhdr->dp.dp_cyls = lbl.d_ncylinders;
285 1.4 simonb volhdr->dp.dp_shd0 = 0;
286 1.4 simonb volhdr->dp.dp_trks0 = lbl.d_ntracks;
287 1.4 simonb volhdr->dp.dp_secs = lbl.d_nsectors;
288 1.4 simonb volhdr->dp.dp_secbytes = lbl.d_secsize;
289 1.4 simonb volhdr->dp.dp_interleave = lbl.d_interleave;
290 1.4 simonb volhdr->dp.dp_nretries = 22;
291 1.1 soren volhdr->partitions[10].blocks = lbl.d_secperunit;
292 1.1 soren volhdr->partitions[10].first = 0;
293 1.1 soren volhdr->partitions[10].type = SGI_PTYPE_VOLUME;
294 1.1 soren volhdr->partitions[8].blocks = SGI_SIZE_VOLHDR;
295 1.1 soren volhdr->partitions[8].first = 0;
296 1.1 soren volhdr->partitions[8].type = SGI_PTYPE_VOLHDR;
297 1.1 soren volhdr->partitions[0].blocks = lbl.d_secperunit - SGI_SIZE_VOLHDR;
298 1.1 soren volhdr->partitions[0].first = SGI_SIZE_VOLHDR;
299 1.2 thorpej volhdr->partitions[0].type = SGI_PTYPE_BSD;
300 1.1 soren write_volhdr();
301 1.1 soren }
302 1.1 soren
303 1.2 thorpej void
304 1.2 thorpej read_file(void)
305 1.1 soren {
306 1.1 soren FILE *fp;
307 1.2 thorpej int i;
308 1.1 soren
309 1.4.6.1 lukem if (!opt_q)
310 1.4.6.1 lukem printf("Reading file %s\n", vfilename);
311 1.2 thorpej for (i = 0; i < 15; ++i) {
312 1.3 thorpej if (strncmp(vfilename, volhdr->voldir[i].name,
313 1.3 thorpej sizeof(volhdr->voldir[i].name)) == NULL)
314 1.1 soren break;
315 1.1 soren }
316 1.2 thorpej if (i >= 15) {
317 1.1 soren printf("file %s not found\n", vfilename);
318 1.1 soren exit(1);
319 1.1 soren }
320 1.1 soren /* XXX assumes volume header starts at 0? */
321 1.2 thorpej lseek(fd, volhdr->voldir[i].block * 512, SEEK_SET);
322 1.1 soren fp = fopen(ufilename, "w");
323 1.1 soren if (fp == NULL) {
324 1.1 soren perror("open write");
325 1.1 soren exit(1);
326 1.1 soren }
327 1.2 thorpej i = volhdr->voldir[i].bytes;
328 1.2 thorpej while (i > 0) {
329 1.1 soren if (read(fd, buf, sizeof(buf)) != sizeof(buf)) {
330 1.1 soren perror("read file");
331 1.1 soren exit(1);
332 1.1 soren }
333 1.2 thorpej fwrite(buf, 1, i > sizeof(buf) ? sizeof(buf) : i, fp);
334 1.2 thorpej i -= i > sizeof(buf) ? sizeof(buf) : i;
335 1.1 soren }
336 1.1 soren fclose(fp);
337 1.1 soren }
338 1.1 soren
339 1.2 thorpej void
340 1.2 thorpej write_file(void)
341 1.1 soren {
342 1.1 soren FILE *fp;
343 1.2 thorpej int slot;
344 1.2 thorpej size_t namelen;
345 1.2 thorpej int block, i;
346 1.1 soren struct stat st;
347 1.1 soren char fbuf[512];
348 1.1 soren
349 1.4.6.1 lukem if (!opt_q)
350 1.4.6.1 lukem printf("Writing file %s\n", ufilename);
351 1.1 soren if (stat(ufilename, &st) < 0) {
352 1.1 soren perror("stat");
353 1.1 soren exit(1);
354 1.1 soren }
355 1.4.6.1 lukem if (!opt_q)
356 1.4.6.1 lukem printf("File %s has %lld bytes\n", ufilename, st.st_size);
357 1.2 thorpej slot = -1;
358 1.2 thorpej for (i = 0; i < 15; ++i) {
359 1.2 thorpej if (volhdr->voldir[i].name[0] == '\0' && slot < 0)
360 1.2 thorpej slot = i;
361 1.2 thorpej if (strcmp(vfilename, volhdr->voldir[i].name) == 0) {
362 1.2 thorpej slot = i;
363 1.1 soren break;
364 1.1 soren }
365 1.1 soren }
366 1.2 thorpej if (slot == -1) {
367 1.2 thorpej printf("No directory space for file %s\n", vfilename);
368 1.1 soren exit(1);
369 1.1 soren }
370 1.1 soren /* -w can overwrite, -a won't overwrite */
371 1.2 thorpej if (volhdr->voldir[slot].block > 0) {
372 1.4.6.1 lukem if (!opt_q)
373 1.4.6.1 lukem printf("File %s exists, removing old file\n",
374 1.4.6.1 lukem vfilename);
375 1.2 thorpej volhdr->voldir[slot].name[0] = 0;
376 1.2 thorpej volhdr->voldir[slot].block = volhdr->voldir[slot].bytes = 0;
377 1.1 soren }
378 1.1 soren if (st.st_size == 0) {
379 1.4.6.1 lukem printf("bad file size\n");
380 1.1 soren exit(1);
381 1.1 soren }
382 1.1 soren /* XXX assumes volume header starts at 0? */
383 1.1 soren block = allocate_space((int)st.st_size);
384 1.1 soren if (block < 0) {
385 1.1 soren printf("No space for file\n");
386 1.1 soren exit(1);
387 1.1 soren }
388 1.1 soren
389 1.2 thorpej /*
390 1.2 thorpej * Make sure the name in the volume header is max. 8 chars,
391 1.2 thorpej * NOT including NUL.
392 1.2 thorpej */
393 1.2 thorpej namelen = strlen(vfilename);
394 1.2 thorpej if (namelen > sizeof(volhdr->voldir[slot].name)) {
395 1.1 soren printf("Warning: '%s' is too long for volume header, ",
396 1.1 soren vfilename);
397 1.2 thorpej namelen = sizeof(volhdr->voldir[slot].name);
398 1.2 thorpej printf("truncating to '%-8s'\n", vfilename);
399 1.1 soren }
400 1.4 simonb
401 1.2 thorpej /* Populate it w/ NULs */
402 1.2 thorpej memset(volhdr->voldir[slot].name, 0,
403 1.2 thorpej sizeof(volhdr->voldir[slot].name));
404 1.2 thorpej /* Then copy the name */
405 1.2 thorpej memcpy(volhdr->voldir[slot].name, vfilename, namelen);
406 1.2 thorpej
407 1.2 thorpej volhdr->voldir[slot].block = block;
408 1.2 thorpej volhdr->voldir[slot].bytes = st.st_size;
409 1.1 soren
410 1.1 soren write_volhdr();
411 1.1 soren
412 1.1 soren /* write the file itself */
413 1.2 thorpej i = lseek(fd, block * 512, SEEK_SET);
414 1.2 thorpej if (i < 0) {
415 1.1 soren perror("lseek write");
416 1.1 soren exit(1);
417 1.1 soren }
418 1.2 thorpej i = st.st_size;
419 1.1 soren fp = fopen(ufilename, "r");
420 1.2 thorpej while (i > 0) {
421 1.2 thorpej fread(fbuf, 1, i > 512 ? 512 : i, fp);
422 1.1 soren if (write(fd, fbuf, 512) != 512) {
423 1.1 soren perror("write file");
424 1.1 soren exit(1);
425 1.1 soren }
426 1.2 thorpej i -= i > 512 ? 512 : i;
427 1.1 soren }
428 1.1 soren }
429 1.1 soren
430 1.2 thorpej void
431 1.2 thorpej delete_file(void)
432 1.1 soren {
433 1.2 thorpej int i;
434 1.2 thorpej
435 1.2 thorpej for (i = 0; i < 15; ++i) {
436 1.2 thorpej if (strcmp(vfilename, volhdr->voldir[i].name) == NULL) {
437 1.1 soren break;
438 1.1 soren }
439 1.1 soren }
440 1.2 thorpej if (i >= 15) {
441 1.1 soren printf("File %s not found\n", vfilename);
442 1.1 soren exit(1);
443 1.1 soren }
444 1.4.6.1 lukem
445 1.4.6.1 lukem /* XXX: we don't compact the file space, so get fragmentation */
446 1.2 thorpej volhdr->voldir[i].name[0] = '\0';
447 1.2 thorpej volhdr->voldir[i].block = volhdr->voldir[i].bytes = 0;
448 1.1 soren write_volhdr();
449 1.1 soren }
450 1.1 soren
451 1.2 thorpej void
452 1.2 thorpej modify_partition(void)
453 1.1 soren {
454 1.4.6.1 lukem if (!opt_q)
455 1.4.6.1 lukem printf("Modify partition %d start %d length %d\n",
456 1.4.6.1 lukem partno, partfirst, partblocks);
457 1.1 soren if (partno < 0 || partno > 15) {
458 1.4.6.1 lukem printf("Invalid partition number: %d\n", partno);
459 1.1 soren exit(1);
460 1.1 soren }
461 1.1 soren volhdr->partitions[partno].blocks = partblocks;
462 1.1 soren volhdr->partitions[partno].first = partfirst;
463 1.1 soren volhdr->partitions[partno].type = parttype;
464 1.1 soren write_volhdr();
465 1.1 soren }
466 1.1 soren
467 1.2 thorpej void
468 1.2 thorpej write_volhdr(void)
469 1.1 soren {
470 1.2 thorpej int i;
471 1.2 thorpej
472 1.1 soren checksum_vol();
473 1.4.6.1 lukem
474 1.4.6.1 lukem if (!opt_q)
475 1.4.6.1 lukem display_vol();
476 1.4.6.1 lukem if (!opt_f) {
477 1.4.6.1 lukem printf("\nDo you want to update volume (y/n)? ");
478 1.4.6.1 lukem i = getchar();
479 1.4.6.1 lukem if (i != 'Y' && i != 'y')
480 1.4.6.1 lukem exit(1);
481 1.4.6.1 lukem }
482 1.2 thorpej i = lseek(fd, 0 , SEEK_SET);
483 1.2 thorpej if (i < 0) {
484 1.1 soren perror("lseek 0");
485 1.1 soren exit(1);
486 1.1 soren }
487 1.2 thorpej i = write(fd, buf, 512);
488 1.2 thorpej if (i < 0)
489 1.1 soren perror("write volhdr");
490 1.1 soren }
491 1.1 soren
492 1.2 thorpej int
493 1.2 thorpej allocate_space(int size)
494 1.1 soren {
495 1.1 soren int n, blocks;
496 1.1 soren int first;
497 1.1 soren
498 1.1 soren blocks = (size + 511) / 512;
499 1.1 soren first = 2;
500 1.1 soren n = 0;
501 1.1 soren while (n < 15) {
502 1.1 soren if (volhdr->voldir[n].name[0]) {
503 1.1 soren if (first < (volhdr->voldir[n].block +
504 1.1 soren (volhdr->voldir[n].bytes + 511) / 512) &&
505 1.4.6.1 lukem (first + blocks) > volhdr->voldir[n].block) {
506 1.1 soren first = volhdr->voldir[n].block +
507 1.1 soren (volhdr->voldir[n].bytes + 511) / 512;
508 1.1 soren #if 0
509 1.1 soren printf("allocate: n=%d first=%d blocks=%d size=%d\n", n, first, blocks, size);
510 1.1 soren printf("%s %d %d\n", volhdr->voldir[n].name, volhdr->voldir[n].block, volhdr->voldir[n].bytes);
511 1.1 soren printf("first=%d block=%d last=%d end=%d\n", first, volhdr->voldir[n].block,
512 1.1 soren first + blocks - 1, volhdr->voldir[n].block + (volhdr->voldir[n].bytes + 511)/512);
513 1.1 soren #endif
514 1.1 soren n = 0;
515 1.1 soren continue;
516 1.1 soren }
517 1.1 soren }
518 1.1 soren ++n;
519 1.1 soren }
520 1.1 soren if (first + blocks > lbl.d_secperunit)
521 1.1 soren first = -1;
522 1.1 soren /* XXX assumes volume header is partition 8 */
523 1.1 soren /* XXX assumes volume header starts at 0? */
524 1.1 soren if (first + blocks >= volhdr->partitions[8].blocks)
525 1.1 soren first = -1;
526 1.1 soren return(first);
527 1.1 soren }
528 1.1 soren
529 1.2 thorpej void
530 1.2 thorpej checksum_vol(void)
531 1.1 soren {
532 1.2 thorpej int32_t *l;
533 1.2 thorpej int i;
534 1.2 thorpej
535 1.1 soren volhdr->checksum = checksum = 0;
536 1.2 thorpej l = (int32_t *)buf;
537 1.2 thorpej for (i = 0; i < 512 / 4; ++i)
538 1.2 thorpej checksum += l[i];
539 1.1 soren volhdr->checksum = -checksum;
540 1.1 soren }
541 1.1 soren
542 1.2 thorpej void
543 1.2 thorpej usage(void)
544 1.1 soren {
545 1.4.6.1 lukem printf("Usage: sgivol [-qf] [-i] device\n"
546 1.4.6.1 lukem " sgivol [-qf] [-r vhfilename diskfilename] device\n"
547 1.4.6.1 lukem " sgivol [-qf] [-w vhfilename diskfilename] device\n"
548 1.4.6.1 lukem " sgivol [-qf] [-d vhfilename] device\n"
549 1.1 soren );
550 1.1 soren exit(0);
551 1.1 soren }
552