Annotation of src/distrib/utils/sysinst/util.c, Revision 1.49
1.49 ! cgd 1: /* $NetBSD: util.c,v 1.48 1999/07/04 22:31:37 cgd Exp $ */
1.1 phil 2:
3: /*
4: * Copyright 1997 Piermont Information Systems Inc.
5: * All rights reserved.
6: *
7: * Written by Philip A. Nelson for Piermont Information Systems Inc.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. All advertising materials mentioning features or use of this software
18: * must display the following acknowledgement:
1.42 cgd 19: * This product includes software developed for the NetBSD Project by
1.1 phil 20: * Piermont Information Systems Inc.
21: * 4. The name of Piermont Information Systems Inc. may not be used to endorse
22: * or promote products derived from this software without specific prior
23: * written permission.
24: *
25: * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
26: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28: * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
29: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
35: * THE POSSIBILITY OF SUCH DAMAGE.
36: *
37: */
38:
39: /* util.c -- routines that don't really fit anywhere else... */
40:
41: #include <stdio.h>
1.10 jonathan 42: #include <stdarg.h>
1.1 phil 43: #include <unistd.h>
1.5 phil 44: #include <sys/types.h>
1.4 phil 45: #include <sys/param.h>
46: #include <sys/sysctl.h>
1.5 phil 47: #include <sys/stat.h>
1.2 phil 48: #include <curses.h>
1.37 bouyer 49: #include <errno.h>
1.1 phil 50: #include "defs.h"
1.5 phil 51: #include "md.h"
1.1 phil 52: #include "msg_defs.h"
53: #include "menu_defs.h"
1.4 phil 54:
1.14 jonathan 55: /*
56: * local prototypes
57: */
1.29 mrg 58: struct tarstats {
1.22 jonathan 59: int nselected;
60: int nfound;
61: int nnotfound;
62: int nerror;
63: int nsuccess;
1.44 cgd 64: int nskipped;
1.22 jonathan 65: } tarstats;
66:
1.44 cgd 67: int extract_file __P((char *path));
1.22 jonathan 68: int extract_dist __P((void));
1.37 bouyer 69: int cleanup_dist __P((const char *path));
1.22 jonathan 70: int distribution_sets_exist_p __P((const char *path));
1.14 jonathan 71: static int check_for __P((const char *type, const char *pathname));
1.4 phil 72:
1.29 mrg 73: /*
74: * XXX these are WAY bogus!
75: */
76: int
77: dir_exists_p(path)
78: const char *path;
1.22 jonathan 79: {
80: register int result;
1.29 mrg 81:
1.35 bouyer 82: result = (run_prog(0, 0, NULL, "test -d %s", path) == 0);
1.22 jonathan 83: return (result);
84: }
85:
1.29 mrg 86: int
87: file_exists_p(path)
88: const char *path;
1.22 jonathan 89: {
90: register int result;
1.29 mrg 91:
1.35 bouyer 92: result = (run_prog(0, 0, NULL, "test -f %s", path) == 0);
1.22 jonathan 93: return (result);
94: }
95:
1.29 mrg 96: int
97: distribution_sets_exist_p(path)
98: const char *path;
1.22 jonathan 99: {
100: char buf[STRSIZE];
101: int result;
102:
103: result = 1;
104: snprintf(buf, STRSIZE, "%s/%s", path, "kern.tgz");
105: result = result && file_exists_p(buf);
106:
107: snprintf(buf, STRSIZE, "%s/%s", path, "etc.tgz");
108: result = result && file_exists_p(buf);
109:
110: return(result);
111: }
112:
113:
1.29 mrg 114: void
115: get_ramsize()
1.4 phil 116: {
1.29 mrg 117: long len = sizeof(long);
1.4 phil 118: int mib[2] = {CTL_HW, HW_PHYSMEM};
119:
120: sysctl(mib, 2, (void *)&ramsize, (size_t *)&len, NULL, 0);
121:
122: /* Find out how many Megs ... round up. */
123: rammb = (ramsize + MEG - 1) / MEG;
124: }
125:
1.1 phil 126: static int asked = 0;
127:
1.29 mrg 128: void
129: ask_sizemult()
1.1 phil 130: {
1.29 mrg 131:
1.1 phil 132: if (!asked) {
1.29 mrg 133: msg_display(MSG_sizechoice, dlcylsize);
134: process_menu(MENU_sizechoice);
1.1 phil 135: }
136: asked = 1;
1.9 phil 137: }
138:
1.29 mrg 139: void
140: reask_sizemult()
1.9 phil 141: {
1.29 mrg 142:
1.9 phil 143: asked = 0;
1.29 mrg 144: ask_sizemult();
1.1 phil 145: }
146:
1.29 mrg 147: void
148: run_makedev()
1.3 phil 149: {
1.22 jonathan 150: char *owd;
151:
1.39 bouyer 152: wclear(stdscr);
153: wrefresh(stdscr);
1.29 mrg 154: msg_display(MSG_makedev);
1.5 phil 155: sleep (1);
1.14 jonathan 156:
1.29 mrg 157: owd = getcwd(NULL,0);
1.22 jonathan 158:
1.14 jonathan 159: /* make /dev, in case the user didn't extract it. */
160: make_target_dir("/dev");
1.10 jonathan 161: target_chdir_or_die("/dev");
1.35 bouyer 162: run_prog(0, 0, NULL, "/bin/sh MAKEDEV all");
1.22 jonathan 163:
164: chdir(owd);
165: free(owd);
1.5 phil 166: }
167:
168:
1.29 mrg 169: /*
170: * Load files from floppy. Requires a /mnt2 directory for mounting them.
171: */
172: int
173: get_via_floppy()
1.5 phil 174: {
175: char distname[STRSIZE];
176: char fddev[STRSIZE] = "/dev/fd0a";
177: char fname[STRSIZE];
178: char fullname[STRSIZE];
1.34 garbled 179: char catcmd[STRSIZE];
1.7 phil 180: distinfo *list;
1.5 phil 181: char post[4];
182: int mounted = 0;
1.8 phil 183: int first;
1.5 phil 184: struct stat sb;
185:
1.29 mrg 186: cd_dist_dir("unloading from floppy");
1.7 phil 187:
1.29 mrg 188: msg_prompt_add(MSG_fddev, fddev, fddev, STRSIZE);
1.5 phil 189:
190: list = dist_list;
1.7 phil 191: while (list->name) {
1.29 mrg 192: strcpy(post, ".aa");
193: snprintf(distname, STRSIZE, "%s%s", list->name, dist_postfix);
1.8 phil 194: while (list->getit && strcmp(&post[1],list->fdlast) <= 0) {
1.29 mrg 195: snprintf(fname, STRSIZE, "%s%s", list->name, post);
196: snprintf(fullname, STRSIZE, "/mnt2/%s", fname);
1.8 phil 197: first = 1;
1.5 phil 198: while (!mounted || stat(fullname, &sb)) {
1.8 phil 199: if (mounted)
1.35 bouyer 200: run_prog(0, 0, NULL, "/sbin/umount /mnt2");
1.8 phil 201: if (first)
1.29 mrg 202: msg_display(MSG_fdmount, fname);
1.8 phil 203: else
1.29 mrg 204: msg_display(MSG_fdnotfound, fname);
205: process_menu(MENU_fdok);
1.8 phil 206: if (!yesno)
207: return 0;
1.35 bouyer 208: while (run_prog(0, 0, NULL,
209: "/sbin/mount -r -t %s %s /mnt2",
1.29 mrg 210: fdtype, fddev)) {
211: msg_display(MSG_fdremount, fname);
212: process_menu(MENU_fdremount);
1.5 phil 213: if (!yesno)
214: return 0;
215: }
216: mounted = 1;
1.8 phil 217: first = 0;
1.5 phil 218: }
1.34 garbled 219: sprintf(catcmd, "/bin/cat %s >> %s",
220: fullname, distname);
221: if (logging)
222: (void)fprintf(log, "%s\n", catcmd);
223: if (scripting)
224: (void)fprintf(script, "%s\n", catcmd);
225: do_system(catcmd);
1.8 phil 226: if (post[2] < 'z')
227: post[2]++;
1.5 phil 228: else
1.29 mrg 229: post[2] = 'a', post[1]++;
1.5 phil 230: }
1.35 bouyer 231: run_prog(0, 0, NULL, "/sbin/umount /mnt2");
1.5 phil 232: mounted = 0;
233: list++;
234: }
235: #ifndef DEBUG
1.10 jonathan 236: chdir("/"); /* back to current real root */
1.5 phil 237: #endif
1.6 phil 238: return 1;
239: }
240:
1.29 mrg 241: /*
242: * Get from a CDROM distribution.
243: */
1.6 phil 244: int
1.29 mrg 245: get_via_cdrom()
1.6 phil 246: {
1.22 jonathan 247: char tmpdir[STRSIZE];
248:
1.29 mrg 249: /*
250: * Fill in final default path, similar to ftp path
251: * because we expect the CDROM structure to be the
252: * same as the ftp site.
253: */
254: strncat(cdrom_dir, machine, STRSIZE - strlen(cdrom_dir));
255: strncat(cdrom_dir, ftp_prefix, STRSIZE - strlen(cdrom_dir));
1.28 fvdl 256:
257: /* Get CD-rom device name and path within CD-rom */
1.29 mrg 258: process_menu(MENU_cdromsource);
1.6 phil 259:
1.22 jonathan 260: again:
1.35 bouyer 261: run_prog(0, 0, NULL, "/sbin/umount /mnt2");
1.22 jonathan 262:
1.6 phil 263: /* Mount it */
1.35 bouyer 264: if (run_prog(0, 0, NULL,
265: "/sbin/mount -rt cd9660 /dev/%sa /mnt2", cdrom_dev)) {
1.22 jonathan 266: msg_display(MSG_badsetdir, cdrom_dev);
1.29 mrg 267: process_menu(MENU_cdrombadmount);
1.6 phil 268: if (!yesno)
269: return 0;
1.22 jonathan 270: if (!ignorerror)
271: goto again;
272: }
273:
274: snprintf(tmpdir, STRSIZE, "%s/%s", "/mnt2", cdrom_dir);
275:
276: /* Verify distribution files exist. */
277: if (distribution_sets_exist_p(tmpdir) == 0) {
278: msg_display(MSG_badsetdir, tmpdir);
1.29 mrg 279: process_menu(MENU_cdrombadmount);
1.22 jonathan 280: if (!yesno)
281: return (0);
282: if (!ignorerror)
283: goto again;
1.6 phil 284: }
285:
286: /* return location, don't clean... */
1.22 jonathan 287: strncpy(ext_dir, tmpdir, STRSIZE);
1.6 phil 288: clean_dist_dir = 0;
289: mnt2_mounted = 1;
1.5 phil 290: return 1;
1.7 phil 291: }
292:
1.22 jonathan 293:
294: /*
295: * Get from a pathname inside an unmounted local filesystem
296: * (e.g., where sets were preloaded onto a local DOS partition)
297: */
1.29 mrg 298: int
299: get_via_localfs()
1.16 mhitch 300: {
1.22 jonathan 301: char tmpdir[STRSIZE];
302:
1.16 mhitch 303: /* Get device, filesystem, and filepath */
304: process_menu (MENU_localfssource);
305:
1.22 jonathan 306: again:
1.35 bouyer 307: run_prog(0, 0, NULL, "/sbin/umount /mnt2");
1.22 jonathan 308:
1.16 mhitch 309: /* Mount it */
1.35 bouyer 310: if (run_prog(0, 0, NULL, "/sbin/mount -rt %s /dev/%s /mnt2",
311: localfs_fs, localfs_dev)) {
1.22 jonathan 312:
1.29 mrg 313: msg_display(MSG_localfsbadmount, localfs_dir, localfs_dev);
314: process_menu(MENU_localfsbadmount);
1.16 mhitch 315: if (!yesno)
316: return 0;
1.22 jonathan 317: if (!ignorerror)
1.29 mrg 318: goto again;
1.22 jonathan 319: }
320:
321: snprintf(tmpdir, STRSIZE, "%s/%s", "/mnt2", localfs_dir);
322:
323: /* Verify distribution files exist. */
324: if (distribution_sets_exist_p(tmpdir) == 0) {
325: msg_display(MSG_badsetdir, tmpdir);
1.29 mrg 326: process_menu(MENU_localfsbadmount);
1.22 jonathan 327: if (!yesno)
328: return 0;
329: if (!ignorerror)
330: goto again;
1.16 mhitch 331: }
332:
333: /* return location, don't clean... */
1.22 jonathan 334: strncpy(ext_dir, tmpdir, STRSIZE);
1.16 mhitch 335: clean_dist_dir = 0;
336: mnt2_mounted = 1;
337: return 1;
338: }
1.7 phil 339:
1.29 mrg 340: /*
341: * Get from an already-mounted pathname.
342: */
1.22 jonathan 343:
344: int get_via_localdir(void)
345: {
346:
347: /* Get device, filesystem, and filepath */
1.29 mrg 348: process_menu(MENU_localdirsource);
1.22 jonathan 349:
350: again:
351: /* Complain if not a directory */
352: if (dir_exists_p(localfs_dir) == 0) {
353:
1.29 mrg 354: msg_display(MSG_badlocalsetdir, localfs_dir);
355: process_menu(MENU_localdirbad);
1.22 jonathan 356: if (!yesno)
357: return (0);
358: if (!ignorerror)
359: goto again;
360: }
361:
362: /* Verify distribution files exist. */
363: if (distribution_sets_exist_p(localfs_dir) == 0) {
364: msg_display(MSG_badsetdir, localfs_dir);
1.29 mrg 365: process_menu(MENU_localdirbad);
1.22 jonathan 366: if (!yesno)
367: return (0);
368: if (!ignorerror)
369: goto again;
370: }
371:
372: /* return location, don't clean... */
1.29 mrg 373: strncpy(ext_dir, localfs_dir, STRSIZE);
1.22 jonathan 374: clean_dist_dir = 0;
375: mnt2_mounted = 0;
376: return 1;
377: }
378:
379:
1.29 mrg 380: void
381: cd_dist_dir(forwhat)
382: char *forwhat;
1.7 phil 383: {
1.19 phil 384: char *cwd;
385:
1.10 jonathan 386: /* ask user for the mountpoint. */
1.29 mrg 387: msg_prompt(MSG_distdir, dist_dir, dist_dir, STRSIZE, forwhat);
1.10 jonathan 388:
389: /* make sure the directory exists. */
390: make_target_dir(dist_dir);
1.7 phil 391:
392: clean_dist_dir = 1;
1.10 jonathan 393: target_chdir_or_die(dist_dir);
1.19 phil 394:
395: /* Set ext_dir for absolute path. */
1.29 mrg 396: cwd = getcwd(NULL,0);
397: strncpy(ext_dir, cwd, STRSIZE);
1.19 phil 398: free (cwd);
1.7 phil 399: }
400:
1.10 jonathan 401:
1.29 mrg 402: /*
403: * Support for custom distribution fetches / unpacks.
404: */
405: void
406: toggle_getit(num)
407: int num;
408: {
1.7 phil 409:
410: dist_list[num].getit ^= 1;
411: }
412:
1.29 mrg 413: void
414: show_cur_distsets()
1.7 phil 415: {
416: distinfo *list;
417:
1.29 mrg 418: msg_display(MSG_cur_distsets);
1.48 cgd 419: msg_table_add(MSG_cur_distsets_header);
1.7 phil 420: list = dist_list;
421: while (list->name) {
1.48 cgd 422: msg_table_add(MSG_cur_distsets_row, list->desc,
1.29 mrg 423: list->getit ? msg_string(MSG_yes) : msg_string(MSG_no));
1.7 phil 424: list++;
425: }
1.1 phil 426: }
1.10 jonathan 427:
1.12 phil 428: /* Do we want a verbose extract? */
429: static int verbose = -1;
430:
431: void
1.29 mrg 432: ask_verbose_dist()
1.12 phil 433: {
1.29 mrg 434:
1.12 phil 435: if (verbose < 0) {
1.29 mrg 436: msg_display(MSG_verboseextract);
437: process_menu(MENU_noyes);
1.12 phil 438: verbose = yesno;
1.36 bouyer 439: wclear(stdscr);
440: wrefresh(stdscr);
1.12 phil 441: }
442: }
443:
1.44 cgd 444: int
1.29 mrg 445: extract_file(path)
446: char *path;
1.12 phil 447: {
448: char *owd;
1.44 cgd 449: int tarexit, rv;
1.12 phil 450:
451: owd = getcwd (NULL,0);
452:
1.22 jonathan 453: /* check tarfile exists */
454: if (!file_exists_p(path)) {
455: tarstats.nnotfound++;
1.44 cgd 456:
457: msg_display(MSG_notarfile, path);
458: process_menu(MENU_noyes);
459: return (yesno == 0);
1.22 jonathan 460: }
461:
462: tarstats.nfound++;
1.14 jonathan 463: /* cd to the target root. */
1.12 phil 464: target_chdir_or_die("/");
465:
1.14 jonathan 466: /* now extract set files files into "./". */
1.35 bouyer 467: tarexit = run_prog(0, 1, NULL,
468: "pax -zr%spe -f %s", verbose ? "v" : "", path);
1.22 jonathan 469:
1.17 phil 470: /* Check tarexit for errors and give warning. */
1.22 jonathan 471: if (tarexit) {
472: tarstats.nerror++;
1.44 cgd 473:
474: msg_display(MSG_tarerror, path);
475: process_menu(MENU_noyes);
476: rv = (yesno == 0);
1.22 jonathan 477: } else {
478: tarstats.nsuccess++;
1.44 cgd 479: rv = 0;
1.22 jonathan 480: }
481:
1.29 mrg 482: chdir(owd);
483: free(owd);
1.44 cgd 484:
485: return (rv);
1.12 phil 486: }
487:
1.19 phil 488:
1.29 mrg 489: /*
1.37 bouyer 490: * Extract_dist **REQUIRES** an absolute path in ext_dir. Any code
1.19 phil 491: * that sets up dist_dir for use by extract_dist needs to put in the
492: * full path name to the directory.
493: */
494:
1.22 jonathan 495: int
1.29 mrg 496: extract_dist()
1.12 phil 497: {
498: char distname[STRSIZE];
499: char fname[STRSIZE];
500: distinfo *list;
1.44 cgd 501: int punt;
1.12 phil 502:
1.22 jonathan 503: /* reset failure/success counters */
1.31 perry 504: memset(&tarstats, 0, sizeof(tarstats));
1.22 jonathan 505:
1.32 garbled 506: /*endwin();*/
1.44 cgd 507: for (punt = 0, list = dist_list; list->name != NULL; list++) {
1.15 phil 508: if (list->getit) {
1.22 jonathan 509: tarstats.nselected++;
1.44 cgd 510: if (punt) {
511: tarstats.nskipped++;
512: continue;
513: }
1.37 bouyer 514: if (cleanup_dist(list->name) == 0) {
515: msg_display(MSG_cleanup_warn);
516: process_menu(MENU_ok);
517: }
1.29 mrg 518: (void)snprintf(distname, STRSIZE, "%s%s", list->name,
519: dist_postfix);
520: (void)snprintf(fname, STRSIZE, "%s/%s", ext_dir,
521: distname);
1.44 cgd 522:
523: /* if extraction failed and user aborted, punt. */
524: punt = extract_file(fname);
1.15 phil 525: }
1.12 phil 526: }
1.22 jonathan 527:
1.43 cgd 528: puts(CL); /* XXX */
529: wclear(stdscr);
1.17 phil 530: wrefresh(stdscr);
1.22 jonathan 531:
532: if (tarstats.nerror == 0 && tarstats.nsuccess == tarstats.nselected) {
1.29 mrg 533: msg_display(MSG_endtarok);
534: process_menu(MENU_ok);
1.22 jonathan 535: return 0;
536: } else {
537: /* We encountered errors. Let the user know. */
538: msg_display(MSG_endtar,
1.44 cgd 539: tarstats.nselected, tarstats.nnotfound, tarstats.nskipped,
1.22 jonathan 540: tarstats.nfound, tarstats.nsuccess, tarstats.nerror);
1.29 mrg 541: process_menu(MENU_ok);
1.22 jonathan 542: return 1;
543: }
1.12 phil 544: }
545:
1.11 jonathan 546: /*
1.37 bouyer 547: * Do pre-extract cleanup for set 'name':
548: * open a file named '/dist/<name>_obsolete file', which contain a list of
549: * files to kill from the target. For each file, test if it is present on
550: * the target. Then display the list of files which will be removed,
551: * ask user for confirmation, and process.
552: * Non-empty directories will be renaned to <directory.old>.
553: */
554:
555: /* definition for a list of files. */
556: struct filelist {
557: struct filelist *next;
558: char name[MAXPATHLEN];
559: mode_t type;
560: };
561:
562: int
563: cleanup_dist(name)
564: const char *name;
565: {
566: char file_path[MAXPATHLEN];
567: char file_name[MAXPATHLEN];
568: FILE *list_file;
569: struct filelist *head = NULL;
570: struct filelist *current;
571: int saved_errno;
572: struct stat st;
573: int retval = 1;
574: int needok = 0;
575:
576: snprintf(file_path, MAXPATHLEN, "/dist/%s_obsolete", name);
577: list_file = fopen(file_path, "r");
578: if (list_file == NULL) {
579: saved_errno = errno;
580: if (logging)
581: fprintf(log, "Open of %s failed: %s\n", file_path,
582: strerror(saved_errno));
583: if (saved_errno == ENOENT)
584: return 1;
585: msg_display_add(MSG_openfail, name, strerror(saved_errno));
586: process_menu(MENU_ok);
587: return 0;
588: }
589: while (fgets(file_name, MAXPATHLEN, list_file)) {
590: /* ignore lines that don't begin with '/' */
591: if (file_name[0] != '/')
592: continue;
593: /* Remove trailing \n if any */
594: if (file_name[strlen(file_name)-1] == '\n')
595: file_name[strlen(file_name)-1] = '\0';
596: snprintf(file_path, MAXPATHLEN, "%s%s", target_prefix(),
597: file_name);
598: if (lstat(file_path, &st) != 0) {
599: saved_errno = errno;
600: if (logging)
601: fprintf(log, "stat() of %s failed: %s\n",
602: file_path, strerror(saved_errno));
603: if (saved_errno == ENOENT)
604: continue;
605: msg_display_add(MSG_statfail, file_path,
606: strerror(saved_errno));
607: process_menu(MENU_ok);
608: return 0;
609: }
610: if (head == NULL) {
611: head = current = malloc(sizeof(struct filelist));
612: if (head == NULL) {
613: fprintf(stderr, "out of memory\n");
614: exit(1);
615: }
616: } else {
617: current->next = malloc(sizeof(struct filelist));
618: if (head == NULL) {
619: fprintf(stderr, "out of memory\n");
620: exit(1);
621: }
622: current = current->next;
623: }
624: current->next = NULL;
625: snprintf(current->name, MAXPATHLEN, "%s", file_path);
626: current->type = st.st_mode & S_IFMT;
627: if (logging)
628: fprintf(log, "Adding file %s, type %d to list of "
629: "obsolete file\n", current->name, current->type);
630: }
631: if (head == NULL)
1.38 bouyer 632: return 1;
1.37 bouyer 633: #if 0
634: /* XXX doesn't work, too many files printed ! */
635: msg_display(MSG_deleting_files);
636: for (current = head; current != NULL; current = current->next) {
1.49 ! cgd 637: if (current->type != S_IFDIR) {
! 638: /* XXX msg_printf_add going/gone away */
1.37 bouyer 639: msg_printf_add("%s ", current->name);
1.49 ! cgd 640: }
1.37 bouyer 641: }
642: msg_display_add(MSG_deleting_dirs);
643: for (current = head; current != NULL; current = current->next) {
1.49 ! cgd 644: if (current->type == S_IFDIR) {
! 645: /* XXX msg_printf_add going/gone away */
1.37 bouyer 646: msg_printf_add("%s ", current->name);
1.49 ! cgd 647: }
1.37 bouyer 648: }
649: process_menu(MENU_ok);
650: #endif
651: /* first remove files */
652: for (current = head; current != NULL; current = current->next) {
653: if (current->type == S_IFDIR)
654: continue;
655: if (scripting)
656: (void)fprintf(script, "rm %s\n", current->name);
657: if (unlink(current->name) != 0) {
658: saved_errno = errno;
659: if (logging)
660: fprintf(log, "rm %s failed: %s\n",
661: current->name, strerror(saved_errno));
662: msg_display_add(MSG_unlink_fail, current->name,
663: strerror(saved_errno));
664: retval = 0;
665: needok = 1;
666: }
667:
668: }
669: /* now dirs */
670: for (current = head; current != NULL; current = current->next) {
671: if (current->type != S_IFDIR)
672: continue;
673: if (rmdir(current->name) == 0) {
674: if (scripting)
675: (void)fprintf(script, "rmdir %s\n",
676: current->name);
677: continue;
678: }
679: saved_errno = errno;
680: if (saved_errno == ENOTEMPTY) {
681: if (logging)
682: fprintf(log, "dir %s not empty, "
683: "trying to rename to %s.old\n",
684: current->name, current->name);
685: snprintf(file_path, MAXPATHLEN,
686: "%s.old", current->name);
687: if (scripting)
688: (void)fprintf(script, "mv %s %s\n",
689: current->name, file_path);
690: needok = 1;
691: if (rename(current->name, file_path) != 0) {
692: saved_errno = errno;
693: if (logging)
694: fprintf(log, "mv %s %s failed: %s\n",
695: current->name, file_path,
696: strerror(saved_errno));
697: msg_display_add(MSG_rename_fail, current->name,
698: file_path, strerror(errno));
699: retval = 0;
700: }
701: msg_display_add(MSG_renamed_dir, current->name,
702: file_path);
703: } else { /* rmdir error */
704: if (logging)
705: fprintf(log, "rm %s failed: %s\n",
706: current->name, strerror(saved_errno));
707: msg_display_add(MSG_unlink_fail, current->name,
708: strerror(saved_errno));
709: retval = 0;
710: needok = 1;
711: }
712: }
713: if (needok)
714: process_menu(MENU_ok);
715: return retval;
716: }
717:
718: /*
1.29 mrg 719: * Get and unpack the distribution.
720: * show success_msg if installation completes. Otherwise,,
721: * show failure_msg and wait for the user to ack it before continuing.
1.11 jonathan 722: * success_msg and failure_msg must both be 0-adic messages.
723: */
1.45 cgd 724: int
1.29 mrg 725: get_and_unpack_sets(success_msg, failure_msg)
1.47 cgd 726: msg success_msg;
727: msg failure_msg;
1.11 jonathan 728: {
1.29 mrg 729:
1.20 jonathan 730: /* Ensure mountpoint for distribution files exists in current root. */
1.32 garbled 731: (void) mkdir("/mnt2", S_IRWXU| S_IRGRP|S_IXGRP | S_IROTH|S_IXOTH);
732: if (scripting)
733: (void)fprintf(script, "mkdir /mnt2\nchmod 755 /mnt2\n");
1.20 jonathan 734:
1.26 phil 735: /* Find out which files to "get" if we get files. */
1.37 bouyer 736: wclear(stdscr);
737: wrefresh(stdscr);
1.29 mrg 738: process_menu(MENU_distset);
1.26 phil 739:
1.37 bouyer 740: /* ask user whether to do normal or verbose extraction */
741: ask_verbose_dist();
742:
1.11 jonathan 743: /* Get the distribution files */
1.46 cgd 744: do {
745: got_dist = 0;
746: process_menu(MENU_distmedium);
747: } while (got_dist == -1);
1.26 phil 748:
1.11 jonathan 749: if (nodist)
1.45 cgd 750: return 1;
1.20 jonathan 751:
1.22 jonathan 752: if (got_dist) {
1.11 jonathan 753:
1.22 jonathan 754: /* Extract the distribution, abort on errors. */
1.45 cgd 755: if (extract_dist())
756: return 1;
1.11 jonathan 757:
758: /* Configure the system */
1.29 mrg 759: run_makedev();
1.11 jonathan 760:
761: /* Other configuration. */
762: mnt_net_config();
763:
1.19 phil 764: /* Clean up dist dir (use absolute path name) */
1.11 jonathan 765: if (clean_dist_dir)
1.35 bouyer 766: run_prog(0, 0, NULL, "/bin/rm -rf %s", ext_dir);
1.11 jonathan 767:
768: /* Mounted dist dir? */
769: if (mnt2_mounted)
1.35 bouyer 770: run_prog(0, 0, NULL, "/sbin/umount /mnt2");
1.14 jonathan 771:
1.29 mrg 772: /* Install/Upgrade complete ... reboot or exit to script */
773: msg_display(success_msg);
774: process_menu(MENU_ok);
1.45 cgd 775: return 0;
1.22 jonathan 776: }
777:
1.29 mrg 778: msg_display(failure_msg);
779: process_menu(MENU_ok);
1.45 cgd 780: return 1;
1.14 jonathan 781: }
1.22 jonathan 782:
783:
1.14 jonathan 784:
785: /*
786: * Do a quick sanity check that the target can reboot.
787: * return 1 if everything OK, 0 if there is a problem.
788: * Uses a table of files we expect to find after a base install/upgrade.
789: */
790:
791: /* test flag and pathname to check for after unpacking. */
792: struct check_table { const char *testarg; const char *path;} checks[] = {
793: { "-f", "/netbsd" },
1.25 jonathan 794: { "-d", "/etc" },
1.14 jonathan 795: { "-f", "/etc/fstab" },
796: { "-f", "/sbin/init" },
797: { "-f", "/bin/sh" },
1.20 jonathan 798: { "-f", "/etc/rc" },
799: { "-f", "/etc/rc.subr" },
800: { "-f", "/etc/rc.conf" },
1.14 jonathan 801: { "-d" "/dev" },
802: { "-c", "/dev/console" },
803: /* XXX check for rootdev in target /dev? */
804: { "-f", "/etc/fstab" },
805: { "-f", "/sbin/fsck" },
806: { "-f", "/sbin/fsck_ffs" },
807: { "-f", "/sbin/mount" },
808: { "-f", "/sbin/mount_ffs" },
809: { "-f", "/sbin/mount_nfs" },
1.20 jonathan 810: #if defined(DEBUG) || defined(DEBUG_CHECK)
811: { "-f", "/foo/bar" }, /* bad entry to exercise warning */
1.14 jonathan 812: #endif
813: { 0, 0 }
814:
815: };
816:
817: /*
818: * Check target for a single file.
819: */
1.29 mrg 820: static int
821: check_for(type, pathname)
822: const char *type;
823: const char *pathname;
1.14 jonathan 824: {
1.18 jonathan 825: int found;
1.14 jonathan 826:
1.18 jonathan 827: found = (target_test(type, pathname) == 0);
828: if (found == 0)
1.14 jonathan 829: msg_display(MSG_rootmissing, pathname);
1.18 jonathan 830: return found;
1.14 jonathan 831: }
832:
1.25 jonathan 833: /*
834: * Check that all the files in check_table are present in the
835: * target root. Warn if not found.
836: */
1.14 jonathan 837: int
838: sanity_check()
839: {
840: int target_ok = 1;
841: struct check_table *p;
842:
843: for (p = checks; p->path; p++) {
844: target_ok = target_ok && check_for(p->testarg, p->path);
845: }
846: if (target_ok)
847: return 0;
848:
849: /* Uh, oh. Something's missing. */
850: msg_display(MSG_badroot);
851: process_menu(MENU_ok);
852: return 1;
1.11 jonathan 853: }
1.32 garbled 854:
855: /* set reverse to 1 to default to no */
856: int askyesno(int reverse)
857: {
858: WINDOW *yesnowin;
859: int c, found;
860:
1.40 simonb 861: yesnowin = subwin(stdscr, 5, 20, getmaxy(stdscr)/2 - 2, getmaxx(stdscr)/2 - 10);
1.41 garbled 862: if (yesnowin == NULL) {
863: fprintf(stderr, "sysinst: failed to allocate yes/no box\n");
864: exit(1);
865: }
1.32 garbled 866: box(yesnowin, '*', '*');
867: wmove(yesnowin, 2,2);
868:
869: if (reverse)
870: waddstr(yesnowin, "Yes or No: [N]");
871: else
872: waddstr(yesnowin, "Yes or No: [Y]");
873:
874: wrefresh(yesnowin);
875: while ((c = getchar())) {
876: if (c == 'y' || c == 'Y') {
877: found = 1;
878: break;
879: } else if (c == 'n' || c == 'N' ) {
880: found = 0;
881: break;
882: } else if (c == '\n' || c == '\r') {
883: if (reverse)
884: found = 0;
885: else
886: found = 1;
887: break;
888: }
889: }
890: wclear(yesnowin);
891: wrefresh(yesnowin);
892: delwin(yesnowin);
893: refresh();
894: return(found);
895: }
CVSweb <webmaster@jp.NetBSD.org>