File: | src/sbin/fsdb/../../sbin/fsck_ffs/dir.c |
Warning: | line 397, column 3 Value stored to 'dp' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: dir.c,v 1.32 2015/01/20 18:22:21 deraadt Exp $ */ |
2 | /* $NetBSD: dir.c,v 1.20 1996/09/27 22:45:11 christos Exp $ */ |
3 | |
4 | /* |
5 | * Copyright (c) 1980, 1986, 1993 |
6 | * The Regents of the University of California. All rights reserved. |
7 | * |
8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions |
10 | * are met: |
11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. |
16 | * 3. Neither the name of the University nor the names of its contributors |
17 | * may be used to endorse or promote products derived from this software |
18 | * without specific prior written permission. |
19 | * |
20 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
30 | * SUCH DAMAGE. |
31 | */ |
32 | |
33 | #include <sys/param.h> /* DEV_BSIZE roundup btodb */ |
34 | #include <sys/time.h> |
35 | #include <ufs/ufs/dinode.h> |
36 | #include <ufs/ufs/dir.h> |
37 | #include <ufs/ffs/fs.h> |
38 | |
39 | #include <stdio.h> |
40 | #include <stdlib.h> |
41 | #include <string.h> |
42 | #include <limits.h> |
43 | |
44 | #include "fsck.h" |
45 | #include "fsutil.h" |
46 | #include "extern.h" |
47 | |
48 | char *lfname = "lost+found"; |
49 | int lfmode = 01700; |
50 | struct dirtemplate emptydir = { 0, DIRBLKSIZ(1 << 9) }; |
51 | struct dirtemplate dirhead = { |
52 | 0, 12, DT_DIR4, 1, ".", |
53 | 0, DIRBLKSIZ(1 << 9) - 12, DT_DIR4, 2, ".." |
54 | }; |
55 | struct odirtemplate odirhead = { |
56 | 0, 12, 1, ".", |
57 | 0, DIRBLKSIZ(1 << 9) - 12, 2, ".." |
58 | }; |
59 | |
60 | static int expanddir(union dinode *, char *); |
61 | static void freedir(ino_t, ino_t); |
62 | static struct direct *fsck_readdir(struct inodesc *); |
63 | static struct bufarea *getdirblk(daddr_t, long); |
64 | static int lftempname(char *, ino_t); |
65 | static int mkentry(struct inodesc *); |
66 | static int chgino(struct inodesc *); |
67 | |
68 | /* |
69 | * Propagate connected state through the tree. |
70 | */ |
71 | void |
72 | propagate(ino_t inumber) |
73 | { |
74 | struct inoinfo *inp; |
75 | char state; |
76 | |
77 | inp = getinoinfo(inumber); |
78 | state = GET_ISTATE(inp->i_number)(inoinfo(inp->i_number)->ino_state); |
79 | for (;;) { |
80 | SET_ISTATE(inp->i_number, state)do { (inoinfo(inp->i_number)->ino_state) = (state); } while (0); |
81 | if (inp->i_child && |
82 | GET_ISTATE(inp->i_child->i_number)(inoinfo(inp->i_child->i_number)->ino_state) != state) |
83 | inp = inp->i_child; |
84 | else if (inp->i_number == inumber) |
85 | break; |
86 | else if (inp->i_sibling) |
87 | inp = inp->i_sibling; |
88 | else |
89 | inp = getinoinfo(inp->i_parent); |
90 | } |
91 | } |
92 | |
93 | /* |
94 | * Scan each entry in a directory block. |
95 | */ |
96 | int |
97 | dirscan(struct inodesc *idesc) |
98 | { |
99 | struct direct *dp; |
100 | struct bufarea *bp; |
101 | int dsize, n; |
102 | long blksiz; |
103 | char dbuf[DIRBLKSIZ(1 << 9)]; |
104 | |
105 | if (idesc->id_type != DATA1) |
106 | errexit("wrong type to dirscan %d\n", idesc->id_type); |
107 | if (idesc->id_entryno == 0 && |
108 | (idesc->id_filesize & (DIRBLKSIZ(1 << 9) - 1)) != 0) |
109 | idesc->id_filesize = roundup(idesc->id_filesize, DIRBLKSIZ)((((idesc->id_filesize)+(((1 << 9))-1))/((1 << 9)))*((1 << 9))); |
110 | blksiz = idesc->id_numfrags * sblock(*sblk.b_un.b_fs).fs_fsize; |
111 | if (chkrange(idesc->id_blkno, idesc->id_numfrags)) { |
112 | idesc->id_filesize -= blksiz; |
113 | return (SKIP0x02); |
114 | } |
115 | idesc->id_loc = 0; |
116 | for (dp = fsck_readdir(idesc); dp != NULL((void *)0); dp = fsck_readdir(idesc)) { |
117 | dsize = dp->d_reclen; |
118 | memcpy(dbuf, dp, (size_t)dsize); |
119 | idesc->id_dirp = (struct direct *)dbuf; |
120 | if ((n = (*idesc->id_func)(idesc)) & ALTERED0x08) { |
121 | bp = getdirblk(idesc->id_blkno, blksiz); |
122 | memcpy(bp->b_un.b_buf + idesc->id_loc - dsize, dbuf, |
123 | (size_t)dsize); |
124 | dirty(bp)(bp)->b_dirty = 1; |
125 | sbdirty()sblk.b_dirty = 1; |
126 | } |
127 | if (n & STOP0x01) |
128 | return (n); |
129 | } |
130 | return (idesc->id_filesize > 0 ? KEEPON0x04 : STOP0x01); |
131 | } |
132 | |
133 | /* |
134 | * get next entry in a directory. |
135 | */ |
136 | static struct direct * |
137 | fsck_readdir(struct inodesc *idesc) |
138 | { |
139 | struct direct *dp, *ndp; |
140 | struct bufarea *bp; |
141 | long size, blksiz, fix, dploc; |
142 | |
143 | blksiz = idesc->id_numfrags * sblock(*sblk.b_un.b_fs).fs_fsize; |
144 | bp = getdirblk(idesc->id_blkno, blksiz); |
145 | if (idesc->id_loc % DIRBLKSIZ(1 << 9) == 0 && idesc->id_filesize > 0 && |
146 | idesc->id_loc < blksiz) { |
147 | dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc); |
148 | if (dircheck(idesc, dp)) |
149 | goto dpok; |
150 | if (idesc->id_fix == IGNORE) |
151 | return (0); |
152 | fix = dofix(idesc, "DIRECTORY CORRUPTED"); |
153 | bp = getdirblk(idesc->id_blkno, blksiz); |
154 | dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc); |
155 | dp->d_reclen = DIRBLKSIZ(1 << 9); |
156 | dp->d_ino = 0; |
157 | dp->d_type = 0; |
158 | dp->d_namlen = 0; |
159 | dp->d_name[0] = '\0'; |
160 | if (fix) |
161 | dirty(bp)(bp)->b_dirty = 1; |
162 | idesc->id_loc += DIRBLKSIZ(1 << 9); |
163 | idesc->id_filesize -= DIRBLKSIZ(1 << 9); |
164 | return (dp); |
165 | } |
166 | dpok: |
167 | if (idesc->id_filesize <= 0 || idesc->id_loc >= blksiz) |
168 | return NULL((void *)0); |
169 | dploc = idesc->id_loc; |
170 | dp = (struct direct *)(bp->b_un.b_buf + dploc); |
171 | idesc->id_loc += dp->d_reclen; |
172 | idesc->id_filesize -= dp->d_reclen; |
173 | if ((idesc->id_loc % DIRBLKSIZ(1 << 9)) == 0) |
174 | return (dp); |
175 | ndp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc); |
176 | if (idesc->id_loc < blksiz && idesc->id_filesize > 0 && |
177 | dircheck(idesc, ndp) == 0) { |
178 | size = DIRBLKSIZ(1 << 9) - (idesc->id_loc % DIRBLKSIZ(1 << 9)); |
179 | idesc->id_loc += size; |
180 | idesc->id_filesize -= size; |
181 | if (idesc->id_fix == IGNORE) |
182 | return (0); |
183 | fix = dofix(idesc, "DIRECTORY CORRUPTED"); |
184 | bp = getdirblk(idesc->id_blkno, blksiz); |
185 | dp = (struct direct *)(bp->b_un.b_buf + dploc); |
186 | dp->d_reclen += size; |
187 | if (fix) |
188 | dirty(bp)(bp)->b_dirty = 1; |
189 | } |
190 | return (dp); |
191 | } |
192 | |
193 | /* |
194 | * Verify that a directory entry is valid. |
195 | * This is a superset of the checks made in the kernel. |
196 | */ |
197 | int |
198 | dircheck(struct inodesc *idesc, struct direct *dp) |
199 | { |
200 | int size; |
201 | char *cp; |
202 | u_char namlen, type; |
203 | int spaceleft; |
204 | |
205 | spaceleft = DIRBLKSIZ(1 << 9) - (idesc->id_loc % DIRBLKSIZ(1 << 9)); |
206 | if (dp->d_ino >= maxino || |
207 | dp->d_reclen == 0 || |
208 | dp->d_reclen > spaceleft || |
209 | (dp->d_reclen & 0x3) != 0) |
210 | return (0); |
211 | if (dp->d_ino == 0) |
212 | return (1); |
213 | size = DIRSIZ(0, dp)((0) ? ((sizeof(struct direct) - (255 +1)) + (((dp)->d_type +1 + 3) &~ 3)) : ((sizeof(struct direct) - (255 +1)) + (( (dp)->d_namlen+1 + 3) &~ 3))); |
214 | namlen = dp->d_namlen; |
215 | type = dp->d_type; |
216 | if (dp->d_reclen < size || |
217 | idesc->id_filesize < size || |
218 | type > 15) |
219 | return (0); |
220 | for (cp = dp->d_name, size = 0; size < namlen; size++) |
221 | if (*cp == '\0' || (*cp++ == '/')) |
222 | return (0); |
223 | if (*cp != '\0') |
224 | return (0); |
225 | return (1); |
226 | } |
227 | |
228 | void |
229 | direrror(ino_t ino, char *errmesg) |
230 | { |
231 | fileerror(ino, ino, errmesg); |
232 | } |
233 | |
234 | void |
235 | fileerror(ino_t cwd, ino_t ino, char *errmesg) |
236 | { |
237 | union dinode *dp; |
238 | char pathbuf[PATH_MAX1024 + 1]; |
239 | |
240 | pwarn("%s ", errmesg); |
241 | pinode(ino); |
242 | printf("\n"); |
243 | getpathname(pathbuf, sizeof pathbuf, cwd, ino); |
244 | if (ino < ROOTINO((ufsino_t)2) || ino > maxino) { |
245 | pfatal("NAME=%s\n", pathbuf); |
246 | return; |
247 | } |
248 | dp = ginode(ino); |
249 | if (ftypeok(dp)) |
250 | pfatal("%s=%s\n", |
251 | (DIP(dp, di_mode)(((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)->dp1.di_mode : (dp)->dp2.di_mode) & IFMT0170000) == IFDIR0040000 ? "DIR" : "FILE", |
252 | pathbuf); |
253 | else |
254 | pfatal("NAME=%s\n", pathbuf); |
255 | } |
256 | |
257 | void |
258 | adjust(struct inodesc *idesc, short lcnt) |
259 | { |
260 | union dinode *dp; |
261 | |
262 | dp = ginode(idesc->id_number); |
263 | if (DIP(dp, di_nlink)(((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)->dp1.di_nlink : (dp)->dp2.di_nlink) == lcnt) { |
264 | if (linkup(idesc->id_number, 0) == 0) |
265 | clri(idesc, "UNREF", 0); |
266 | } else { |
267 | pwarn("LINK COUNT %s", (lfdir == idesc->id_number) ? lfname : |
268 | ((DIP(dp, di_mode)(((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)->dp1.di_mode : (dp)->dp2.di_mode) & IFMT0170000) == IFDIR0040000 ? "DIR" : "FILE")); |
269 | pinode(idesc->id_number); |
270 | printf(" COUNT %d SHOULD BE %d", DIP(dp, di_nlink)(((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)->dp1.di_nlink : (dp)->dp2.di_nlink), |
271 | DIP(dp, di_nlink)(((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)->dp1.di_nlink : (dp)->dp2.di_nlink) - lcnt); |
272 | if (preen || usedsoftdep) { |
273 | if (lcnt < 0) { |
274 | printf("\n"); |
275 | pfatal("LINK COUNT INCREASING"); |
276 | } |
277 | if (preen) |
278 | printf(" (ADJUSTED)\n"); |
279 | } |
280 | if (preen || reply("ADJUST") == 1) { |
281 | DIP_SET(dp, di_nlink, DIP(dp, di_nlink) - lcnt)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (dp)->dp1 .di_nlink = ((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp) ->dp1.di_nlink : (dp)->dp2.di_nlink) - lcnt); else (dp) ->dp2.di_nlink = ((((*sblk.b_un.b_fs).fs_magic == 0x011954 ) ? (dp)->dp1.di_nlink : (dp)->dp2.di_nlink) - lcnt); } while (0); |
282 | inodirty(); |
283 | } |
284 | } |
285 | } |
286 | |
287 | static int |
288 | mkentry(struct inodesc *idesc) |
289 | { |
290 | struct direct *dirp = idesc->id_dirp; |
291 | struct direct newent; |
292 | int newlen, oldlen; |
293 | |
294 | newent.d_namlen = strlen(idesc->id_name); |
295 | newlen = DIRSIZ(0, &newent)((0) ? ((sizeof(struct direct) - (255 +1)) + (((&newent)-> d_type+1 + 3) &~ 3)) : ((sizeof(struct direct) - (255 +1) ) + (((&newent)->d_namlen+1 + 3) &~ 3))); |
296 | if (dirp->d_ino != 0) |
297 | oldlen = DIRSIZ(0, dirp)((0) ? ((sizeof(struct direct) - (255 +1)) + (((dirp)->d_type +1 + 3) &~ 3)) : ((sizeof(struct direct) - (255 +1)) + (( (dirp)->d_namlen+1 + 3) &~ 3))); |
298 | else |
299 | oldlen = 0; |
300 | if (dirp->d_reclen - oldlen < newlen) |
301 | return (KEEPON0x04); |
302 | newent.d_reclen = dirp->d_reclen - oldlen; |
303 | dirp->d_reclen = oldlen; |
304 | dirp = (struct direct *)(((char *)dirp) + oldlen); |
305 | dirp->d_ino = idesc->id_parent; /* ino to be entered is in id_parent */ |
306 | dirp->d_reclen = newent.d_reclen; |
307 | dirp->d_type = GET_ITYPE(idesc->id_parent)(inoinfo(idesc->id_parent)->ino_type); |
308 | dirp->d_namlen = newent.d_namlen; |
309 | memcpy(dirp->d_name, idesc->id_name, (size_t)dirp->d_namlen + 1); |
310 | return (ALTERED0x08|STOP0x01); |
311 | } |
312 | |
313 | static int |
314 | chgino(struct inodesc *idesc) |
315 | { |
316 | struct direct *dirp = idesc->id_dirp; |
317 | |
318 | if (memcmp(dirp->d_name, idesc->id_name, (int)dirp->d_namlen + 1)) |
319 | return (KEEPON0x04); |
320 | dirp->d_ino = idesc->id_parent; |
321 | dirp->d_type = GET_ITYPE(idesc->id_parent)(inoinfo(idesc->id_parent)->ino_type); |
322 | return (ALTERED0x08|STOP0x01); |
323 | } |
324 | |
325 | int |
326 | linkup(ino_t orphan, ino_t parentdir) |
327 | { |
328 | union dinode *dp; |
329 | int lostdir; |
330 | ino_t oldlfdir; |
331 | struct inodesc idesc; |
332 | char tempname[BUFSIZ1024]; |
333 | |
334 | memset(&idesc, 0, sizeof(struct inodesc)); |
335 | dp = ginode(orphan); |
336 | lostdir = (DIP(dp, di_mode)(((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)->dp1.di_mode : (dp)->dp2.di_mode) & IFMT0170000) == IFDIR0040000; |
337 | pwarn("UNREF %s ", lostdir ? "DIR" : "FILE"); |
338 | pinode(orphan); |
339 | if ((preen || usedsoftdep) && DIP(dp, di_size)(((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)->dp1.di_size : (dp)->dp2.di_size) == 0) |
340 | return (0); |
341 | if (preen) |
342 | printf(" (RECONNECTED)\n"); |
343 | else |
344 | if (reply("RECONNECT") == 0) |
345 | return (0); |
346 | if (lfdir == 0) { |
347 | dp = ginode(ROOTINO((ufsino_t)2)); |
348 | idesc.id_name = lfname; |
349 | idesc.id_type = DATA1; |
350 | idesc.id_func = findino; |
351 | idesc.id_number = ROOTINO((ufsino_t)2); |
352 | if ((ckinode(dp, &idesc) & FOUND0x10) != 0) { |
353 | lfdir = idesc.id_parent; |
354 | } else { |
355 | pwarn("NO lost+found DIRECTORY"); |
356 | if (preen || reply("CREATE")) { |
357 | lfdir = allocdir(ROOTINO((ufsino_t)2), 0, lfmode); |
358 | if (lfdir != 0) { |
359 | if (makeentry(ROOTINO((ufsino_t)2), lfdir, lfname) != 0) { |
360 | if (preen) |
361 | printf(" (CREATED)\n"); |
362 | } else { |
363 | freedir(lfdir, ROOTINO((ufsino_t)2)); |
364 | lfdir = 0; |
365 | if (preen) |
366 | printf("\n"); |
367 | } |
368 | } |
369 | } |
370 | } |
371 | if (lfdir == 0) { |
372 | pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY"); |
373 | printf("\n\n"); |
374 | return (0); |
375 | } |
376 | } |
377 | dp = ginode(lfdir); |
378 | if ((DIP(dp, di_mode)(((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)->dp1.di_mode : (dp)->dp2.di_mode) & IFMT0170000) != IFDIR0040000) { |
379 | pfatal("lost+found IS NOT A DIRECTORY"); |
380 | if (reply("REALLOCATE") == 0) |
381 | return (0); |
382 | oldlfdir = lfdir; |
383 | if ((lfdir = allocdir(ROOTINO((ufsino_t)2), 0, lfmode)) == 0) { |
384 | pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n"); |
385 | return (0); |
386 | } |
387 | if ((changeino(ROOTINO((ufsino_t)2), lfname, lfdir) & ALTERED0x08) == 0) { |
388 | pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n"); |
389 | return (0); |
390 | } |
391 | inodirty(); |
392 | idesc.id_type = ADDR2; |
393 | idesc.id_func = pass4check; |
394 | idesc.id_number = oldlfdir; |
395 | adjust(&idesc, ILNCOUNT(oldlfdir)(inoinfo(oldlfdir)->ino_linkcnt) + 1); |
396 | ILNCOUNT(oldlfdir)(inoinfo(oldlfdir)->ino_linkcnt) = 0; |
397 | dp = ginode(lfdir); |
Value stored to 'dp' is never read | |
398 | } |
399 | if (GET_ISTATE(lfdir)(inoinfo(lfdir)->ino_state) != DFOUND04) { |
400 | pfatal("SORRY. NO lost+found DIRECTORY\n\n"); |
401 | return (0); |
402 | } |
403 | (void)lftempname(tempname, orphan); |
404 | if (makeentry(lfdir, orphan, tempname) == 0) { |
405 | pfatal("SORRY. NO SPACE IN lost+found DIRECTORY"); |
406 | printf("\n\n"); |
407 | return (0); |
408 | } |
409 | ILNCOUNT(orphan)(inoinfo(orphan)->ino_linkcnt)--; |
410 | if (lostdir) { |
411 | if ((changeino(orphan, "..", lfdir) & ALTERED0x08) == 0 && |
412 | parentdir != (ino_t)-1) |
413 | (void)makeentry(orphan, lfdir, ".."); |
414 | dp = ginode(lfdir); |
415 | DIP_SET(dp, di_nlink, DIP(dp, di_nlink) + 1)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (dp)->dp1 .di_nlink = ((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp) ->dp1.di_nlink : (dp)->dp2.di_nlink) + 1); else (dp)-> dp2.di_nlink = ((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? ( dp)->dp1.di_nlink : (dp)->dp2.di_nlink) + 1); } while ( 0); |
416 | inodirty(); |
417 | ILNCOUNT(lfdir)(inoinfo(lfdir)->ino_linkcnt)++; |
418 | pwarn("DIR I=%llu CONNECTED. ", |
419 | (unsigned long long)orphan); |
420 | if (parentdir != (ino_t)-1) { |
421 | printf("PARENT WAS I=%llu\n", |
422 | (unsigned long long)parentdir); |
423 | /* |
424 | * The parent directory, because of the ordering |
425 | * guarantees, has had the link count incremented |
426 | * for the child, but no entry was made. This |
427 | * fixes the parent link count so that fsck does |
428 | * not need to be rerun. |
429 | */ |
430 | ILNCOUNT(parentdir)(inoinfo(parentdir)->ino_linkcnt)++; |
431 | } |
432 | if (preen == 0) |
433 | printf("\n"); |
434 | } |
435 | return (1); |
436 | } |
437 | |
438 | /* |
439 | * fix an entry in a directory. |
440 | */ |
441 | int |
442 | changeino(dir, name, newnum) |
443 | ino_t dir; |
444 | char *name; |
445 | ino_t newnum; |
446 | { |
447 | struct inodesc idesc; |
448 | |
449 | memset(&idesc, 0, sizeof(struct inodesc)); |
450 | idesc.id_type = DATA1; |
451 | idesc.id_func = chgino; |
452 | idesc.id_number = dir; |
453 | idesc.id_fix = DONTKNOW; |
454 | idesc.id_name = name; |
455 | idesc.id_parent = newnum; /* new value for name */ |
456 | return (ckinode(ginode(dir), &idesc)); |
457 | } |
458 | |
459 | /* |
460 | * make an entry in a directory |
461 | */ |
462 | int |
463 | makeentry(ino_t parent, ino_t ino, char *name) |
464 | { |
465 | union dinode *dp; |
466 | struct inodesc idesc; |
467 | char pathbuf[PATH_MAX1024 + 1]; |
468 | |
469 | if (parent < ROOTINO((ufsino_t)2) || parent >= maxino || |
470 | ino < ROOTINO((ufsino_t)2) || ino >= maxino) |
471 | return (0); |
472 | memset(&idesc, 0, sizeof(struct inodesc)); |
473 | idesc.id_type = DATA1; |
474 | idesc.id_func = mkentry; |
475 | idesc.id_number = parent; |
476 | idesc.id_parent = ino; /* this is the inode to enter */ |
477 | idesc.id_fix = DONTKNOW; |
478 | idesc.id_name = name; |
479 | dp = ginode(parent); |
480 | if (DIP(dp, di_size)(((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)->dp1.di_size : (dp)->dp2.di_size) % DIRBLKSIZ(1 << 9)) { |
481 | DIP_SET(dp, di_size, roundup(DIP(dp, di_size), DIRBLKSIZ))do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (dp)->dp1 .di_size = ((((((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? ( dp)->dp1.di_size : (dp)->dp2.di_size))+(((1 << 9) )-1))/((1 << 9)))*((1 << 9)))); else (dp)->dp2 .di_size = ((((((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? ( dp)->dp1.di_size : (dp)->dp2.di_size))+(((1 << 9) )-1))/((1 << 9)))*((1 << 9)))); } while (0); |
482 | inodirty(); |
483 | } |
484 | if ((ckinode(dp, &idesc) & ALTERED0x08) != 0) |
485 | return (1); |
486 | getpathname(pathbuf, sizeof pathbuf, parent, parent); |
487 | dp = ginode(parent); |
488 | if (expanddir(dp, pathbuf) == 0) |
489 | return (0); |
490 | return (ckinode(dp, &idesc) & ALTERED0x08); |
491 | } |
492 | |
493 | /* |
494 | * Attempt to expand the size of a directory |
495 | */ |
496 | static int |
497 | expanddir(union dinode *dp, char *name) |
498 | { |
499 | daddr_t lastbn, newblk; |
500 | struct bufarea *bp; |
501 | char *cp, firstblk[DIRBLKSIZ(1 << 9)]; |
502 | u_int64_t dis; |
503 | |
504 | dis = lblkno(&sblock, DIP(dp, di_size))(((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)->dp1.di_size : (dp)->dp2.di_size)) >> (&(*sblk.b_un.b_fs))-> fs_bshift); |
505 | if (dis > (u_int64_t)INT_MAX2147483647) |
506 | return (0); |
507 | lastbn = dis; |
508 | if (lastbn >= NDADDR12 - 1 || DIP(dp, di_db[lastbn])(((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)->dp1.di_db [lastbn] : (dp)->dp2.di_db[lastbn]) == 0 || |
509 | DIP(dp, di_size)(((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)->dp1.di_size : (dp)->dp2.di_size) == 0) |
510 | return (0); |
511 | if ((newblk = allocblk(sblock(*sblk.b_un.b_fs).fs_frag)) == 0) |
512 | return (0); |
513 | DIP_SET(dp, di_db[lastbn + 1], DIP(dp, di_db[lastbn]))do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (dp)->dp1 .di_db[lastbn + 1] = ((((*sblk.b_un.b_fs).fs_magic == 0x011954 ) ? (dp)->dp1.di_db[lastbn] : (dp)->dp2.di_db[lastbn])) ; else (dp)->dp2.di_db[lastbn + 1] = ((((*sblk.b_un.b_fs). fs_magic == 0x011954) ? (dp)->dp1.di_db[lastbn] : (dp)-> dp2.di_db[lastbn])); } while (0); |
514 | DIP_SET(dp, di_db[lastbn], newblk)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (dp)->dp1 .di_db[lastbn] = (newblk); else (dp)->dp2.di_db[lastbn] = ( newblk); } while (0); |
515 | DIP_SET(dp, di_size, DIP(dp, di_size) + sblock.fs_bsize)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (dp)->dp1 .di_size = ((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)-> dp1.di_size : (dp)->dp2.di_size) + (*sblk.b_un.b_fs).fs_bsize ); else (dp)->dp2.di_size = ((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)->dp1.di_size : (dp)->dp2.di_size) + ( *sblk.b_un.b_fs).fs_bsize); } while (0); |
516 | DIP_SET(dp, di_blocks, DIP(dp, di_blocks) + btodb(sblock.fs_bsize))do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (dp)->dp1 .di_blocks = ((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp )->dp1.di_blocks : (dp)->dp2.di_blocks) + (((*sblk.b_un .b_fs).fs_bsize) >> 9)); else (dp)->dp2.di_blocks = ( (((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)->dp1.di_blocks : (dp)->dp2.di_blocks) + (((*sblk.b_un.b_fs).fs_bsize) >> 9)); } while (0); |
517 | bp = getdirblk(DIP(dp, di_db[lastbn + 1])(((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)->dp1.di_db [lastbn + 1] : (dp)->dp2.di_db[lastbn + 1]), |
518 | sblksize(&sblock, DIP(dp, di_size), lastbn + 1)(((lastbn + 1) >= 12 || ((((*sblk.b_un.b_fs).fs_magic == 0x011954 ) ? (dp)->dp1.di_size : (dp)->dp2.di_size)) >= ((lastbn + 1) + 1) << (&(*sblk.b_un.b_fs))->fs_bshift) ? (u_int64_t)(&(*sblk.b_un.b_fs))->fs_bsize : ((((((((( (*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)->dp1.di_size : (dp)->dp2.di_size))) & (&(*sblk.b_un.b_fs))-> fs_qbmask)) + (&(*sblk.b_un.b_fs))->fs_qfmask) & ( &(*sblk.b_un.b_fs))->fs_fmask)))); |
519 | if (bp->b_errs) |
520 | goto bad; |
521 | memcpy(firstblk, bp->b_un.b_buf, DIRBLKSIZ(1 << 9)); |
522 | bp = getdirblk(newblk, sblock(*sblk.b_un.b_fs).fs_bsize); |
523 | if (bp->b_errs) |
524 | goto bad; |
525 | memcpy(bp->b_un.b_buf, firstblk, DIRBLKSIZ(1 << 9)); |
526 | for (cp = &bp->b_un.b_buf[DIRBLKSIZ(1 << 9)]; |
527 | cp < &bp->b_un.b_buf[sblock(*sblk.b_un.b_fs).fs_bsize]; |
528 | cp += DIRBLKSIZ(1 << 9)) |
529 | memcpy(cp, &emptydir, sizeof emptydir); |
530 | dirty(bp)(bp)->b_dirty = 1; |
531 | bp = getdirblk(DIP(dp, di_db[lastbn + 1])(((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)->dp1.di_db [lastbn + 1] : (dp)->dp2.di_db[lastbn + 1]), |
532 | sblksize(&sblock, DIP(dp, di_size), lastbn + 1)(((lastbn + 1) >= 12 || ((((*sblk.b_un.b_fs).fs_magic == 0x011954 ) ? (dp)->dp1.di_size : (dp)->dp2.di_size)) >= ((lastbn + 1) + 1) << (&(*sblk.b_un.b_fs))->fs_bshift) ? (u_int64_t)(&(*sblk.b_un.b_fs))->fs_bsize : ((((((((( (*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)->dp1.di_size : (dp)->dp2.di_size))) & (&(*sblk.b_un.b_fs))-> fs_qbmask)) + (&(*sblk.b_un.b_fs))->fs_qfmask) & ( &(*sblk.b_un.b_fs))->fs_fmask)))); |
533 | if (bp->b_errs) |
534 | goto bad; |
535 | memcpy(bp->b_un.b_buf, &emptydir, sizeof emptydir); |
536 | pwarn("NO SPACE LEFT IN %s", name); |
537 | if (preen) |
538 | printf(" (EXPANDED)\n"); |
539 | else if (reply("EXPAND") == 0) |
540 | goto bad; |
541 | dirty(bp)(bp)->b_dirty = 1; |
542 | inodirty(); |
543 | return (1); |
544 | bad: |
545 | DIP_SET(dp, di_db[lastbn], DIP(dp, di_db[lastbn + 1]))do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (dp)->dp1 .di_db[lastbn] = ((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)->dp1.di_db[lastbn + 1] : (dp)->dp2.di_db[lastbn + 1])); else (dp)->dp2.di_db[lastbn] = ((((*sblk.b_un.b_fs) .fs_magic == 0x011954) ? (dp)->dp1.di_db[lastbn + 1] : (dp )->dp2.di_db[lastbn + 1])); } while (0); |
546 | DIP_SET(dp, di_db[lastbn + 1], 0)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (dp)->dp1 .di_db[lastbn + 1] = (0); else (dp)->dp2.di_db[lastbn + 1] = (0); } while (0); |
547 | DIP_SET(dp, di_size, DIP(dp, di_size) - sblock.fs_bsize)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (dp)->dp1 .di_size = ((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)-> dp1.di_size : (dp)->dp2.di_size) - (*sblk.b_un.b_fs).fs_bsize ); else (dp)->dp2.di_size = ((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)->dp1.di_size : (dp)->dp2.di_size) - ( *sblk.b_un.b_fs).fs_bsize); } while (0); |
548 | DIP_SET(dp, di_blocks, DIP(dp, di_blocks) - btodb(sblock.fs_bsize))do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (dp)->dp1 .di_blocks = ((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp )->dp1.di_blocks : (dp)->dp2.di_blocks) - (((*sblk.b_un .b_fs).fs_bsize) >> 9)); else (dp)->dp2.di_blocks = ( (((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)->dp1.di_blocks : (dp)->dp2.di_blocks) - (((*sblk.b_un.b_fs).fs_bsize) >> 9)); } while (0); |
549 | freeblk(newblk, sblock(*sblk.b_un.b_fs).fs_frag); |
550 | return (0); |
551 | } |
552 | |
553 | /* |
554 | * allocate a new directory |
555 | */ |
556 | ino_t |
557 | allocdir(ino_t parent, ino_t request, int mode) |
558 | { |
559 | ino_t ino; |
560 | uid_t uid; |
561 | gid_t gid; |
562 | char *cp; |
563 | union dinode *dp; |
564 | struct bufarea *bp; |
565 | struct dirtemplate *dirp; |
566 | struct inoinfo *inp; |
567 | |
568 | ino = allocino(request, IFDIR0040000|mode); |
569 | dirp = &dirhead; |
570 | dirp->dot_ino = ino; |
571 | dirp->dotdot_ino = parent; |
572 | dp = ginode(ino); |
573 | bp = getdirblk(DIP(dp, di_db[0])(((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)->dp1.di_db [0] : (dp)->dp2.di_db[0]), sblock(*sblk.b_un.b_fs).fs_fsize); |
574 | if (bp->b_errs) { |
575 | freeino(ino); |
576 | return (0); |
577 | } |
578 | memcpy(bp->b_un.b_buf, dirp, sizeof(struct dirtemplate)); |
579 | for (cp = &bp->b_un.b_buf[DIRBLKSIZ(1 << 9)]; |
580 | cp < &bp->b_un.b_buf[sblock(*sblk.b_un.b_fs).fs_fsize]; |
581 | cp += DIRBLKSIZ(1 << 9)) |
582 | memcpy(cp, &emptydir, sizeof emptydir); |
583 | dirty(bp)(bp)->b_dirty = 1; |
584 | DIP_SET(dp, di_nlink, 2)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (dp)->dp1 .di_nlink = (2); else (dp)->dp2.di_nlink = (2); } while (0 ); |
585 | inodirty(); |
586 | if (ino == ROOTINO((ufsino_t)2)) { |
587 | ILNCOUNT(ino)(inoinfo(ino)->ino_linkcnt) = DIP(dp, di_nlink)(((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)->dp1.di_nlink : (dp)->dp2.di_nlink); |
588 | cacheino(dp, ino); |
589 | return(ino); |
590 | } |
591 | if (GET_ISTATE(parent)(inoinfo(parent)->ino_state) != DSTATE03 && GET_ISTATE(parent)(inoinfo(parent)->ino_state) != DFOUND04) { |
592 | freeino(ino); |
593 | return (0); |
594 | } |
595 | cacheino(dp, ino); |
596 | inp = getinoinfo(ino); |
597 | inp->i_parent = parent; |
598 | inp->i_dotdot = parent; |
599 | SET_ISTATE(ino, GET_ISTATE(parent))do { (inoinfo(ino)->ino_state) = ((inoinfo(parent)->ino_state )); } while (0); |
600 | if (GET_ISTATE(ino)(inoinfo(ino)->ino_state) == DSTATE03) { |
601 | ILNCOUNT(ino)(inoinfo(ino)->ino_linkcnt) = DIP(dp, di_nlink)(((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)->dp1.di_nlink : (dp)->dp2.di_nlink); |
602 | ILNCOUNT(parent)(inoinfo(parent)->ino_linkcnt)++; |
603 | } |
604 | dp = ginode(parent); |
605 | DIP_SET(dp, di_nlink, DIP(dp, di_nlink) + 1)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (dp)->dp1 .di_nlink = ((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp) ->dp1.di_nlink : (dp)->dp2.di_nlink) + 1); else (dp)-> dp2.di_nlink = ((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? ( dp)->dp1.di_nlink : (dp)->dp2.di_nlink) + 1); } while ( 0); |
606 | uid = DIP(dp, di_uid)(((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)->dp1.di_uid : (dp)->dp2.di_uid); |
607 | gid = DIP(dp, di_gid)(((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp)->dp1.di_gid : (dp)->dp2.di_gid); |
608 | inodirty(); |
609 | dp = ginode(ino); |
610 | DIP_SET(dp, di_uid, uid)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (dp)->dp1 .di_uid = (uid); else (dp)->dp2.di_uid = (uid); } while (0 ); |
611 | DIP_SET(dp, di_gid, gid)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (dp)->dp1 .di_gid = (gid); else (dp)->dp2.di_gid = (gid); } while (0 ); |
612 | inodirty(); |
613 | return (ino); |
614 | } |
615 | |
616 | /* |
617 | * free a directory inode |
618 | */ |
619 | static void |
620 | freedir(ino_t ino, ino_t parent) |
621 | { |
622 | union dinode *dp; |
623 | |
624 | if (ino != parent) { |
625 | dp = ginode(parent); |
626 | DIP_SET(dp, di_nlink, DIP(dp, di_nlink) - 1)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (dp)->dp1 .di_nlink = ((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (dp) ->dp1.di_nlink : (dp)->dp2.di_nlink) - 1); else (dp)-> dp2.di_nlink = ((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? ( dp)->dp1.di_nlink : (dp)->dp2.di_nlink) - 1); } while ( 0); |
627 | inodirty(); |
628 | } |
629 | freeino(ino); |
630 | } |
631 | |
632 | /* |
633 | * generate a temporary name for the lost+found directory. |
634 | */ |
635 | static int |
636 | lftempname(char *bufp, ino_t ino) |
637 | { |
638 | ino_t in; |
639 | char *cp; |
640 | int namlen; |
641 | |
642 | cp = bufp + 2; |
643 | for (in = maxino; in > 0; in /= 10) |
644 | cp++; |
645 | *--cp = 0; |
646 | namlen = cp - bufp; |
647 | in = ino; |
648 | while (cp > bufp) { |
649 | *--cp = (in % 10) + '0'; |
650 | in /= 10; |
651 | } |
652 | *cp = '#'; |
653 | return (namlen); |
654 | } |
655 | |
656 | /* |
657 | * Get a directory block. |
658 | * Insure that it is held until another is requested. |
659 | */ |
660 | static struct bufarea * |
661 | getdirblk(daddr_t blkno, long size) |
662 | { |
663 | |
664 | if (pdirbp != 0) |
665 | pdirbp->b_flags &= ~B_INUSE1; |
666 | pdirbp = getdatablk(blkno, size); |
667 | return (pdirbp); |
668 | } |