]>
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 | ||
5c33baee CH |
498 | libxfs_defer_ijoin(&dfops, ip); |
499 | error = -libxfs_defer_finish(&tp, &dfops); | |
2bd0ea18 | 500 | if (error) |
9440d84d | 501 | fail(_("Pre-allocated file creation failed"), error); |
de5a3f46 | 502 | libxfs_trans_commit(tp); |
2bd0ea18 | 503 | rsvfile(mp, ip, llen); |
260c85e8 | 504 | IRELE(ip); |
2bd0ea18 NS |
505 | return; |
506 | ||
507 | case IF_BLOCK: | |
9074815c | 508 | tp = getres(mp, 0); |
a887c950 DC |
509 | majdev = getnum(getstr(pp), 0, 0, false); |
510 | mindev = getnum(getstr(pp), 0, 0, false); | |
12b53197 | 511 | error = -libxfs_inode_alloc(&tp, pip, mode|S_IFBLK, 1, |
9f064b7e | 512 | IRIX_MKDEV(majdev, mindev), &creds, fsxp, &ip); |
2bd0ea18 | 513 | if (error) { |
9440d84d | 514 | fail(_("Inode allocation failed"), error); |
2bd0ea18 NS |
515 | } |
516 | libxfs_trans_ijoin(tp, pip, 0); | |
0aa7d591 | 517 | xname.type = XFS_DIR3_FT_BLKDEV; |
f33cea1a | 518 | newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops); |
2bd0ea18 NS |
519 | flags |= XFS_ILOG_DEV; |
520 | break; | |
521 | ||
522 | case IF_CHAR: | |
9074815c | 523 | tp = getres(mp, 0); |
a887c950 DC |
524 | majdev = getnum(getstr(pp), 0, 0, false); |
525 | mindev = getnum(getstr(pp), 0, 0, false); | |
12b53197 | 526 | error = -libxfs_inode_alloc(&tp, pip, mode|S_IFCHR, 1, |
9f064b7e | 527 | IRIX_MKDEV(majdev, mindev), &creds, fsxp, &ip); |
2bd0ea18 | 528 | if (error) |
9440d84d | 529 | fail(_("Inode allocation failed"), error); |
2bd0ea18 | 530 | libxfs_trans_ijoin(tp, pip, 0); |
0aa7d591 | 531 | xname.type = XFS_DIR3_FT_CHRDEV; |
f33cea1a | 532 | newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops); |
2bd0ea18 NS |
533 | flags |= XFS_ILOG_DEV; |
534 | break; | |
535 | ||
536 | case IF_FIFO: | |
9074815c | 537 | tp = getres(mp, 0); |
12b53197 | 538 | error = -libxfs_inode_alloc(&tp, pip, mode|S_IFIFO, 1, 0, |
9f064b7e | 539 | &creds, fsxp, &ip); |
2bd0ea18 | 540 | if (error) |
9440d84d | 541 | fail(_("Inode allocation failed"), error); |
2bd0ea18 | 542 | libxfs_trans_ijoin(tp, pip, 0); |
0aa7d591 | 543 | xname.type = XFS_DIR3_FT_FIFO; |
f33cea1a | 544 | newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops); |
2bd0ea18 NS |
545 | break; |
546 | case IF_SYMLINK: | |
547 | buf = getstr(pp); | |
548 | len = (int)strlen(buf); | |
9074815c | 549 | tp = getres(mp, XFS_B_TO_FSB(mp, len)); |
12b53197 | 550 | error = -libxfs_inode_alloc(&tp, pip, mode|S_IFLNK, 1, 0, |
9f064b7e | 551 | &creds, fsxp, &ip); |
2bd0ea18 | 552 | if (error) |
9440d84d | 553 | fail(_("Inode allocation failed"), error); |
f33cea1a | 554 | flags |= newfile(tp, ip, &dfops, &first, 1, 1, buf, len); |
2bd0ea18 | 555 | libxfs_trans_ijoin(tp, pip, 0); |
0aa7d591 | 556 | xname.type = XFS_DIR3_FT_SYMLINK; |
f33cea1a | 557 | newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops); |
2bd0ea18 NS |
558 | break; |
559 | case IF_DIRECTORY: | |
9074815c | 560 | tp = getres(mp, 0); |
12b53197 | 561 | error = -libxfs_inode_alloc(&tp, pip, mode|S_IFDIR, 1, 0, |
9f064b7e | 562 | &creds, fsxp, &ip); |
2bd0ea18 | 563 | if (error) |
9440d84d | 564 | fail(_("Inode allocation failed"), error); |
bcbe04c1 | 565 | inc_nlink(VFS_I(ip)); /* account for . */ |
2bd0ea18 NS |
566 | if (!pip) { |
567 | pip = ip; | |
568 | mp->m_sb.sb_rootino = ip->i_ino; | |
19ebedcf | 569 | libxfs_log_sb(tp); |
2bd0ea18 NS |
570 | isroot = 1; |
571 | } else { | |
572 | libxfs_trans_ijoin(tp, pip, 0); | |
0aa7d591 | 573 | xname.type = XFS_DIR3_FT_DIR; |
5e656dbb | 574 | newdirent(mp, tp, pip, &xname, ip->i_ino, |
f33cea1a | 575 | &first, &dfops); |
bcbe04c1 | 576 | inc_nlink(VFS_I(pip)); |
2bd0ea18 NS |
577 | libxfs_trans_log_inode(tp, pip, XFS_ILOG_CORE); |
578 | } | |
579 | newdirectory(mp, tp, ip, pip); | |
580 | libxfs_trans_log_inode(tp, ip, flags); | |
5c33baee CH |
581 | libxfs_defer_ijoin(&dfops, ip); |
582 | error = -libxfs_defer_finish(&tp, &dfops); | |
2bd0ea18 | 583 | if (error) |
9440d84d | 584 | fail(_("Directory creation failed"), error); |
de5a3f46 | 585 | libxfs_trans_commit(tp); |
2bd0ea18 NS |
586 | /* |
587 | * RT initialization. Do this here to ensure that | |
588 | * the RT inodes get placed after the root inode. | |
589 | */ | |
590 | if (isroot) | |
591 | rtinit(mp); | |
592 | tp = NULL; | |
593 | for (;;) { | |
594 | name = getstr(pp); | |
a0b22cc7 RC |
595 | if (!name) |
596 | break; | |
2bd0ea18 NS |
597 | if (strcmp(name, "$") == 0) |
598 | break; | |
9f064b7e | 599 | parseproto(mp, ip, fsxp, pp, name); |
2bd0ea18 | 600 | } |
dd2c21d2 | 601 | IRELE(ip); |
2bd0ea18 | 602 | return; |
3ddc4aeb ES |
603 | default: |
604 | ASSERT(0); | |
605 | fail(_("Unknown format"), EINVAL); | |
2bd0ea18 NS |
606 | } |
607 | libxfs_trans_log_inode(tp, ip, flags); | |
5c33baee CH |
608 | libxfs_defer_ijoin(&dfops, ip); |
609 | error = -libxfs_defer_finish(&tp, &dfops); | |
2bd0ea18 | 610 | if (error) { |
9440d84d NS |
611 | fail(_("Error encountered creating file from prototype file"), |
612 | error); | |
2bd0ea18 | 613 | } |
de5a3f46 | 614 | libxfs_trans_commit(tp); |
260c85e8 | 615 | IRELE(ip); |
2bd0ea18 NS |
616 | } |
617 | ||
9f064b7e NS |
618 | void |
619 | parse_proto( | |
620 | xfs_mount_t *mp, | |
621 | struct fsxattr *fsx, | |
622 | char **pp) | |
623 | { | |
624 | parseproto(mp, NULL, fsx, pp, NULL); | |
625 | } | |
626 | ||
2bd0ea18 NS |
627 | /* |
628 | * Allocate the realtime bitmap and summary inodes, and fill in data if any. | |
629 | */ | |
630 | static void | |
631 | rtinit( | |
632 | xfs_mount_t *mp) | |
633 | { | |
5a35bf2c | 634 | xfs_fileoff_t bno; |
5a35bf2c | 635 | xfs_fileoff_t ebno; |
2bd0ea18 NS |
636 | xfs_bmbt_irec_t *ep; |
637 | int error; | |
638 | xfs_fsblock_t first; | |
f33cea1a | 639 | struct xfs_defer_ops dfops; |
2bd0ea18 NS |
640 | int i; |
641 | xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP]; | |
642 | xfs_extlen_t nsumblocks; | |
643 | int nmap; | |
644 | xfs_inode_t *rbmip; | |
645 | xfs_inode_t *rsumip; | |
646 | xfs_trans_t *tp; | |
9f064b7e NS |
647 | struct cred creds; |
648 | struct fsxattr fsxattrs; | |
48ea6cb9 | 649 | struct xfs_trans_res tres = {0}; |
2bd0ea18 NS |
650 | |
651 | /* | |
652 | * First, allocate the inodes. | |
653 | */ | |
9074815c | 654 | i = -libxfs_trans_alloc(mp, &tres, MKFS_BLOCKRES_INODE, 0, 0, &tp); |
48ea6cb9 | 655 | if (i) |
2bd0ea18 | 656 | res_failed(i); |
48ea6cb9 | 657 | |
dab9b8d6 BN |
658 | memset(&creds, 0, sizeof(creds)); |
659 | memset(&fsxattrs, 0, sizeof(fsxattrs)); | |
12b53197 | 660 | error = -libxfs_inode_alloc(&tp, NULL, S_IFREG, 1, 0, |
9f064b7e | 661 | &creds, &fsxattrs, &rbmip); |
2bd0ea18 | 662 | if (error) { |
9440d84d | 663 | fail(_("Realtime bitmap inode allocation failed"), error); |
2bd0ea18 NS |
664 | } |
665 | /* | |
666 | * Do our thing with rbmip before allocating rsumip, | |
667 | * because the next call to ialloc() may | |
668 | * commit the transaction in which rbmip was allocated. | |
669 | */ | |
670 | mp->m_sb.sb_rbmino = rbmip->i_ino; | |
671 | rbmip->i_d.di_size = mp->m_sb.sb_rbmblocks * mp->m_sb.sb_blocksize; | |
672 | rbmip->i_d.di_flags = XFS_DIFLAG_NEWRTBM; | |
14f8b681 | 673 | *(uint64_t *)&VFS_I(rbmip)->i_atime = 0; |
2bd0ea18 | 674 | libxfs_trans_log_inode(tp, rbmip, XFS_ILOG_CORE); |
19ebedcf | 675 | libxfs_log_sb(tp); |
2bd0ea18 | 676 | mp->m_rbmip = rbmip; |
12b53197 | 677 | error = -libxfs_inode_alloc(&tp, NULL, S_IFREG, 1, 0, |
9f064b7e | 678 | &creds, &fsxattrs, &rsumip); |
2bd0ea18 | 679 | if (error) { |
9440d84d | 680 | fail(_("Realtime summary inode allocation failed"), error); |
2bd0ea18 NS |
681 | } |
682 | mp->m_sb.sb_rsumino = rsumip->i_ino; | |
683 | rsumip->i_d.di_size = mp->m_rsumsize; | |
684 | libxfs_trans_log_inode(tp, rsumip, XFS_ILOG_CORE); | |
19ebedcf | 685 | libxfs_log_sb(tp); |
de5a3f46 | 686 | libxfs_trans_commit(tp); |
2bd0ea18 NS |
687 | mp->m_rsumip = rsumip; |
688 | /* | |
689 | * Next, give the bitmap file some zero-filled blocks. | |
690 | */ | |
9074815c CH |
691 | i = -libxfs_trans_alloc(mp, &tres, |
692 | mp->m_sb.sb_rbmblocks + (XFS_BM_MAXLEVELS(mp,XFS_DATA_FORK) - 1), | |
693 | 0, 0, &tp); | |
48ea6cb9 | 694 | if (i) |
2bd0ea18 | 695 | res_failed(i); |
48ea6cb9 | 696 | |
2bd0ea18 NS |
697 | libxfs_trans_ijoin(tp, rbmip, 0); |
698 | bno = 0; | |
f33cea1a | 699 | libxfs_defer_init(&dfops, &first); |
2bd0ea18 NS |
700 | while (bno < mp->m_sb.sb_rbmblocks) { |
701 | nmap = XFS_BMAP_MAX_NMAP; | |
12b53197 | 702 | error = -libxfs_bmapi_write(tp, rbmip, bno, |
2bd0ea18 | 703 | (xfs_extlen_t)(mp->m_sb.sb_rbmblocks - bno), |
a2ceac1f | 704 | 0, &first, mp->m_sb.sb_rbmblocks, |
f33cea1a | 705 | map, &nmap, &dfops); |
2bd0ea18 | 706 | if (error) { |
9440d84d NS |
707 | fail(_("Allocation of the realtime bitmap failed"), |
708 | error); | |
2bd0ea18 NS |
709 | } |
710 | for (i = 0, ep = map; i < nmap; i++, ep++) { | |
75c8b434 | 711 | libxfs_device_zero(mp->m_ddev_targp, |
2bd0ea18 NS |
712 | XFS_FSB_TO_DADDR(mp, ep->br_startblock), |
713 | XFS_FSB_TO_BB(mp, ep->br_blockcount)); | |
714 | bno += ep->br_blockcount; | |
715 | } | |
716 | } | |
717 | ||
5c33baee CH |
718 | libxfs_defer_ijoin(&dfops, rbmip); |
719 | error = -libxfs_defer_finish(&tp, &dfops); | |
2bd0ea18 | 720 | if (error) { |
9440d84d | 721 | fail(_("Completion of the realtime bitmap failed"), error); |
2bd0ea18 | 722 | } |
de5a3f46 | 723 | libxfs_trans_commit(tp); |
9440d84d | 724 | |
2bd0ea18 NS |
725 | /* |
726 | * Give the summary file some zero-filled blocks. | |
727 | */ | |
2bd0ea18 | 728 | nsumblocks = mp->m_rsumsize >> mp->m_sb.sb_blocklog; |
9074815c CH |
729 | i = -libxfs_trans_alloc(mp, &tres, |
730 | nsumblocks + (XFS_BM_MAXLEVELS(mp,XFS_DATA_FORK) - 1), | |
731 | 0, 0, &tp); | |
48ea6cb9 | 732 | if (i) |
2bd0ea18 NS |
733 | res_failed(i); |
734 | libxfs_trans_ijoin(tp, rsumip, 0); | |
735 | bno = 0; | |
f33cea1a | 736 | libxfs_defer_init(&dfops, &first); |
2bd0ea18 NS |
737 | while (bno < nsumblocks) { |
738 | nmap = XFS_BMAP_MAX_NMAP; | |
12b53197 | 739 | error = -libxfs_bmapi_write(tp, rsumip, bno, |
2bd0ea18 | 740 | (xfs_extlen_t)(nsumblocks - bno), |
a2ceac1f | 741 | 0, &first, nsumblocks, |
f33cea1a | 742 | map, &nmap, &dfops); |
2bd0ea18 | 743 | if (error) { |
9440d84d NS |
744 | fail(_("Allocation of the realtime summary failed"), |
745 | error); | |
2bd0ea18 NS |
746 | } |
747 | for (i = 0, ep = map; i < nmap; i++, ep++) { | |
75c8b434 | 748 | libxfs_device_zero(mp->m_ddev_targp, |
2bd0ea18 NS |
749 | XFS_FSB_TO_DADDR(mp, ep->br_startblock), |
750 | XFS_FSB_TO_BB(mp, ep->br_blockcount)); | |
751 | bno += ep->br_blockcount; | |
752 | } | |
753 | } | |
5c33baee CH |
754 | libxfs_defer_ijoin(&dfops, rsumip); |
755 | error = -libxfs_defer_finish(&tp, &dfops); | |
2bd0ea18 | 756 | if (error) { |
9440d84d | 757 | fail(_("Completion of the realtime summary failed"), error); |
2bd0ea18 | 758 | } |
de5a3f46 | 759 | libxfs_trans_commit(tp); |
9440d84d | 760 | |
2bd0ea18 NS |
761 | /* |
762 | * Free the whole area using transactions. | |
763 | * Do one transaction per bitmap block. | |
764 | */ | |
765 | for (bno = 0; bno < mp->m_sb.sb_rextents; bno = ebno) { | |
9074815c | 766 | i = -libxfs_trans_alloc(mp, &tres, 0, 0, 0, &tp); |
48ea6cb9 | 767 | if (i) |
2bd0ea18 | 768 | res_failed(i); |
6697bce2 | 769 | libxfs_trans_ijoin(tp, rbmip, 0); |
f33cea1a | 770 | libxfs_defer_init(&dfops, &first); |
2bd0ea18 NS |
771 | ebno = XFS_RTMIN(mp->m_sb.sb_rextents, |
772 | bno + NBBY * mp->m_sb.sb_blocksize); | |
12b53197 | 773 | error = -libxfs_rtfree_extent(tp, bno, (xfs_extlen_t)(ebno-bno)); |
2bd0ea18 | 774 | if (error) { |
9440d84d NS |
775 | fail(_("Error initializing the realtime space"), |
776 | error); | |
2bd0ea18 | 777 | } |
5c33baee CH |
778 | libxfs_defer_ijoin(&dfops, rbmip); |
779 | error = -libxfs_defer_finish(&tp, &dfops); | |
2bd0ea18 | 780 | if (error) { |
9440d84d | 781 | fail(_("Error completing the realtime space"), error); |
2bd0ea18 | 782 | } |
de5a3f46 | 783 | libxfs_trans_commit(tp); |
2bd0ea18 NS |
784 | } |
785 | } | |
786 | ||
2bd0ea18 NS |
787 | static long |
788 | filesize( | |
789 | int fd) | |
790 | { | |
f594a0d1 | 791 | struct stat stb; |
2bd0ea18 | 792 | |
f594a0d1 | 793 | if (fstat(fd, &stb) < 0) |
2bd0ea18 NS |
794 | return -1; |
795 | return (long)stb.st_size; | |
796 | } |