1 | /* Created by: Theodore Ts'o |
---|
2 | * |
---|
3 | * $Source: /afs/dev.mit.edu/source/repository/athena/bin/attach/ufs.c,v $ |
---|
4 | * $Author: vrt $ |
---|
5 | * |
---|
6 | * Copyright (c) 1988 by the Massachusetts Institute of Technology. |
---|
7 | */ |
---|
8 | |
---|
9 | #ifndef lint |
---|
10 | static char rcsid_ufs_c[] = "$Header: /afs/dev.mit.edu/source/repository/athena/bin/attach/ufs.c,v 1.4 1993-05-05 17:05:37 vrt Exp $"; |
---|
11 | #endif |
---|
12 | |
---|
13 | #include "attach.h" |
---|
14 | #include <sys/stat.h> |
---|
15 | #include <sys/wait.h> |
---|
16 | #include <sys/file.h> |
---|
17 | |
---|
18 | #ifdef UFS |
---|
19 | /* |
---|
20 | * Attach an Unix filesystem |
---|
21 | */ |
---|
22 | |
---|
23 | ufs_attach(at, mopt, errorout) |
---|
24 | struct _attachtab *at; |
---|
25 | struct mntopts *mopt; |
---|
26 | int errorout; |
---|
27 | { |
---|
28 | if (at->mode == 'w' && !skip_fsck) { |
---|
29 | if (perform_fsck(at->hostdir, at->hesiodname, 1) == FAILURE) |
---|
30 | return(FAILURE); |
---|
31 | } |
---|
32 | |
---|
33 | /* XXX This is kind of bogus, because if a filesystem has a number |
---|
34 | * of hesiod entries, and the mount point is busy, each one will |
---|
35 | * be tried until the last one fails, then an error printed. |
---|
36 | * C'est la vie. |
---|
37 | */ |
---|
38 | |
---|
39 | if (mountfs(at, at->hostdir, mopt, errorout) == FAILURE) { |
---|
40 | return (FAILURE); |
---|
41 | } |
---|
42 | |
---|
43 | return (SUCCESS); |
---|
44 | } |
---|
45 | |
---|
46 | /* |
---|
47 | * Detach a Unix filesystem |
---|
48 | */ |
---|
49 | ufs_detach(at) |
---|
50 | struct _attachtab *at; |
---|
51 | { |
---|
52 | if (at->flags & FLAG_PERMANENT) { |
---|
53 | if (debug_flag) |
---|
54 | printf("Permanent flag on, skipping umount.\n"); |
---|
55 | return(SUCCESS); |
---|
56 | } |
---|
57 | |
---|
58 | if (unmount_42(at->hesiodname, at->mntpt, at->hostdir) == FAILURE) |
---|
59 | return (FAILURE); |
---|
60 | |
---|
61 | return (SUCCESS); |
---|
62 | } |
---|
63 | #endif |
---|
64 | |
---|
65 | /* |
---|
66 | * Attach an "error" filesystem. |
---|
67 | * (Print an error message and go away; always fails) |
---|
68 | * Not strictly UFS, but it's a good place to sneak it in... |
---|
69 | */ |
---|
70 | err_attach(at, mopt, errorout) |
---|
71 | struct _attachtab *at; |
---|
72 | struct mntopts *mopt; |
---|
73 | int errorout; /* ignored */ |
---|
74 | { |
---|
75 | fprintf(stderr, "%s: error: %s\n", at->hesiodname, at->hostdir); |
---|
76 | return(FAILURE); |
---|
77 | } |
---|
78 | |
---|
79 | #if defined(UFS) || defined(RVD) |
---|
80 | /* |
---|
81 | * Subroutine to check a filesystem with fsck |
---|
82 | */ |
---|
83 | perform_fsck(device, errorname, useraw) |
---|
84 | char *device, *errorname; |
---|
85 | int useraw; |
---|
86 | { |
---|
87 | static char rdevice[512]; |
---|
88 | static char *fsck_av[4]; |
---|
89 | int error_ret, save_stderr; |
---|
90 | #ifdef POSIX |
---|
91 | int waitb; |
---|
92 | #else |
---|
93 | union wait waitb; |
---|
94 | #endif |
---|
95 | |
---|
96 | strncpy(rdevice, device, sizeof(rdevice)); |
---|
97 | |
---|
98 | /* Try to generate the raw device, since it's almost always faster */ |
---|
99 | if (useraw) { |
---|
100 | char *cpp, *cpp2; |
---|
101 | struct stat buf; |
---|
102 | |
---|
103 | if (!(cpp = rindex(rdevice, '/'))) |
---|
104 | cpp = rdevice; |
---|
105 | else |
---|
106 | cpp++; |
---|
107 | *cpp++ = 'r'; |
---|
108 | if (!(cpp2 = rindex(device, '/'))) |
---|
109 | cpp2 = device; |
---|
110 | else |
---|
111 | cpp2++; |
---|
112 | (void) strcpy(cpp, cpp2); |
---|
113 | |
---|
114 | /* |
---|
115 | * Try to stat the constructed rdevice. If it isn't a |
---|
116 | * device file or if it doesn't exist, give up and use |
---|
117 | * the original file. |
---|
118 | */ |
---|
119 | if (stat(rdevice,&buf) || !(buf.st_mode & (S_IFCHR|S_IFBLK))) |
---|
120 | strcpy(rdevice,device); |
---|
121 | } |
---|
122 | |
---|
123 | if (debug_flag) |
---|
124 | printf("performing an fsck on %s\n", rdevice); |
---|
125 | |
---|
126 | fsck_av[0] = FSCK_SHORTNAME; |
---|
127 | fsck_av[1] = "-p"; /* Preen option */ |
---|
128 | fsck_av[2] = rdevice; |
---|
129 | fsck_av[3] = NULL; |
---|
130 | switch(vfork()) { |
---|
131 | case -1: |
---|
132 | perror("vfork: to fsck"); |
---|
133 | error_status = ERR_ATTACHFSCK; |
---|
134 | return(FAILURE); |
---|
135 | case 0: |
---|
136 | if (!debug_flag) { |
---|
137 | save_stderr = dup(2); |
---|
138 | close(0); |
---|
139 | close(1); |
---|
140 | close(2); |
---|
141 | open("/dev/null", O_RDWR); |
---|
142 | dup(0); |
---|
143 | dup(0); |
---|
144 | } |
---|
145 | |
---|
146 | execv(FSCK_FULLNAME, fsck_av); |
---|
147 | if (!debug_flag) |
---|
148 | dup2(save_stderr, 2); |
---|
149 | perror(FSCK_FULLNAME); |
---|
150 | exit(1); |
---|
151 | /*NOTREACHED*/ |
---|
152 | default: |
---|
153 | if (wait(&waitb) < 0) { |
---|
154 | perror("wait: for fsck"); |
---|
155 | error_status = ERR_ATTACHFSCK; |
---|
156 | return(FAILURE); |
---|
157 | } |
---|
158 | } |
---|
159 | |
---|
160 | #ifdef POSIX |
---|
161 | if ((error_ret = WEXITSTATUS(waitb))) { |
---|
162 | #else |
---|
163 | if (error_ret = waitb.w_retcode) { |
---|
164 | #endif |
---|
165 | fprintf(stderr, |
---|
166 | "%s: fsck returned a bad exit status (%d)\n", |
---|
167 | errorname, error_ret); |
---|
168 | error_status = ERR_ATTACHFSCK; |
---|
169 | return (FAILURE); |
---|
170 | } |
---|
171 | return(SUCCESS); |
---|
172 | } |
---|
173 | |
---|
174 | /* |
---|
175 | * Parsing of explicit UFS file types |
---|
176 | */ |
---|
177 | char **ufs_explicit(name) |
---|
178 | char *name; |
---|
179 | { |
---|
180 | extern char *exp_hesptr[2]; |
---|
181 | |
---|
182 | sprintf(exp_hesline, "UFS %s %c %s", name, override_mode ? |
---|
183 | override_mode : 'w', mntpt ? mntpt : "/mnt"); |
---|
184 | exp_hesptr[0] = exp_hesline; |
---|
185 | exp_hesptr[1] = 0; |
---|
186 | return(exp_hesptr); |
---|
187 | } |
---|
188 | |
---|
189 | #endif |
---|