]>
Commit | Line | Data |
---|---|---|
2bd0ea18 | 1 | /* |
da23017d NS |
2 | * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | |
9f064b7e | 4 | * |
da23017d NS |
5 | * This program is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU General Public License as | |
2bd0ea18 | 7 | * published by the Free Software Foundation. |
9f064b7e | 8 | * |
da23017d NS |
9 | * This program is distributed in the hope that it would be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
9f064b7e | 13 | * |
da23017d NS |
14 | * You should have received a copy of the GNU General Public License |
15 | * along with this program; if not, write the Free Software Foundation, | |
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
2bd0ea18 NS |
17 | */ |
18 | ||
6b803e5a | 19 | #include "libxfs.h" |
33a12367 | 20 | #include <sys/stat.h> |
4a32b9e9 | 21 | #include "xfs_multidisk.h" |
2bd0ea18 NS |
22 | |
23 | /* | |
24 | * Prototypes for internal functions. | |
25 | */ | |
2bd0ea18 NS |
26 | static char *getstr(char **pp); |
27 | static void fail(char *msg, int i); | |
9074815c | 28 | static struct xfs_trans * getres(struct xfs_mount *mp, uint blocks); |
2bd0ea18 | 29 | static void rsvfile(xfs_mount_t *mp, xfs_inode_t *ip, long long len); |
f33cea1a | 30 | static int newfile(xfs_trans_t *tp, xfs_inode_t *ip, struct xfs_defer_ops *dfops, |
2bd0ea18 | 31 | xfs_fsblock_t *first, int dolocal, int logit, char *buf, int len); |
9f064b7e | 32 | static char *newregfile(char **pp, int *len); |
2bd0ea18 NS |
33 | static void rtinit(xfs_mount_t *mp); |
34 | static long filesize(int fd); | |
35 | ||
36 | /* | |
37 | * Use this for block reservations needed for mkfs's conditions | |
38 | * (basically no fragmentation). | |
39 | */ | |
40 | #define MKFS_BLOCKRES_INODE \ | |
ff105f75 | 41 | ((uint)(mp->m_ialloc_blks + (mp->m_in_maxlevels - 1))) |
2bd0ea18 NS |
42 | #define MKFS_BLOCKRES(rb) \ |
43 | ((uint)(MKFS_BLOCKRES_INODE + XFS_DA_NODE_MAXDEPTH + \ | |
44 | (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1) + (rb))) | |
45 | ||
6c855628 DC |
46 | static long long |
47 | getnum( | |
48 | const char *str, | |
49 | unsigned int blksize, | |
50 | unsigned int sectsize, | |
51 | bool convert) | |
52 | { | |
53 | long long i; | |
54 | char *sp; | |
55 | ||
56 | if (convert) | |
57 | return cvtnum(blksize, sectsize, str); | |
58 | ||
59 | i = strtoll(str, &sp, 0); | |
60 | if (i == 0 && sp == str) | |
61 | return -1LL; | |
62 | if (*sp != '\0') | |
63 | return -1LL; /* trailing garbage */ | |
64 | return i; | |
65 | } | |
2bd0ea18 NS |
66 | |
67 | char * | |
68 | setup_proto( | |
69 | char *fname) | |
70 | { | |
355ac015 | 71 | char *buf = NULL; |
2bd0ea18 NS |
72 | static char dflt[] = "d--755 0 0 $"; |
73 | int fd; | |
74 | long size; | |
75 | ||
76 | if (!fname) | |
77 | return dflt; | |
78 | if ((fd = open(fname, O_RDONLY)) < 0 || (size = filesize(fd)) < 0) { | |
9440d84d | 79 | fprintf(stderr, _("%s: failed to open %s: %s\n"), |
2bd0ea18 | 80 | progname, fname, strerror(errno)); |
11e06961 | 81 | goto out_fail; |
2bd0ea18 | 82 | } |
11e06961 | 83 | |
2bd0ea18 NS |
84 | buf = malloc(size + 1); |
85 | if (read(fd, buf, size) < size) { | |
9440d84d | 86 | fprintf(stderr, _("%s: read failed on %s: %s\n"), |
2bd0ea18 | 87 | progname, fname, strerror(errno)); |
11e06961 | 88 | goto out_fail; |
2bd0ea18 NS |
89 | } |
90 | if (buf[size - 1] != '\n') { | |
9440d84d | 91 | fprintf(stderr, _("%s: proto file %s premature EOF\n"), |
2bd0ea18 | 92 | progname, fname); |
11e06961 | 93 | goto out_fail; |
2bd0ea18 NS |
94 | } |
95 | buf[size] = '\0'; | |
96 | /* | |
97 | * Skip past the stuff there for compatibility, a string and 2 numbers. | |
98 | */ | |
99 | (void)getstr(&buf); /* boot image name */ | |
a887c950 DC |
100 | (void)getnum(getstr(&buf), 0, 0, false); /* block count */ |
101 | (void)getnum(getstr(&buf), 0, 0, false); /* inode count */ | |
11e06961 | 102 | close(fd); |
2bd0ea18 | 103 | return buf; |
11e06961 ES |
104 | |
105 | out_fail: | |
aabc02b3 ES |
106 | if (fd >= 0) |
107 | close(fd); | |
355ac015 | 108 | free(buf); |
11e06961 | 109 | exit(1); |
2bd0ea18 NS |
110 | } |
111 | ||
2bd0ea18 NS |
112 | static void |
113 | fail( | |
114 | char *msg, | |
115 | int i) | |
116 | { | |
a981f202 | 117 | fprintf(stderr, "%s: %s [%d - %s]\n", progname, msg, i, strerror(i)); |
2bd0ea18 NS |
118 | exit(1); |
119 | } | |
120 | ||
a981f202 NS |
121 | void |
122 | res_failed( | |
123 | int i) | |
124 | { | |
9440d84d | 125 | fail(_("cannot reserve space"), i); |
a981f202 NS |
126 | } |
127 | ||
9074815c | 128 | static struct xfs_trans * |
2bd0ea18 | 129 | getres( |
9074815c | 130 | struct xfs_mount *mp, |
2bd0ea18 NS |
131 | uint blocks) |
132 | { | |
9074815c | 133 | struct xfs_trans *tp; |
2bd0ea18 | 134 | int i; |
2bd0ea18 NS |
135 | uint r; |
136 | ||
2bd0ea18 | 137 | for (i = 0, r = MKFS_BLOCKRES(blocks); r >= blocks; r--) { |
48ea6cb9 DC |
138 | struct xfs_trans_res tres = {0}; |
139 | ||
9074815c | 140 | i = -libxfs_trans_alloc(mp, &tres, r, 0, 0, &tp); |
2bd0ea18 | 141 | if (i == 0) |
9074815c | 142 | return tp; |
2bd0ea18 NS |
143 | } |
144 | res_failed(i); | |
145 | /* NOTREACHED */ | |
9074815c | 146 | return NULL; |
2bd0ea18 NS |
147 | } |
148 | ||
149 | static char * | |
150 | getstr( | |
151 | char **pp) | |
152 | { | |
a0b22cc7 | 153 | char c; |
2bd0ea18 NS |
154 | char *p; |
155 | char *rval; | |
156 | ||
157 | p = *pp; | |
27527004 | 158 | while ((c = *p)) { |
2bd0ea18 NS |
159 | switch (c) { |
160 | case ' ': | |
161 | case '\t': | |
162 | case '\n': | |
163 | p++; | |
164 | continue; | |
165 | case ':': | |
166 | p++; | |
167 | while (*p++ != '\n') | |
168 | ; | |
169 | continue; | |
170 | default: | |
171 | rval = p; | |
172 | while (c != ' ' && c != '\t' && c != '\n' && c != '\0') | |
173 | c = *++p; | |
174 | *p++ = '\0'; | |
175 | *pp = p; | |
176 | return rval; | |
177 | } | |
178 | } | |
a0b22cc7 | 179 | if (c != '\0') { |
9440d84d | 180 | fprintf(stderr, _("%s: premature EOF in prototype file\n"), |
2bd0ea18 NS |
181 | progname); |
182 | exit(1); | |
183 | } | |
184 | return NULL; | |
185 | } | |
186 | ||
187 | static void | |
188 | rsvfile( | |
189 | xfs_mount_t *mp, | |
190 | xfs_inode_t *ip, | |
191 | long long llen) | |
192 | { | |
193 | int error; | |
194 | xfs_trans_t *tp; | |
9074815c | 195 | struct xfs_trans_res tres = {0}; |
2bd0ea18 | 196 | |
12b53197 | 197 | error = -libxfs_alloc_file_space(ip, 0, llen, 1, 0); |
2bd0ea18 NS |
198 | |
199 | if (error) { | |
9440d84d | 200 | fail(_("error reserving space for a file"), error); |
2bd0ea18 NS |
201 | exit(1); |
202 | } | |
203 | ||
204 | /* | |
205 | * update the inode timestamp, mode, and prealloc flag bits | |
206 | */ | |
9074815c | 207 | libxfs_trans_alloc(mp, &tres, 0, 0, 0, &tp); |
2bd0ea18 | 208 | libxfs_trans_ijoin(tp, ip, 0); |
2bd0ea18 | 209 | |
e37bf53c | 210 | VFS_I(ip)->i_mode &= ~S_ISUID; |
2bd0ea18 NS |
211 | |
212 | /* | |
213 | * Note that we don't have to worry about mandatory | |
214 | * file locking being disabled here because we only | |
322f2a29 | 215 | * clear the S_ISGID bit if the Group execute bit is |
2bd0ea18 NS |
216 | * on, but if it was on then mandatory locking wouldn't |
217 | * have been enabled. | |
218 | */ | |
e37bf53c DC |
219 | if (VFS_I(ip)->i_mode & S_IXGRP) |
220 | VFS_I(ip)->i_mode &= ~S_ISGID; | |
2bd0ea18 | 221 | |
56b2de80 | 222 | libxfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); |
2bd0ea18 NS |
223 | |
224 | ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC; | |
225 | ||
226 | libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | |
de5a3f46 | 227 | libxfs_trans_commit(tp); |
2bd0ea18 NS |
228 | } |
229 | ||
230 | static int | |
231 | newfile( | |
232 | xfs_trans_t *tp, | |
233 | xfs_inode_t *ip, | |
f33cea1a | 234 | struct xfs_defer_ops *dfops, |
2bd0ea18 NS |
235 | xfs_fsblock_t *first, |
236 | int dolocal, | |
237 | int logit, | |
238 | char *buf, | |
239 | int len) | |
240 | { | |
241 | xfs_buf_t *bp; | |
242 | xfs_daddr_t d; | |
243 | int error; | |
244 | int flags; | |
245 | xfs_bmbt_irec_t map; | |
246 | xfs_mount_t *mp; | |
247 | xfs_extlen_t nb; | |
248 | int nmap; | |
249 | ||
250 | flags = 0; | |
251 | mp = ip->i_mount; | |
252 | if (dolocal && len <= XFS_IFORK_DSIZE(ip)) { | |
f616e2bf | 253 | libxfs_idata_realloc(ip, len, XFS_DATA_FORK); |
2bd0ea18 | 254 | if (buf) |
dab9b8d6 | 255 | memmove(ip->i_df.if_u1.if_data, buf, len); |
2bd0ea18 NS |
256 | ip->i_d.di_size = len; |
257 | ip->i_df.if_flags &= ~XFS_IFEXTENTS; | |
258 | ip->i_df.if_flags |= XFS_IFINLINE; | |
259 | ip->i_d.di_format = XFS_DINODE_FMT_LOCAL; | |
260 | flags = XFS_ILOG_DDATA; | |
261 | } else if (len > 0) { | |
262 | nb = XFS_B_TO_FSB(mp, len); | |
263 | nmap = 1; | |
12b53197 | 264 | error = -libxfs_bmapi_write(tp, ip, 0, nb, 0, first, nb, |
f33cea1a | 265 | &map, &nmap, dfops); |
2bd0ea18 | 266 | if (error) { |
9440d84d | 267 | fail(_("error allocating space for a file"), error); |
2bd0ea18 NS |
268 | } |
269 | if (nmap != 1) { | |
9440d84d NS |
270 | fprintf(stderr, |
271 | _("%s: cannot allocate space for file\n"), | |
2bd0ea18 NS |
272 | progname); |
273 | exit(1); | |
274 | } | |
275 | d = XFS_FSB_TO_DADDR(mp, map.br_startblock); | |
276 | bp = libxfs_trans_get_buf(logit ? tp : 0, mp->m_dev, d, | |
277 | nb << mp->m_blkbb_log, 0); | |
dab9b8d6 | 278 | memmove(XFS_BUF_PTR(bp), buf, len); |
2bd0ea18 | 279 | if (len < XFS_BUF_COUNT(bp)) |
dab9b8d6 | 280 | memset(XFS_BUF_PTR(bp) + len, 0, XFS_BUF_COUNT(bp) - len); |
2bd0ea18 NS |
281 | if (logit) |
282 | libxfs_trans_log_buf(tp, bp, 0, XFS_BUF_COUNT(bp) - 1); | |
283 | else | |
9440d84d | 284 | libxfs_writebuf(bp, LIBXFS_EXIT_ON_FAILURE); |
2bd0ea18 NS |
285 | } |
286 | ip->i_d.di_size = len; | |
287 | return flags; | |
288 | } | |
289 | ||
290 | static char * | |
291 | newregfile( | |
292 | char **pp, | |
293 | int *len) | |
294 | { | |
295 | char *buf; | |
296 | int fd; | |
297 | char *fname; | |
298 | long size; | |
299 | ||
300 | fname = getstr(pp); | |
301 | if ((fd = open(fname, O_RDONLY)) < 0 || (size = filesize(fd)) < 0) { | |
9440d84d | 302 | fprintf(stderr, _("%s: cannot open %s: %s\n"), |
2bd0ea18 NS |
303 | progname, fname, strerror(errno)); |
304 | exit(1); | |
305 | } | |
27527004 | 306 | if ((*len = (int)size)) { |
2bd0ea18 NS |
307 | buf = malloc(size); |
308 | if (read(fd, buf, size) < size) { | |
9440d84d | 309 | fprintf(stderr, _("%s: read failed on %s: %s\n"), |
2bd0ea18 NS |
310 | progname, fname, strerror(errno)); |
311 | exit(1); | |
312 | } | |
313 | } else | |
314 | buf = 0; | |
315 | close(fd); | |
316 | return buf; | |
317 | } | |
318 | ||
319 | static void | |
320 | newdirent( | |
321 | xfs_mount_t *mp, | |
322 | xfs_trans_t *tp, | |
323 | xfs_inode_t *pip, | |
5e656dbb | 324 | struct xfs_name *name, |
2bd0ea18 NS |
325 | xfs_ino_t inum, |
326 | xfs_fsblock_t *first, | |
f33cea1a | 327 | struct xfs_defer_ops *dfops) |
2bd0ea18 NS |
328 | { |
329 | int error; | |
1b6bf714 ES |
330 | int rsv; |
331 | ||
332 | rsv = XFS_DIRENTER_SPACE_RES(mp, name->len); | |
2bd0ea18 | 333 | |
f33cea1a | 334 | error = -libxfs_dir_createname(tp, pip, name, inum, first, dfops, rsv); |
2bd0ea18 | 335 | if (error) |
9440d84d | 336 | fail(_("directory createname error"), error); |
2bd0ea18 NS |
337 | } |
338 | ||
339 | static void | |
340 | newdirectory( | |
341 | xfs_mount_t *mp, | |
342 | xfs_trans_t *tp, | |
343 | xfs_inode_t *dp, | |
344 | xfs_inode_t *pdp) | |
345 | { | |
346 | int error; | |
347 | ||
12b53197 | 348 | error = -libxfs_dir_init(tp, dp, pdp); |
2bd0ea18 | 349 | if (error) |
9440d84d | 350 | fail(_("directory create error"), error); |
2bd0ea18 NS |
351 | } |
352 | ||
9f064b7e | 353 | static void |
2bd0ea18 NS |
354 | parseproto( |
355 | xfs_mount_t *mp, | |
356 | xfs_inode_t *pip, | |
9f064b7e | 357 | struct fsxattr *fsxp, |
2bd0ea18 NS |
358 | char **pp, |
359 | char *name) | |
360 | { | |
361 | #define IF_REGULAR 0 | |
362 | #define IF_RESERVED 1 | |
363 | #define IF_BLOCK 2 | |
364 | #define IF_CHAR 3 | |
365 | #define IF_DIRECTORY 4 | |
366 | #define IF_SYMLINK 5 | |
367 | #define IF_FIFO 6 | |
368 | ||
369 | char *buf; | |
2bd0ea18 NS |
370 | int error; |
371 | xfs_fsblock_t first; | |
372 | int flags; | |
f33cea1a | 373 | struct xfs_defer_ops dfops; |
2bd0ea18 NS |
374 | int fmt; |
375 | int i; | |
376 | xfs_inode_t *ip; | |
377 | int len; | |
378 | long long llen; | |
379 | int majdev; | |
380 | int mindev; | |
381 | int mode; | |
382 | char *mstr; | |
383 | xfs_trans_t *tp; | |
384 | int val; | |
385 | int isroot = 0; | |
386 | cred_t creds; | |
387 | char *value; | |
5e656dbb | 388 | struct xfs_name xname; |
2bd0ea18 | 389 | |
dab9b8d6 | 390 | memset(&creds, 0, sizeof(creds)); |
2bd0ea18 NS |
391 | mstr = getstr(pp); |
392 | switch (mstr[0]) { | |
393 | case '-': | |
394 | fmt = IF_REGULAR; | |
395 | break; | |
396 | case 'r': | |
397 | fmt = IF_RESERVED; | |
398 | break; | |
399 | case 'b': | |
400 | fmt = IF_BLOCK; | |
401 | break; | |
402 | case 'c': | |
403 | fmt = IF_CHAR; | |
404 | break; | |
405 | case 'd': | |
406 | fmt = IF_DIRECTORY; | |
407 | break; | |
408 | case 'l': | |
409 | fmt = IF_SYMLINK; | |
410 | break; | |
411 | case 'p': | |
412 | fmt = IF_FIFO; | |
413 | break; | |
414 | default: | |
9440d84d NS |
415 | fprintf(stderr, _("%s: bad format string %s\n"), |
416 | progname, mstr); | |
2bd0ea18 NS |
417 | exit(1); |
418 | } | |
419 | mode = 0; | |
420 | switch (mstr[1]) { | |
421 | case '-': | |
422 | break; | |
423 | case 'u': | |
322f2a29 | 424 | mode |= S_ISUID; |
2bd0ea18 NS |
425 | break; |
426 | default: | |
9440d84d NS |
427 | fprintf(stderr, _("%s: bad format string %s\n"), |
428 | progname, mstr); | |
2bd0ea18 NS |
429 | exit(1); |
430 | } | |
431 | switch (mstr[2]) { | |
432 | case '-': | |
433 | break; | |
434 | case 'g': | |
322f2a29 | 435 | mode |= S_ISGID; |
2bd0ea18 NS |
436 | break; |
437 | default: | |
9440d84d NS |
438 | fprintf(stderr, _("%s: bad format string %s\n"), |
439 | progname, mstr); | |
2bd0ea18 NS |
440 | exit(1); |
441 | } | |
442 | val = 0; | |
443 | for (i = 3; i < 6; i++) { | |
444 | if (mstr[i] < '0' || mstr[i] > '7') { | |
9440d84d | 445 | fprintf(stderr, _("%s: bad format string %s\n"), |
2bd0ea18 NS |
446 | progname, mstr); |
447 | exit(1); | |
448 | } | |
449 | val = val * 8 + mstr[i] - '0'; | |
450 | } | |
451 | mode |= val; | |
a887c950 DC |
452 | creds.cr_uid = (int)getnum(getstr(pp), 0, 0, false); |
453 | creds.cr_gid = (int)getnum(getstr(pp), 0, 0, false); | |
02211695 | 454 | xname.name = (unsigned char *)name; |
5e656dbb | 455 | xname.len = name ? strlen(name) : 0; |
0aa7d591 | 456 | xname.type = 0; |
2bd0ea18 | 457 | flags = XFS_ILOG_CORE; |
f33cea1a | 458 | libxfs_defer_init(&dfops, &first); |
2bd0ea18 NS |
459 | switch (fmt) { |
460 | case IF_REGULAR: | |
461 | buf = newregfile(pp, &len); | |
9074815c | 462 | tp = getres(mp, XFS_B_TO_FSB(mp, len)); |
12b53197 | 463 | error = -libxfs_inode_alloc(&tp, pip, mode|S_IFREG, 1, 0, |
9f064b7e | 464 | &creds, fsxp, &ip); |
2bd0ea18 | 465 | if (error) |
9440d84d | 466 | fail(_("Inode allocation failed"), error); |
f33cea1a | 467 | flags |= newfile(tp, ip, &dfops, &first, 0, 0, buf, len); |
2bd0ea18 NS |
468 | if (buf) |
469 | free(buf); | |
470 | libxfs_trans_ijoin(tp, pip, 0); | |
0aa7d591 | 471 | xname.type = XFS_DIR3_FT_REG_FILE; |
f33cea1a | 472 | newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops); |
2bd0ea18 NS |
473 | break; |
474 | ||
475 | case IF_RESERVED: /* pre-allocated space only */ | |
476 | value = getstr(pp); | |
a887c950 DC |
477 | llen = getnum(value, mp->m_sb.sb_blocksize, |
478 | mp->m_sb.sb_sectsize, true); | |
479 | if (llen < 0) { | |
480 | fprintf(stderr, | |
481 | _("%s: Bad value %s for proto file %s\n"), | |
482 | progname, value, name); | |
483 | exit(1); | |
484 | } | |
9074815c | 485 | tp = getres(mp, XFS_B_TO_FSB(mp, llen)); |
2bd0ea18 | 486 | |
12b53197 | 487 | error = -libxfs_inode_alloc(&tp, pip, mode|S_IFREG, 1, 0, |
9f064b7e | 488 | &creds, fsxp, &ip); |
2bd0ea18 | 489 | if (error) |
9440d84d | 490 | fail(_("Inode pre-allocation failed"), error); |
2bd0ea18 NS |
491 | |
492 | libxfs_trans_ijoin(tp, pip, 0); | |
493 | ||
0aa7d591 | 494 | xname.type = XFS_DIR3_FT_REG_FILE; |
f33cea1a | 495 | newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops); |
2bd0ea18 NS |
496 | libxfs_trans_log_inode(tp, ip, flags); |
497 | ||
f33cea1a | 498 | error = -libxfs_defer_finish(&tp, &dfops, ip); |
2bd0ea18 | 499 | if (error) |
9440d84d | 500 | fail(_("Pre-allocated file creation failed"), error); |
de5a3f46 | 501 | libxfs_trans_commit(tp); |
2bd0ea18 | 502 | rsvfile(mp, ip, llen); |
260c85e8 | 503 | IRELE(ip); |
2bd0ea18 NS |
504 | return; |
505 | ||
506 | case IF_BLOCK: | |
9074815c | 507 | tp = getres(mp, 0); |
a887c950 DC |
508 | majdev = getnum(getstr(pp), 0, 0, false); |
509 | mindev = getnum(getstr(pp), 0, 0, false); | |
12b53197 | 510 | error = -libxfs_inode_alloc(&tp, pip, mode|S_IFBLK, 1, |
9f064b7e | 511 | IRIX_MKDEV(majdev, mindev), &creds, fsxp, &ip); |
2bd0ea18 | 512 | if (error) { |
9440d84d | 513 | fail(_("Inode allocation failed"), error); |
2bd0ea18 NS |
514 | } |
515 | libxfs_trans_ijoin(tp, pip, 0); | |
0aa7d591 | 516 | xname.type = XFS_DIR3_FT_BLKDEV; |
f33cea1a | 517 | newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops); |
2bd0ea18 NS |
518 | flags |= XFS_ILOG_DEV; |
519 | break; | |
520 | ||
521 | case IF_CHAR: | |
9074815c | 522 | tp = getres(mp, 0); |
a887c950 DC |
523 | majdev = getnum(getstr(pp), 0, 0, false); |
524 | mindev = getnum(getstr(pp), 0, 0, false); | |
12b53197 | 525 | error = -libxfs_inode_alloc(&tp, pip, mode|S_IFCHR, 1, |
9f064b7e | 526 | IRIX_MKDEV(majdev, mindev), &creds, fsxp, &ip); |
2bd0ea18 | 527 | if (error) |
9440d84d | 528 | fail(_("Inode allocation failed"), error); |
2bd0ea18 | 529 | libxfs_trans_ijoin(tp, pip, 0); |
0aa7d591 | 530 | xname.type = XFS_DIR3_FT_CHRDEV; |
f33cea1a | 531 | newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops); |
2bd0ea18 NS |
532 | flags |= XFS_ILOG_DEV; |
533 | break; | |
534 | ||
535 | case IF_FIFO: | |
9074815c | 536 | tp = getres(mp, 0); |
12b53197 | 537 | error = -libxfs_inode_alloc(&tp, pip, mode|S_IFIFO, 1, 0, |
9f064b7e | 538 | &creds, fsxp, &ip); |
2bd0ea18 | 539 | if (error) |
9440d84d | 540 | fail(_("Inode allocation failed"), error); |
2bd0ea18 | 541 | libxfs_trans_ijoin(tp, pip, 0); |
0aa7d591 | 542 | xname.type = XFS_DIR3_FT_FIFO; |
f33cea1a | 543 | newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops); |
2bd0ea18 NS |
544 | break; |
545 | case IF_SYMLINK: | |
546 | buf = getstr(pp); | |
547 | len = (int)strlen(buf); | |
9074815c | 548 | tp = getres(mp, XFS_B_TO_FSB(mp, len)); |
12b53197 | 549 | error = -libxfs_inode_alloc(&tp, pip, mode|S_IFLNK, 1, 0, |
9f064b7e | 550 | &creds, fsxp, &ip); |
2bd0ea18 | 551 | if (error) |
9440d84d | 552 | fail(_("Inode allocation failed"), error); |
f33cea1a | 553 | flags |= newfile(tp, ip, &dfops, &first, 1, 1, buf, len); |
2bd0ea18 | 554 | libxfs_trans_ijoin(tp, pip, 0); |
0aa7d591 | 555 | xname.type = XFS_DIR3_FT_SYMLINK; |
f33cea1a | 556 | newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops); |
2bd0ea18 NS |
557 | break; |
558 | case IF_DIRECTORY: | |
9074815c | 559 | tp = getres(mp, 0); |
12b53197 | 560 | error = -libxfs_inode_alloc(&tp, pip, mode|S_IFDIR, 1, 0, |
9f064b7e | 561 | &creds, fsxp, &ip); |
2bd0ea18 | 562 | if (error) |
9440d84d | 563 | fail(_("Inode allocation failed"), error); |
bcbe04c1 | 564 | inc_nlink(VFS_I(ip)); /* account for . */ |
2bd0ea18 NS |
565 | if (!pip) { |
566 | pip = ip; | |
567 | mp->m_sb.sb_rootino = ip->i_ino; | |
19ebedcf | 568 | libxfs_log_sb(tp); |
2bd0ea18 NS |
569 | isroot = 1; |
570 | } else { | |
571 | libxfs_trans_ijoin(tp, pip, 0); | |
0aa7d591 | 572 | xname.type = XFS_DIR3_FT_DIR; |
5e656dbb | 573 | newdirent(mp, tp, pip, &xname, ip->i_ino, |
f33cea1a | 574 | &first, &dfops); |
bcbe04c1 | 575 | inc_nlink(VFS_I(pip)); |
2bd0ea18 NS |
576 | libxfs_trans_log_inode(tp, pip, XFS_ILOG_CORE); |
577 | } | |
578 | newdirectory(mp, tp, ip, pip); | |
579 | libxfs_trans_log_inode(tp, ip, flags); | |
f33cea1a | 580 | error = -libxfs_defer_finish(&tp, &dfops, ip); |
2bd0ea18 | 581 | if (error) |
9440d84d | 582 | fail(_("Directory creation failed"), error); |
de5a3f46 | 583 | libxfs_trans_commit(tp); |
2bd0ea18 NS |
584 | /* |
585 | * RT initialization. Do this here to ensure that | |
586 | * the RT inodes get placed after the root inode. | |
587 | */ | |
588 | if (isroot) | |
589 | rtinit(mp); | |
590 | tp = NULL; | |
591 | for (;;) { | |
592 | name = getstr(pp); | |
a0b22cc7 RC |
593 | if (!name) |
594 | break; | |
2bd0ea18 NS |
595 | if (strcmp(name, "$") == 0) |
596 | break; | |
9f064b7e | 597 | parseproto(mp, ip, fsxp, pp, name); |
2bd0ea18 | 598 | } |
dd2c21d2 | 599 | IRELE(ip); |
2bd0ea18 | 600 | return; |
3ddc4aeb ES |
601 | default: |
602 | ASSERT(0); | |
603 | fail(_("Unknown format"), EINVAL); | |
2bd0ea18 NS |
604 | } |
605 | libxfs_trans_log_inode(tp, ip, flags); | |
f33cea1a | 606 | error = -libxfs_defer_finish(&tp, &dfops, ip); |
2bd0ea18 | 607 | if (error) { |
9440d84d NS |
608 | fail(_("Error encountered creating file from prototype file"), |
609 | error); | |
2bd0ea18 | 610 | } |
de5a3f46 | 611 | libxfs_trans_commit(tp); |
260c85e8 | 612 | IRELE(ip); |
2bd0ea18 NS |
613 | } |
614 | ||
9f064b7e NS |
615 | void |
616 | parse_proto( | |
617 | xfs_mount_t *mp, | |
618 | struct fsxattr *fsx, | |
619 | char **pp) | |
620 | { | |
621 | parseproto(mp, NULL, fsx, pp, NULL); | |
622 | } | |
623 | ||
2bd0ea18 NS |
624 | /* |
625 | * Allocate the realtime bitmap and summary inodes, and fill in data if any. | |
626 | */ | |
627 | static void | |
628 | rtinit( | |
629 | xfs_mount_t *mp) | |
630 | { | |
5a35bf2c | 631 | xfs_fileoff_t bno; |
5a35bf2c | 632 | xfs_fileoff_t ebno; |
2bd0ea18 NS |
633 | xfs_bmbt_irec_t *ep; |
634 | int error; | |
635 | xfs_fsblock_t first; | |
f33cea1a | 636 | struct xfs_defer_ops dfops; |
2bd0ea18 NS |
637 | int i; |
638 | xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP]; | |
639 | xfs_extlen_t nsumblocks; | |
640 | int nmap; | |
641 | xfs_inode_t *rbmip; | |
642 | xfs_inode_t *rsumip; | |
643 | xfs_trans_t *tp; | |
9f064b7e NS |
644 | struct cred creds; |
645 | struct fsxattr fsxattrs; | |
48ea6cb9 | 646 | struct xfs_trans_res tres = {0}; |
2bd0ea18 NS |
647 | |
648 | /* | |
649 | * First, allocate the inodes. | |
650 | */ | |
9074815c | 651 | i = -libxfs_trans_alloc(mp, &tres, MKFS_BLOCKRES_INODE, 0, 0, &tp); |
48ea6cb9 | 652 | if (i) |
2bd0ea18 | 653 | res_failed(i); |
48ea6cb9 | 654 | |
dab9b8d6 BN |
655 | memset(&creds, 0, sizeof(creds)); |
656 | memset(&fsxattrs, 0, sizeof(fsxattrs)); | |
12b53197 | 657 | error = -libxfs_inode_alloc(&tp, NULL, S_IFREG, 1, 0, |
9f064b7e | 658 | &creds, &fsxattrs, &rbmip); |
2bd0ea18 | 659 | if (error) { |
9440d84d | 660 | fail(_("Realtime bitmap inode allocation failed"), error); |
2bd0ea18 NS |
661 | } |
662 | /* | |
663 | * Do our thing with rbmip before allocating rsumip, | |
664 | * because the next call to ialloc() may | |
665 | * commit the transaction in which rbmip was allocated. | |
666 | */ | |
667 | mp->m_sb.sb_rbmino = rbmip->i_ino; | |
668 | rbmip->i_d.di_size = mp->m_sb.sb_rbmblocks * mp->m_sb.sb_blocksize; | |
669 | rbmip->i_d.di_flags = XFS_DIFLAG_NEWRTBM; | |
14f8b681 | 670 | *(uint64_t *)&VFS_I(rbmip)->i_atime = 0; |
2bd0ea18 | 671 | libxfs_trans_log_inode(tp, rbmip, XFS_ILOG_CORE); |
19ebedcf | 672 | libxfs_log_sb(tp); |
2bd0ea18 | 673 | mp->m_rbmip = rbmip; |
12b53197 | 674 | error = -libxfs_inode_alloc(&tp, NULL, S_IFREG, 1, 0, |
9f064b7e | 675 | &creds, &fsxattrs, &rsumip); |
2bd0ea18 | 676 | if (error) { |
9440d84d | 677 | fail(_("Realtime summary inode allocation failed"), error); |
2bd0ea18 NS |
678 | } |
679 | mp->m_sb.sb_rsumino = rsumip->i_ino; | |
680 | rsumip->i_d.di_size = mp->m_rsumsize; | |
681 | libxfs_trans_log_inode(tp, rsumip, XFS_ILOG_CORE); | |
19ebedcf | 682 | libxfs_log_sb(tp); |
de5a3f46 | 683 | libxfs_trans_commit(tp); |
2bd0ea18 NS |
684 | mp->m_rsumip = rsumip; |
685 | /* | |
686 | * Next, give the bitmap file some zero-filled blocks. | |
687 | */ | |
9074815c CH |
688 | i = -libxfs_trans_alloc(mp, &tres, |
689 | mp->m_sb.sb_rbmblocks + (XFS_BM_MAXLEVELS(mp,XFS_DATA_FORK) - 1), | |
690 | 0, 0, &tp); | |
48ea6cb9 | 691 | if (i) |
2bd0ea18 | 692 | res_failed(i); |
48ea6cb9 | 693 | |
2bd0ea18 NS |
694 | libxfs_trans_ijoin(tp, rbmip, 0); |
695 | bno = 0; | |
f33cea1a | 696 | libxfs_defer_init(&dfops, &first); |
2bd0ea18 NS |
697 | while (bno < mp->m_sb.sb_rbmblocks) { |
698 | nmap = XFS_BMAP_MAX_NMAP; | |
12b53197 | 699 | error = -libxfs_bmapi_write(tp, rbmip, bno, |
2bd0ea18 | 700 | (xfs_extlen_t)(mp->m_sb.sb_rbmblocks - bno), |
a2ceac1f | 701 | 0, &first, mp->m_sb.sb_rbmblocks, |
f33cea1a | 702 | map, &nmap, &dfops); |
2bd0ea18 | 703 | if (error) { |
9440d84d NS |
704 | fail(_("Allocation of the realtime bitmap failed"), |
705 | error); | |
2bd0ea18 NS |
706 | } |
707 | for (i = 0, ep = map; i < nmap; i++, ep++) { | |
75c8b434 | 708 | libxfs_device_zero(mp->m_ddev_targp, |
2bd0ea18 NS |
709 | XFS_FSB_TO_DADDR(mp, ep->br_startblock), |
710 | XFS_FSB_TO_BB(mp, ep->br_blockcount)); | |
711 | bno += ep->br_blockcount; | |
712 | } | |
713 | } | |
714 | ||
f33cea1a | 715 | error = -libxfs_defer_finish(&tp, &dfops, rbmip); |
2bd0ea18 | 716 | if (error) { |
9440d84d | 717 | fail(_("Completion of the realtime bitmap failed"), error); |
2bd0ea18 | 718 | } |
de5a3f46 | 719 | libxfs_trans_commit(tp); |
9440d84d | 720 | |
2bd0ea18 NS |
721 | /* |
722 | * Give the summary file some zero-filled blocks. | |
723 | */ | |
2bd0ea18 | 724 | nsumblocks = mp->m_rsumsize >> mp->m_sb.sb_blocklog; |
9074815c CH |
725 | i = -libxfs_trans_alloc(mp, &tres, |
726 | nsumblocks + (XFS_BM_MAXLEVELS(mp,XFS_DATA_FORK) - 1), | |
727 | 0, 0, &tp); | |
48ea6cb9 | 728 | if (i) |
2bd0ea18 NS |
729 | res_failed(i); |
730 | libxfs_trans_ijoin(tp, rsumip, 0); | |
731 | bno = 0; | |
f33cea1a | 732 | libxfs_defer_init(&dfops, &first); |
2bd0ea18 NS |
733 | while (bno < nsumblocks) { |
734 | nmap = XFS_BMAP_MAX_NMAP; | |
12b53197 | 735 | error = -libxfs_bmapi_write(tp, rsumip, bno, |
2bd0ea18 | 736 | (xfs_extlen_t)(nsumblocks - bno), |
a2ceac1f | 737 | 0, &first, nsumblocks, |
f33cea1a | 738 | map, &nmap, &dfops); |
2bd0ea18 | 739 | if (error) { |
9440d84d NS |
740 | fail(_("Allocation of the realtime summary failed"), |
741 | error); | |
2bd0ea18 NS |
742 | } |
743 | for (i = 0, ep = map; i < nmap; i++, ep++) { | |
75c8b434 | 744 | libxfs_device_zero(mp->m_ddev_targp, |
2bd0ea18 NS |
745 | XFS_FSB_TO_DADDR(mp, ep->br_startblock), |
746 | XFS_FSB_TO_BB(mp, ep->br_blockcount)); | |
747 | bno += ep->br_blockcount; | |
748 | } | |
749 | } | |
f33cea1a | 750 | error = -libxfs_defer_finish(&tp, &dfops, rsumip); |
2bd0ea18 | 751 | if (error) { |
9440d84d | 752 | fail(_("Completion of the realtime summary failed"), error); |
2bd0ea18 | 753 | } |
de5a3f46 | 754 | libxfs_trans_commit(tp); |
9440d84d | 755 | |
2bd0ea18 NS |
756 | /* |
757 | * Free the whole area using transactions. | |
758 | * Do one transaction per bitmap block. | |
759 | */ | |
760 | for (bno = 0; bno < mp->m_sb.sb_rextents; bno = ebno) { | |
9074815c | 761 | i = -libxfs_trans_alloc(mp, &tres, 0, 0, 0, &tp); |
48ea6cb9 | 762 | if (i) |
2bd0ea18 | 763 | res_failed(i); |
6697bce2 | 764 | libxfs_trans_ijoin(tp, rbmip, 0); |
f33cea1a | 765 | libxfs_defer_init(&dfops, &first); |
2bd0ea18 NS |
766 | ebno = XFS_RTMIN(mp->m_sb.sb_rextents, |
767 | bno + NBBY * mp->m_sb.sb_blocksize); | |
12b53197 | 768 | error = -libxfs_rtfree_extent(tp, bno, (xfs_extlen_t)(ebno-bno)); |
2bd0ea18 | 769 | if (error) { |
9440d84d NS |
770 | fail(_("Error initializing the realtime space"), |
771 | error); | |
2bd0ea18 | 772 | } |
f33cea1a | 773 | error = -libxfs_defer_finish(&tp, &dfops, rbmip); |
2bd0ea18 | 774 | if (error) { |
9440d84d | 775 | fail(_("Error completing the realtime space"), error); |
2bd0ea18 | 776 | } |
de5a3f46 | 777 | libxfs_trans_commit(tp); |
2bd0ea18 NS |
778 | } |
779 | } | |
780 | ||
2bd0ea18 NS |
781 | static long |
782 | filesize( | |
783 | int fd) | |
784 | { | |
f594a0d1 | 785 | struct stat stb; |
2bd0ea18 | 786 | |
f594a0d1 | 787 | if (fstat(fd, &stb) < 0) |
2bd0ea18 NS |
788 | return -1; |
789 | return (long)stb.st_size; | |
790 | } |