OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

[/] [eco32/] [tags/] [eco32-0.22/] [disk/] [tools/] [fs-NetBSD/] [makefs/] [ffs.c] - Blame information for rev 185

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 17 hellwig
/*      $NetBSD: ffs.c,v 1.46 2012/01/28 02:35:46 christos Exp $        */
2
 
3
/*
4
 * Copyright (c) 2001 Wasabi Systems, Inc.
5
 * All rights reserved.
6
 *
7
 * Written by Luke Mewburn for Wasabi Systems, Inc.
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 * 3. All advertising materials mentioning features or use of this software
18
 *    must display the following acknowledgement:
19
 *      This product includes software developed for the NetBSD Project by
20
 *      Wasabi Systems, Inc.
21
 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22
 *    or promote products derived from this software without specific prior
23
 *    written permission.
24
 *
25
 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
29
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35
 * POSSIBILITY OF SUCH DAMAGE.
36
 */
37
/*
38
 * Copyright (c) 1982, 1986, 1989, 1993
39
 *      The Regents of the University of California.  All rights reserved.
40
 *
41
 * Redistribution and use in source and binary forms, with or without
42
 * modification, are permitted provided that the following conditions
43
 * are met:
44
 * 1. Redistributions of source code must retain the above copyright
45
 *    notice, this list of conditions and the following disclaimer.
46
 * 2. Redistributions in binary form must reproduce the above copyright
47
 *    notice, this list of conditions and the following disclaimer in the
48
 *    documentation and/or other materials provided with the distribution.
49
 * 3. Neither the name of the University nor the names of its contributors
50
 *    may be used to endorse or promote products derived from this software
51
 *    without specific prior written permission.
52
 *
53
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63
 * SUCH DAMAGE.
64
 *
65
 *      @(#)ffs_alloc.c 8.19 (Berkeley) 7/13/95
66
 */
67
 
68
#if HAVE_NBTOOL_CONFIG_H
69
#include "nbtool_config.h"
70
#endif
71
 
72
#include <sys/cdefs.h>
73
#if defined(__RCSID) && !defined(__lint)
74
__RCSID("$NetBSD: ffs.c,v 1.46 2012/01/28 02:35:46 christos Exp $");
75
#endif  /* !__lint */
76
 
77
#include <sys/param.h>
78
 
79
#if !HAVE_NBTOOL_CONFIG_H
80
#include <sys/mount.h>
81
#endif
82
 
83
#include <assert.h>
84
#include <errno.h>
85
#include <fcntl.h>
86
#include <stdarg.h>
87
#include <stdio.h>
88
#include <stdlib.h>
89
#include <string.h>
90
#include <unistd.h>
91
#include <time.h>
92
#include <sys/time.h>
93
 
94
#include "common.h"
95
#include "makefs.h"
96
#include "ffs.h"
97
 
98
#if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS
99
#include <sys/statvfs.h>
100
#endif
101
 
102
#include "dinode.h"
103
#include "dir.h"
104
#include "fs.h"
105
#include "ufs_bswap.h"
106
 
107
#include "ufs_inode.h"
108
#include "newfs_extern.h"
109
#include "ffs_extern.h"
110
 
111
#undef DIP
112
#define DIP(dp, field) \
113
        ((ffs_opts->version == 1) ? \
114
        (dp)->ffs1_din.di_##field : (dp)->ffs2_din.di_##field)
115
 
116
/*
117
 * Various file system defaults (cribbed from newfs(8)).
118
 */
119
#define DFL_FRAGSIZE            1024            /* fragment size */
120
#define DFL_BLKSIZE             8192            /* block size */
121
#define DFL_SECSIZE             512             /* sector size */
122
#define DFL_CYLSPERGROUP        65536           /* cylinders per group */
123
#define DFL_FRAGSPERINODE       4               /* fragments per inode */
124
#define DFL_ROTDELAY            0                /* rotational delay */
125
#define DFL_NRPOS               1               /* rotational positions */
126
#define DFL_RPM                 3600            /* rpm of disk */
127
#define DFL_NSECTORS            64              /* # of sectors */
128
#define DFL_NTRACKS             16              /* # of tracks */
129
 
130
 
131
typedef struct {
132
        u_char          *buf;           /* buf for directory */
133
        doff_t          size;           /* full size of buf */
134
        doff_t          cur;            /* offset of current entry */
135
} dirbuf_t;
136
 
137
 
138
static  int     ffs_create_image(const char *, fsinfo_t *);
139
static  void    ffs_dump_fsinfo(fsinfo_t *);
140
static  void    ffs_dump_dirbuf(dirbuf_t *, const char *, int);
141
static  void    ffs_make_dirbuf(dirbuf_t *, const char *, fsnode *, int);
142
static  int     ffs_populate_dir(const char *, fsnode *, fsinfo_t *);
143
static  void    ffs_size_dir(fsnode *, fsinfo_t *);
144
static  void    ffs_validate(const char *, fsnode *, fsinfo_t *);
145
static  void    ffs_write_file(union dinode *, uint32_t, void *, fsinfo_t *);
146
static  void    ffs_write_inode(union dinode *, uint32_t, const fsinfo_t *);
147
static  void    *ffs_build_dinode1(struct ufs1_dinode *, dirbuf_t *, fsnode *,
148
                                 fsnode *, fsinfo_t *);
149
static  void    *ffs_build_dinode2(struct ufs2_dinode *, dirbuf_t *, fsnode *,
150
                                 fsnode *, fsinfo_t *);
151
 
152
 
153
 
154
int     sectorsize;             /* XXX: for buf.c::getblk() */
155
 
156
        /* publically visible functions */
157
 
158
void
159
ffs_prep_opts(fsinfo_t *fsopts)
160
{
161
        ffs_opt_t *ffs_opts;
162
 
163
        if ((ffs_opts = calloc(1, sizeof(ffs_opt_t))) == NULL)
164
                err(1, "Allocating memory for ffs_options");
165
 
166
        fsopts->fs_specific = ffs_opts;
167
 
168
        ffs_opts->bsize= -1;
169
        ffs_opts->fsize= -1;
170
        ffs_opts->cpg= -1;
171
        ffs_opts->density= -1;
172
        ffs_opts->minfree= -1;
173
        ffs_opts->optimization= -1;
174
        ffs_opts->maxcontig= -1;
175
        ffs_opts->maxbpg= -1;
176
        ffs_opts->avgfilesize= -1;
177
        ffs_opts->avgfpdir= -1;
178
        ffs_opts->version = 1;
179
}
180
 
181
void
182
ffs_cleanup_opts(fsinfo_t *fsopts)
183
{
184
        if (fsopts->fs_specific)
185
                free(fsopts->fs_specific);
186
}
187
 
188
int
189
ffs_parse_opts(const char *option, fsinfo_t *fsopts)
190
{
191
        ffs_opt_t       *ffs_opts = fsopts->fs_specific;
192
 
193
        option_t ffs_options[] = {
194
                { "bsize",      &ffs_opts->bsize,       1,      INT_MAX,
195
                                        "block size" },
196
                { "fsize",      &ffs_opts->fsize,       1,      INT_MAX,
197
                                        "fragment size" },
198
                { "density",    &ffs_opts->density,     1,      INT_MAX,
199
                                        "bytes per inode" },
200
                { "minfree",    &ffs_opts->minfree,     0,       99,
201
                                        "minfree" },
202
                { "maxbpf",     &ffs_opts->maxbpg,      1,      INT_MAX,
203
                                        "max blocks per file in a cg" },
204
                { "avgfilesize", &ffs_opts->avgfilesize,1,      INT_MAX,
205
                                        "expected average file size" },
206
                { "avgfpdir",   &ffs_opts->avgfpdir,    1,      INT_MAX,
207
                                        "expected # of files per directory" },
208
                { "extent",     &ffs_opts->maxbsize,    1,      INT_MAX,
209
                                        "maximum # extent size" },
210
                { "maxbpcg",    &ffs_opts->maxblkspercg,1,      INT_MAX,
211
                                        "max # of blocks per group" },
212
                { "version",    &ffs_opts->version,     1,      2,
213
                                        "UFS version" },
214
                { .name = NULL }
215
        };
216
 
217
        char    *var, *val;
218
        int     rv;
219
 
220
        assert(option != NULL);
221
        assert(fsopts != NULL);
222
        assert(ffs_opts != NULL);
223
 
224
        if (debug & DEBUG_FS_PARSE_OPTS)
225
                printf("ffs_parse_opts: got `%s'\n", option);
226
 
227
        if ((var = strdup(option)) == NULL)
228
                err(1, "Allocating memory for copy of option string");
229
        rv = 0;
230
 
231
        if ((val = strchr(var, '=')) == NULL) {
232
                warnx("Option `%s' doesn't contain a value", var);
233
                goto leave_ffs_parse_opts;
234
        }
235
        *val++ = '\0';
236
 
237
        if (strcmp(var, "optimization") == 0) {
238
                if (strcmp(val, "time") == 0) {
239
                        ffs_opts->optimization = FS_OPTTIME;
240
                } else if (strcmp(val, "space") == 0) {
241
                        ffs_opts->optimization = FS_OPTSPACE;
242
                } else {
243
                        warnx("Invalid optimization `%s'", val);
244
                        goto leave_ffs_parse_opts;
245
                }
246
                rv = 1;
247
        } else if (strcmp(var, "label") == 0) {
248
                /* !!!!! HG: */
249
                //strlcpy(ffs_opts->label, val, sizeof(ffs_opts->label));
250
                strncpy(ffs_opts->label, val, sizeof(ffs_opts->label));
251
                /* :HG !!!!! */
252
                rv = 1;
253
        } else
254
                rv = set_option(ffs_options, var, val);
255
 
256
 leave_ffs_parse_opts:
257
        if (var)
258
                free(var);
259
        return (rv);
260
}
261
 
262
 
263
void
264
ffs_makefs(const char *image, const char *dir, fsnode *root, fsinfo_t *fsopts)
265
{
266
        struct fs       *superblock;
267
        struct timeval  start;
268
 
269
        assert(image != NULL);
270
        assert(dir != NULL);
271
        assert(root != NULL);
272
        assert(fsopts != NULL);
273
 
274
        if (debug & DEBUG_FS_MAKEFS)
275
                printf("ffs_makefs: image %s directory %s root %p\n",
276
                    image, dir, root);
277
 
278
                /* validate tree and options */
279
        TIMER_START(start);
280
        ffs_validate(dir, root, fsopts);
281
        TIMER_RESULTS(start, "ffs_validate");
282
 
283
        printf("Calculated size of `%s': %lld bytes, %lld inodes\n",
284
            image, (long long)fsopts->size, (long long)fsopts->inodes);
285
 
286
                /* create image */
287
        TIMER_START(start);
288
        if (ffs_create_image(image, fsopts) == -1)
289
                errx(1, "Image file `%s' not created.", image);
290
        TIMER_RESULTS(start, "ffs_create_image");
291
 
292
        fsopts->curinode = ROOTINO;
293
 
294
        if (debug & DEBUG_FS_MAKEFS)
295
                putchar('\n');
296
 
297
                /* populate image */
298
        printf("Populating `%s'\n", image);
299
        TIMER_START(start);
300
        if (! ffs_populate_dir(dir, root, fsopts))
301
                errx(1, "Image file `%s' not populated.", image);
302
        TIMER_RESULTS(start, "ffs_populate_dir");
303
 
304
                /* ensure no outstanding buffers remain */
305
        if (debug & DEBUG_FS_MAKEFS)
306
                bcleanup();
307
 
308
                /* update various superblock parameters */
309
        superblock = fsopts->superblock;
310
        superblock->fs_fmod = 0;
311
        superblock->fs_old_cstotal.cs_ndir   = superblock->fs_cstotal.cs_ndir;
312
        superblock->fs_old_cstotal.cs_nbfree = superblock->fs_cstotal.cs_nbfree;
313
        superblock->fs_old_cstotal.cs_nifree = superblock->fs_cstotal.cs_nifree;
314
        superblock->fs_old_cstotal.cs_nffree = superblock->fs_cstotal.cs_nffree;
315
 
316
                /* write out superblock; image is now complete */
317
        ffs_write_superblock(fsopts->superblock, fsopts);
318
        if (close(fsopts->fd) == -1)
319
                err(1, "Closing `%s'", image);
320
        fsopts->fd = -1;
321
        printf("Image `%s' complete\n", image);
322
}
323
 
324
        /* end of public functions */
325
 
326
 
327
static void
328
ffs_validate(const char *dir, fsnode *root, fsinfo_t *fsopts)
329
{
330
        int32_t ncg = 1;
331
#if notyet
332
        int32_t spc, nspf, ncyl, fssize;
333
#endif
334
        ffs_opt_t       *ffs_opts = fsopts->fs_specific;
335
 
336
        assert(dir != NULL);
337
        assert(root != NULL);
338
        assert(fsopts != NULL);
339
        assert(ffs_opts != NULL);
340
 
341
        if (debug & DEBUG_FS_VALIDATE) {
342
                printf("ffs_validate: before defaults set:\n");
343
                ffs_dump_fsinfo(fsopts);
344
        }
345
 
346
                /* set FFS defaults */
347
        if (fsopts->sectorsize == -1)
348
                fsopts->sectorsize = DFL_SECSIZE;
349
        if (ffs_opts->fsize == -1)
350
                ffs_opts->fsize = MAX(DFL_FRAGSIZE, fsopts->sectorsize);
351
        if (ffs_opts->bsize == -1)
352
                ffs_opts->bsize = MIN(DFL_BLKSIZE, 8 * ffs_opts->fsize);
353
        if (ffs_opts->cpg == -1)
354
                ffs_opts->cpg = DFL_CYLSPERGROUP;
355
        else
356
                ffs_opts->cpgflg = 1;
357
                                /* fsopts->density is set below */
358
        if (ffs_opts->nsectors == -1)
359
                ffs_opts->nsectors = DFL_NSECTORS;
360
        if (ffs_opts->minfree == -1)
361
                ffs_opts->minfree = MINFREE;
362
        if (ffs_opts->optimization == -1)
363
                ffs_opts->optimization = DEFAULTOPT;
364
        if (ffs_opts->maxcontig == -1)
365
                ffs_opts->maxcontig =
366
                    MAX(1, MIN(MAXPHYS, FFS_MAXBSIZE) / ffs_opts->bsize);
367
        /* XXX ondisk32 */
368
        if (ffs_opts->maxbpg == -1)
369
                ffs_opts->maxbpg = ffs_opts->bsize / sizeof(int32_t);
370
        if (ffs_opts->avgfilesize == -1)
371
                ffs_opts->avgfilesize = AVFILESIZ;
372
        if (ffs_opts->avgfpdir == -1)
373
                ffs_opts->avgfpdir = AFPDIR;
374
 
375
                /* calculate size of tree */
376
        ffs_size_dir(root, fsopts);
377
        fsopts->inodes += ROOTINO;              /* include first two inodes */
378
 
379
        if (debug & DEBUG_FS_VALIDATE)
380
                printf("ffs_validate: size of tree: %lld bytes, %lld inodes\n",
381
                    (long long)fsopts->size, (long long)fsopts->inodes);
382
 
383
                /* add requested slop */
384
        fsopts->size += fsopts->freeblocks;
385
        fsopts->inodes += fsopts->freefiles;
386
        if (fsopts->freefilepc > 0)
387
                fsopts->inodes =
388
                    fsopts->inodes * (100 + fsopts->freefilepc) / 100;
389
        if (fsopts->freeblockpc > 0)
390
                fsopts->size =
391
                    fsopts->size * (100 + fsopts->freeblockpc) / 100;
392
 
393
                /* add space needed for superblocks */
394
        /*
395
         * The old SBOFF (SBLOCK_UFS1) is used here because makefs is
396
         * typically used for small filesystems where space matters.
397
         * XXX make this an option.
398
         */
399
        fsopts->size += (SBLOCK_UFS1 + SBLOCKSIZE) * ncg;
400
                /* add space needed to store inodes, x3 for blockmaps, etc */
401
        if (ffs_opts->version == 1)
402
                fsopts->size += ncg * DINODE1_SIZE *
403
                    roundup(fsopts->inodes / ncg,
404
                        ffs_opts->bsize / DINODE1_SIZE);
405
        else
406
                fsopts->size += ncg * DINODE2_SIZE *
407
                    roundup(fsopts->inodes / ncg,
408
                        ffs_opts->bsize / DINODE2_SIZE);
409
 
410
                /* add minfree */
411
        if (ffs_opts->minfree > 0)
412
                fsopts->size =
413
                    fsopts->size * (100 + ffs_opts->minfree) / 100;
414
        /*
415
         * XXX  any other fs slop to add, such as csum's, bitmaps, etc ??
416
         */
417
 
418
        if (fsopts->size < fsopts->minsize)     /* ensure meets minimum size */
419
                fsopts->size = fsopts->minsize;
420
 
421
                /* round up to the next block */
422
        fsopts->size = roundup(fsopts->size, ffs_opts->bsize);
423
 
424
                /* calculate density if necessary */
425
        if (ffs_opts->density == -1)
426
                ffs_opts->density = fsopts->size / fsopts->inodes + 1;
427
 
428
        if (debug & DEBUG_FS_VALIDATE) {
429
                printf("ffs_validate: after defaults set:\n");
430
                ffs_dump_fsinfo(fsopts);
431
                printf("ffs_validate: dir %s; %lld bytes, %lld inodes\n",
432
                    dir, (long long)fsopts->size, (long long)fsopts->inodes);
433
        }
434
        sectorsize = fsopts->sectorsize;        /* XXX - see earlier */
435
 
436
                /* now check calculated sizes vs requested sizes */
437
        if (fsopts->maxsize > 0 && fsopts->size > fsopts->maxsize) {
438
                errx(1, "`%s' size of %lld is larger than the maxsize of %lld.",
439
                    dir, (long long)fsopts->size, (long long)fsopts->maxsize);
440
        }
441
}
442
 
443
 
444
static void
445
ffs_dump_fsinfo(fsinfo_t *f)
446
{
447
 
448
        ffs_opt_t       *fs = f->fs_specific;
449
 
450
        printf("fsopts at %p\n", f);
451
 
452
        printf("\tsize %lld, inodes %lld, curinode %u\n",
453
            (long long)f->size, (long long)f->inodes, f->curinode);
454
 
455
        printf("\tminsize %lld, maxsize %lld\n",
456
            (long long)f->minsize, (long long)f->maxsize);
457
        printf("\tfree files %lld, freefile %% %d\n",
458
            (long long)f->freefiles, f->freefilepc);
459
        printf("\tfree blocks %lld, freeblock %% %d\n",
460
            (long long)f->freeblocks, f->freeblockpc);
461
        printf("\tneedswap %d, sectorsize %d\n", f->needswap, f->sectorsize);
462
 
463
        printf("\tbsize %d, fsize %d, cpg %d, density %d\n",
464
            fs->bsize, fs->fsize, fs->cpg, fs->density);
465
        printf("\tnsectors %d, rpm %d, minfree %d\n",
466
            fs->nsectors, fs->rpm, fs->minfree);
467
        printf("\tmaxcontig %d, maxbpg %d\n",
468
            fs->maxcontig, fs->maxbpg);
469
        printf("\toptimization %s\n",
470
            fs->optimization == FS_OPTSPACE ? "space" : "time");
471
}
472
 
473
 
474
static int
475
ffs_create_image(const char *image, fsinfo_t *fsopts)
476
{
477
#if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS
478
        struct statvfs  sfs;
479
#endif
480
        struct fs       *fs;
481
        char    *buf;
482
        int     i, bufsize;
483
        off_t   bufrem;
484
 
485
        assert (image != NULL);
486
        assert (fsopts != NULL);
487
 
488
                /* create image */
489
        if ((fsopts->fd = open(image, O_RDWR | O_CREAT | O_TRUNC, 0666))
490
            == -1) {
491
                warn("Can't open `%s' for writing", image);
492
                return (-1);
493
        }
494
 
495
                /* zero image */
496
#if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS
497
        if (fstatvfs(fsopts->fd, &sfs) == -1) {
498
#endif
499
                bufsize = 8192;
500
#if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS
501
                warn("can't fstatvfs `%s', using default %d byte chunk",
502
                    image, bufsize);
503
        } else
504
                bufsize = sfs.f_iosize;
505
#endif
506
        bufrem = fsopts->size;
507
        if (debug & DEBUG_FS_CREATE_IMAGE)
508
                printf(
509
                    "zero-ing image `%s', %lld sectors, using %d byte chunks\n",
510
                    image, (long long)bufrem, bufsize);
511
        if ((buf = calloc(1, bufsize)) == NULL) {
512
                warn("Can't create buffer for sector");
513
                return (-1);
514
        }
515
        while (bufrem > 0) {
516
                i = write(fsopts->fd, buf, MIN(bufsize, bufrem));
517
                if (i == -1) {
518
                        warn("zeroing image, %lld bytes to go",
519
                            (long long)bufrem);
520
                        free(buf);
521
                        return (-1);
522
                }
523
                bufrem -= i;
524
        }
525
        free(buf);
526
 
527
                /* make the file system */
528
        if (debug & DEBUG_FS_CREATE_IMAGE)
529
                printf("calling mkfs(\"%s\", ...)\n", image);
530
        fs = ffs_mkfs(image, fsopts);
531
        fsopts->superblock = (void *)fs;
532
        if (debug & DEBUG_FS_CREATE_IMAGE) {
533
                time_t t;
534
 
535
                t = (time_t)((struct fs *)fsopts->superblock)->fs_time;
536
                printf("mkfs returned %p; fs_time %s",
537
                    fsopts->superblock, ctime(&t));
538
                printf("fs totals: nbfree %lld, nffree %lld, nifree %lld, ndir %lld\n",
539
                    (long long)fs->fs_cstotal.cs_nbfree,
540
                    (long long)fs->fs_cstotal.cs_nffree,
541
                    (long long)fs->fs_cstotal.cs_nifree,
542
                    (long long)fs->fs_cstotal.cs_ndir);
543
        }
544
 
545
        if (fs->fs_cstotal.cs_nifree + ROOTINO < fsopts->inodes) {
546
                warnx(
547
                "Image file `%s' has %lld free inodes; %lld are required.",
548
                    image,
549
                    (long long)(fs->fs_cstotal.cs_nifree + ROOTINO),
550
                    (long long)fsopts->inodes);
551
                return (-1);
552
        }
553
        return (fsopts->fd);
554
}
555
 
556
 
557
static void
558
ffs_size_dir(fsnode *root, fsinfo_t *fsopts)
559
{
560
        struct direct   tmpdir;
561
        fsnode *        node;
562
        int             curdirsize, this;
563
        ffs_opt_t       *ffs_opts = fsopts->fs_specific;
564
 
565
        /* node may be NULL (empty directory) */
566
        assert(fsopts != NULL);
567
        assert(ffs_opts != NULL);
568
 
569
        if (debug & DEBUG_FS_SIZE_DIR)
570
                printf("ffs_size_dir: entry: bytes %lld inodes %lld\n",
571
                    (long long)fsopts->size, (long long)fsopts->inodes);
572
 
573
#define ADDDIRENT(e) do {                                               \
574
        tmpdir.d_namlen = strlen((e));                                  \
575
        this = DIRSIZ(0, &tmpdir, 0);                                     \
576
        if (debug & DEBUG_FS_SIZE_DIR_ADD_DIRENT)                       \
577
                printf("ADDDIRENT: was: %s (%d) this %d cur %d\n",      \
578
                    e, tmpdir.d_namlen, this, curdirsize);              \
579
        if (this + curdirsize > roundup(curdirsize, DIRBLKSIZ))         \
580
                curdirsize = roundup(curdirsize, DIRBLKSIZ);            \
581
        curdirsize += this;                                             \
582
        if (debug & DEBUG_FS_SIZE_DIR_ADD_DIRENT)                       \
583
                printf("ADDDIRENT: now: %s (%d) this %d cur %d\n",      \
584
                    e, tmpdir.d_namlen, this, curdirsize);              \
585
} while (0);
586
 
587
        /*
588
         * XXX  this needs to take into account extra space consumed
589
         *      by indirect blocks, etc.
590
         */
591
#define ADDSIZE(x) do {                                                 \
592
        fsopts->size += roundup((x), ffs_opts->fsize);                  \
593
} while (0);
594
 
595
        curdirsize = 0;
596
        for (node = root; node != NULL; node = node->next) {
597
                ADDDIRENT(node->name);
598
                if (node == root) {                     /* we're at "." */
599
                        assert(strcmp(node->name, ".") == 0);
600
                        ADDDIRENT("..");
601
                } else if ((node->inode->flags & FI_SIZED) == 0) {
602
                                /* don't count duplicate names */
603
                        node->inode->flags |= FI_SIZED;
604
                        if (debug & DEBUG_FS_SIZE_DIR_NODE)
605
                                printf("ffs_size_dir: `%s' size %lld\n",
606
                                    node->name,
607
                                    (long long)node->inode->st.st_size);
608
                        fsopts->inodes++;
609
                        if (node->type == S_IFREG)
610
                                ADDSIZE(node->inode->st.st_size);
611
                        if (node->type == S_IFLNK) {
612
                                int     slen;
613
 
614
                                slen = strlen(node->symlink) + 1;
615
                                if (slen >= (ffs_opts->version == 1 ?
616
                                                MAXSYMLINKLEN_UFS1 :
617
                                                MAXSYMLINKLEN_UFS2))
618
                                        ADDSIZE(slen);
619
                        }
620
                }
621
                if (node->type == S_IFDIR)
622
                        ffs_size_dir(node->child, fsopts);
623
        }
624
        ADDSIZE(curdirsize);
625
 
626
        if (debug & DEBUG_FS_SIZE_DIR)
627
                printf("ffs_size_dir: exit: size %lld inodes %lld\n",
628
                    (long long)fsopts->size, (long long)fsopts->inodes);
629
}
630
 
631
static void *
632
ffs_build_dinode1(struct ufs1_dinode *dinp, dirbuf_t *dbufp, fsnode *cur,
633
                 fsnode *root, fsinfo_t *fsopts)
634
{
635
        int slen;
636
        void *membuf;
637
 
638
        memset(dinp, 0, sizeof(*dinp));
639
        dinp->di_mode = cur->inode->st.st_mode;
640
        dinp->di_nlink = cur->inode->nlink;
641
        dinp->di_size = cur->inode->st.st_size;
642
        dinp->di_atime = cur->inode->st.st_atime;
643
        dinp->di_mtime = cur->inode->st.st_mtime;
644
        dinp->di_ctime = cur->inode->st.st_ctime;
645
#if HAVE_STRUCT_STAT_ST_MTIMENSEC
646
        dinp->di_atimensec = cur->inode->st.st_atimensec;
647
        dinp->di_mtimensec = cur->inode->st.st_mtimensec;
648
        dinp->di_ctimensec = cur->inode->st.st_ctimensec;
649
#endif
650
#if HAVE_STRUCT_STAT_ST_FLAGS
651
        dinp->di_flags = cur->inode->st.st_flags;
652
#endif
653
#if HAVE_STRUCT_STAT_ST_GEN
654
        dinp->di_gen = cur->inode->st.st_gen;
655
#endif
656
        dinp->di_uid = cur->inode->st.st_uid;
657
        dinp->di_gid = cur->inode->st.st_gid;
658
                /* not set: di_db, di_ib, di_blocks, di_spare */
659
 
660
        membuf = NULL;
661
        if (cur == root) {                      /* "."; write dirbuf */
662
                membuf = dbufp->buf;
663
                dinp->di_size = dbufp->size;
664
        } else if (S_ISBLK(cur->type) || S_ISCHR(cur->type)) {
665
                dinp->di_size = 0;       /* a device */
666
                dinp->di_rdev =
667
                    ufs_rw32(cur->inode->st.st_rdev, fsopts->needswap);
668
        } else if (S_ISLNK(cur->type)) {        /* symlink */
669
                slen = strlen(cur->symlink);
670
                if (slen < MAXSYMLINKLEN_UFS1) {        /* short link */
671
                        memcpy(dinp->di_db, cur->symlink, slen);
672
                } else
673
                        membuf = cur->symlink;
674
                dinp->di_size = slen;
675
        }
676
        return membuf;
677
}
678
 
679
static void *
680
ffs_build_dinode2(struct ufs2_dinode *dinp, dirbuf_t *dbufp, fsnode *cur,
681
                 fsnode *root, fsinfo_t *fsopts)
682
{
683
        int slen;
684
        void *membuf;
685
 
686
        memset(dinp, 0, sizeof(*dinp));
687
        dinp->di_mode = cur->inode->st.st_mode;
688
        dinp->di_nlink = cur->inode->nlink;
689
        dinp->di_size = cur->inode->st.st_size;
690
        dinp->di_atime = cur->inode->st.st_atime;
691
        dinp->di_mtime = cur->inode->st.st_mtime;
692
        dinp->di_ctime = cur->inode->st.st_ctime;
693
#if HAVE_STRUCT_STAT_ST_MTIMENSEC
694
        dinp->di_atimensec = cur->inode->st.st_atimensec;
695
        dinp->di_mtimensec = cur->inode->st.st_mtimensec;
696
        dinp->di_ctimensec = cur->inode->st.st_ctimensec;
697
#endif
698
#if HAVE_STRUCT_STAT_ST_FLAGS
699
        dinp->di_flags = cur->inode->st.st_flags;
700
#endif
701
#if HAVE_STRUCT_STAT_ST_GEN
702
        dinp->di_gen = cur->inode->st.st_gen;
703
#endif
704
#if HAVE_STRUCT_STAT_BIRTHTIME
705
        dinp->di_birthtime = cur->inode->st.st_birthtime;
706
        dinp->di_birthnsec = cur->inode->st.st_birthtimensec;
707
#endif
708
        dinp->di_uid = cur->inode->st.st_uid;
709
        dinp->di_gid = cur->inode->st.st_gid;
710
                /* not set: di_db, di_ib, di_blocks, di_spare */
711
 
712
        membuf = NULL;
713
        if (cur == root) {                      /* "."; write dirbuf */
714
                membuf = dbufp->buf;
715
                dinp->di_size = dbufp->size;
716
        } else if (S_ISBLK(cur->type) || S_ISCHR(cur->type)) {
717
                dinp->di_size = 0;       /* a device */
718
                dinp->di_rdev =
719
                    ufs_rw64(cur->inode->st.st_rdev, fsopts->needswap);
720
        } else if (S_ISLNK(cur->type)) {        /* symlink */
721
                slen = strlen(cur->symlink);
722
                if (slen < MAXSYMLINKLEN_UFS2) {        /* short link */
723
                        memcpy(dinp->di_db, cur->symlink, slen);
724
                } else
725
                        membuf = cur->symlink;
726
                dinp->di_size = slen;
727
        }
728
        return membuf;
729
}
730
 
731
static int
732
ffs_populate_dir(const char *dir, fsnode *root, fsinfo_t *fsopts)
733
{
734
        fsnode          *cur;
735
        dirbuf_t        dirbuf;
736
        union dinode    din;
737
        void            *membuf;
738
        char            path[MAXPATHLEN + 1];
739
        ffs_opt_t       *ffs_opts = fsopts->fs_specific;
740
 
741
        assert(dir != NULL);
742
        assert(root != NULL);
743
        assert(fsopts != NULL);
744
        assert(ffs_opts != NULL);
745
 
746
        (void)memset(&dirbuf, 0, sizeof(dirbuf));
747
 
748
        if (debug & DEBUG_FS_POPULATE)
749
                printf("ffs_populate_dir: PASS 1  dir %s node %p\n", dir, root);
750
 
751
                /*
752
                 * pass 1: allocate inode numbers, build directory `file'
753
                 */
754
        for (cur = root; cur != NULL; cur = cur->next) {
755
                if ((cur->inode->flags & FI_ALLOCATED) == 0) {
756
                        cur->inode->flags |= FI_ALLOCATED;
757
                        if (cur == root && cur->parent != NULL)
758
                                cur->inode->ino = cur->parent->inode->ino;
759
                        else {
760
                                cur->inode->ino = fsopts->curinode;
761
                                fsopts->curinode++;
762
                        }
763
                }
764
                ffs_make_dirbuf(&dirbuf, cur->name, cur, fsopts->needswap);
765
                if (cur == root) {              /* we're at "."; add ".." */
766
                        ffs_make_dirbuf(&dirbuf, "..",
767
                            cur->parent == NULL ? cur : cur->parent->first,
768
                            fsopts->needswap);
769
                        root->inode->nlink++;   /* count my parent's link */
770
                } else if (cur->child != NULL)
771
                        root->inode->nlink++;   /* count my child's link */
772
 
773
                /*
774
                 * XXX  possibly write file and long symlinks here,
775
                 *      ensuring that blocks get written before inodes?
776
                 *      otoh, this isn't a real filesystem, so who
777
                 *      cares about ordering? :-)
778
                 */
779
        }
780
        if (debug & DEBUG_FS_POPULATE_DIRBUF)
781
                ffs_dump_dirbuf(&dirbuf, dir, fsopts->needswap);
782
 
783
                /*
784
                 * pass 2: write out dirbuf, then non-directories at this level
785
                 */
786
        if (debug & DEBUG_FS_POPULATE)
787
                printf("ffs_populate_dir: PASS 2  dir %s\n", dir);
788
        for (cur = root; cur != NULL; cur = cur->next) {
789
                if (cur->inode->flags & FI_WRITTEN)
790
                        continue;               /* skip hard-linked entries */
791
                cur->inode->flags |= FI_WRITTEN;
792
 
793
                if ((size_t)snprintf(path, sizeof(path), "%s/%s/%s", cur->root,
794
                    cur->path, cur->name) >= sizeof(path))
795
                        errx(1, "Pathname too long.");
796
 
797
                if (cur->child != NULL)
798
                        continue;               /* child creates own inode */
799
 
800
                                /* build on-disk inode */
801
                if (ffs_opts->version == 1)
802
                        membuf = ffs_build_dinode1(&din.ffs1_din, &dirbuf, cur,
803
                            root, fsopts);
804
                else
805
                        membuf = ffs_build_dinode2(&din.ffs2_din, &dirbuf, cur,
806
                            root, fsopts);
807
 
808
                if (debug & DEBUG_FS_POPULATE_NODE) {
809
                        printf("ffs_populate_dir: writing ino %d, %s",
810
                            cur->inode->ino, inode_type(cur->type));
811
                        if (cur->inode->nlink > 1)
812
                                printf(", nlink %d", cur->inode->nlink);
813
                        putchar('\n');
814
                }
815
 
816
                if (membuf != NULL) {
817
                        ffs_write_file(&din, cur->inode->ino, membuf, fsopts);
818
                } else if (S_ISREG(cur->type)) {
819
                        ffs_write_file(&din, cur->inode->ino, path, fsopts);
820
                } else {
821
                        assert (! S_ISDIR(cur->type));
822
                        ffs_write_inode(&din, cur->inode->ino, fsopts);
823
                }
824
        }
825
 
826
                /*
827
                 * pass 3: write out sub-directories
828
                 */
829
        if (debug & DEBUG_FS_POPULATE)
830
                printf("ffs_populate_dir: PASS 3  dir %s\n", dir);
831
        for (cur = root; cur != NULL; cur = cur->next) {
832
                if (cur->child == NULL)
833
                        continue;
834
                if (snprintf(path, sizeof(path), "%s/%s", dir, cur->name)
835
                    >= sizeof(path))
836
                        errx(1, "Pathname too long.");
837
                if (! ffs_populate_dir(path, cur->child, fsopts))
838
                        return (0);
839
        }
840
 
841
        if (debug & DEBUG_FS_POPULATE)
842
                printf("ffs_populate_dir: DONE dir %s\n", dir);
843
 
844
                /* cleanup */
845
        if (dirbuf.buf != NULL)
846
                free(dirbuf.buf);
847
        return (1);
848
}
849
 
850
 
851
static void
852
ffs_write_file(union dinode *din, uint32_t ino, void *buf, fsinfo_t *fsopts)
853
{
854
        int     isfile, ffd;
855
        char    *fbuf, *p;
856
        off_t   bufleft, chunk, offset;
857
        ssize_t nread;
858
        struct inode    in;
859
        struct buf *    bp;
860
        ffs_opt_t       *ffs_opts = fsopts->fs_specific;
861
 
862
        assert (din != NULL);
863
        assert (buf != NULL);
864
        assert (fsopts != NULL);
865
        assert (ffs_opts != NULL);
866
 
867
        isfile = S_ISREG(DIP(din, mode));
868
        fbuf = NULL;
869
        ffd = -1;
870
        p = NULL;
871
 
872
        in.i_fs = (struct fs *)fsopts->superblock;
873
 
874
        if (debug & DEBUG_FS_WRITE_FILE) {
875
                printf(
876
                    "ffs_write_file: ino %u, din %p, isfile %d, %s, size %lld",
877
                    ino, din, isfile, inode_type(DIP(din, mode) & S_IFMT),
878
                    (long long)DIP(din, size));
879
                if (isfile)
880
                        printf(", file '%s'\n", (char *)buf);
881
                else
882
                        printf(", buffer %p\n", buf);
883
        }
884
 
885
        in.i_number = ino;
886
        in.i_size = DIP(din, size);
887
        if (ffs_opts->version == 1)
888
                memcpy(&in.i_din.ffs1_din, &din->ffs1_din,
889
                    sizeof(in.i_din.ffs1_din));
890
        else
891
                memcpy(&in.i_din.ffs2_din, &din->ffs2_din,
892
                    sizeof(in.i_din.ffs2_din));
893
        in.i_fd = fsopts->fd;
894
 
895
        if (DIP(din, size) == 0)
896
                goto write_inode_and_leave;             /* mmm, cheating */
897
 
898
        if (isfile) {
899
                if ((fbuf = malloc(ffs_opts->bsize)) == NULL)
900
                        err(1, "Allocating memory for write buffer");
901
                if ((ffd = open((char *)buf, O_RDONLY, 0444)) == -1) {
902
                        warn("Can't open `%s' for reading", (char *)buf);
903
                        goto leave_ffs_write_file;
904
                }
905
        } else {
906
                p = buf;
907
        }
908
 
909
        chunk = 0;
910
        for (bufleft = DIP(din, size); bufleft > 0; bufleft -= chunk) {
911
                chunk = MIN(bufleft, ffs_opts->bsize);
912
                if (!isfile)
913
                        ;
914
                else if ((nread = read(ffd, fbuf, chunk)) == -1)
915
                        err(EXIT_FAILURE, "Reading `%s', %lld bytes to go",
916
                            (char *)buf, (long long)bufleft);
917
                else if (nread != chunk)
918
                        errx(EXIT_FAILURE, "Reading `%s', %lld bytes to go, "
919
                            "read %zd bytes, expected %ju bytes, does "
920
                            "metalog size= attribute mismatch source size?",
921
                            (char *)buf, (long long)bufleft, nread,
922
                            (uintmax_t)chunk);
923
                else
924
                        p = fbuf;
925
                offset = DIP(din, size) - bufleft;
926
                if (debug & DEBUG_FS_WRITE_FILE_BLOCK)
927
                        printf(
928
                "ffs_write_file: write %p offset %lld size %lld left %lld\n",
929
                            p, (long long)offset,
930
                            (long long)chunk, (long long)bufleft);
931
        /*
932
         * XXX  if holey support is desired, do the check here
933
         *
934
         * XXX  might need to write out last bit in fragroundup
935
         *      sized chunk. however, ffs_balloc() handles this for us
936
         */
937
                errno = ffs_balloc(&in, offset, chunk, &bp);
938
 bad_ffs_write_file:
939
                if (errno != 0)
940
                        err(1,
941
                            "Writing inode %d (%s), bytes %lld + %lld",
942
                            ino,
943
                            isfile ? (char *)buf :
944
                              inode_type(DIP(din, mode) & S_IFMT),
945
                            (long long)offset, (long long)chunk);
946
                memcpy(bp->b_data, p, chunk);
947
                errno = bwrite(bp);
948
                if (errno != 0)
949
                        goto bad_ffs_write_file;
950
                brelse(bp);
951
                if (!isfile)
952
                        p += chunk;
953
        }
954
 
955
 write_inode_and_leave:
956
        ffs_write_inode(&in.i_din, in.i_number, fsopts);
957
 
958
 leave_ffs_write_file:
959
        if (fbuf)
960
                free(fbuf);
961
        if (ffd != -1)
962
                close(ffd);
963
}
964
 
965
 
966
static void
967
ffs_dump_dirbuf(dirbuf_t *dbuf, const char *dir, int needswap)
968
{
969
        doff_t          i;
970
        struct direct   *de;
971
        uint16_t        reclen;
972
 
973
        assert (dbuf != NULL);
974
        assert (dir != NULL);
975
        printf("ffs_dump_dirbuf: dir %s size %d cur %d\n",
976
            dir, dbuf->size, dbuf->cur);
977
 
978
        for (i = 0; i < dbuf->size; ) {
979
                de = (struct direct *)(dbuf->buf + i);
980
                reclen = ufs_rw16(de->d_reclen, needswap);
981
                printf(
982
            " inode %4d %7s offset %4d reclen %3d namlen %3d name %s\n",
983
                    ufs_rw32(de->d_fileno, needswap),
984
                    inode_type(DTTOIF(de->d_type)), i, reclen,
985
                    de->d_namlen, de->d_name);
986
                i += reclen;
987
                assert(reclen > 0);
988
        }
989
}
990
 
991
static void
992
ffs_make_dirbuf(dirbuf_t *dbuf, const char *name, fsnode *node, int needswap)
993
{
994
        struct direct   de, *dp;
995
        uint16_t        llen, reclen;
996
        u_char          *newbuf;
997
 
998
        assert (dbuf != NULL);
999
        assert (name != NULL);
1000
        assert (node != NULL);
1001
                                        /* create direct entry */
1002
        (void)memset(&de, 0, sizeof(de));
1003
        de.d_fileno = ufs_rw32(node->inode->ino, needswap);
1004
        de.d_type = IFTODT(node->type);
1005
        de.d_namlen = (uint8_t)strlen(name);
1006
        strcpy(de.d_name, name);
1007
        reclen = DIRSIZ(0, &de, needswap);
1008
        de.d_reclen = ufs_rw16(reclen, needswap);
1009
 
1010
        dp = (struct direct *)(dbuf->buf + dbuf->cur);
1011
        llen = 0;
1012
        if (dp != NULL)
1013
                llen = DIRSIZ(0, dp, needswap);
1014
 
1015
        if (debug & DEBUG_FS_MAKE_DIRBUF)
1016
                printf(
1017
                    "ffs_make_dirbuf: dbuf siz %d cur %d lastlen %d\n"
1018
                    "  ino %d type %d reclen %d namlen %d name %.30s\n",
1019
                    dbuf->size, dbuf->cur, llen,
1020
                    ufs_rw32(de.d_fileno, needswap), de.d_type, reclen,
1021
                    de.d_namlen, de.d_name);
1022
 
1023
        if (reclen + dbuf->cur + llen > roundup(dbuf->size, DIRBLKSIZ)) {
1024
                if (debug & DEBUG_FS_MAKE_DIRBUF)
1025
                        printf("ffs_make_dirbuf: growing buf to %d\n",
1026
                            dbuf->size + DIRBLKSIZ);
1027
                if ((newbuf = realloc(dbuf->buf, dbuf->size + DIRBLKSIZ)) == NULL)
1028
                        err(1, "Allocating memory for directory buffer");
1029
                dbuf->buf = newbuf;
1030
                dbuf->size += DIRBLKSIZ;
1031
                memset(dbuf->buf + dbuf->size - DIRBLKSIZ, 0, DIRBLKSIZ);
1032
                dbuf->cur = dbuf->size - DIRBLKSIZ;
1033
        } else if (dp) {                        /* shrink end of previous */
1034
                dp->d_reclen = ufs_rw16(llen,needswap);
1035
                dbuf->cur += llen;
1036
        }
1037
        dp = (struct direct *)(dbuf->buf + dbuf->cur);
1038
        memcpy(dp, &de, reclen);
1039
        dp->d_reclen = ufs_rw16(dbuf->size - dbuf->cur, needswap);
1040
}
1041
 
1042
/*
1043
 * cribbed from sys/ufs/ffs/ffs_alloc.c
1044
 */
1045
static void
1046
ffs_write_inode(union dinode *dp, uint32_t ino, const fsinfo_t *fsopts)
1047
{
1048
        char            *buf;
1049
        struct ufs1_dinode *dp1;
1050
        struct ufs2_dinode *dp2, *dip;
1051
        struct cg       *cgp;
1052
        struct fs       *fs;
1053
        int             cg, cgino, i;
1054
        daddr_t         d;
1055
        char            sbbuf[FFS_MAXBSIZE];
1056
        int32_t         initediblk;
1057
        ffs_opt_t       *ffs_opts = fsopts->fs_specific;
1058
 
1059
        assert (dp != NULL);
1060
        assert (ino > 0);
1061
        assert (fsopts != NULL);
1062
        assert (ffs_opts != NULL);
1063
 
1064
        fs = (struct fs *)fsopts->superblock;
1065
        cg = ino_to_cg(fs, ino);
1066
        cgino = ino % fs->fs_ipg;
1067
        if (debug & DEBUG_FS_WRITE_INODE)
1068
                printf("ffs_write_inode: din %p ino %u cg %d cgino %d\n",
1069
                    dp, ino, cg, cgino);
1070
 
1071
        ffs_rdfs(fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, &sbbuf,
1072
            fsopts);
1073
        cgp = (struct cg *)sbbuf;
1074
        if (!cg_chkmagic(cgp, fsopts->needswap))
1075
                errx(1, "ffs_write_inode: cg %d: bad magic number", cg);
1076
 
1077
        assert (isclr(cg_inosused(cgp, fsopts->needswap), cgino));
1078
 
1079
        buf = malloc(fs->fs_bsize);
1080
        if (buf == NULL)
1081
                errx(1, "ffs_write_inode: cg %d: can't alloc inode block", cg);
1082
 
1083
        dp1 = (struct ufs1_dinode *)buf;
1084
        dp2 = (struct ufs2_dinode *)buf;
1085
 
1086
        if (fs->fs_cstotal.cs_nifree == 0)
1087
                errx(1, "ffs_write_inode: fs out of inodes for ino %u",
1088
                    ino);
1089
        if (fs->fs_cs(fs, cg).cs_nifree == 0)
1090
                errx(1,
1091
                    "ffs_write_inode: cg %d out of inodes for ino %u",
1092
                    cg, ino);
1093
        setbit(cg_inosused(cgp, fsopts->needswap), cgino);
1094
        ufs_add32(cgp->cg_cs.cs_nifree, -1, fsopts->needswap);
1095
        fs->fs_cstotal.cs_nifree--;
1096
        fs->fs_cs(fs, cg).cs_nifree--;
1097
        if (S_ISDIR(DIP(dp, mode))) {
1098
                ufs_add32(cgp->cg_cs.cs_ndir, 1, fsopts->needswap);
1099
                fs->fs_cstotal.cs_ndir++;
1100
                fs->fs_cs(fs, cg).cs_ndir++;
1101
        }
1102
 
1103
        /*
1104
         * Initialize inode blocks on the fly for UFS2.
1105
         */
1106
        initediblk = ufs_rw32(cgp->cg_initediblk, fsopts->needswap);
1107
        if (ffs_opts->version == 2 && cgino + INOPB(fs) > initediblk &&
1108
            initediblk < ufs_rw32(cgp->cg_niblk, fsopts->needswap)) {
1109
                memset(buf, 0, fs->fs_bsize);
1110
                dip = (struct ufs2_dinode *)buf;
1111
                srandom(time(NULL));
1112
                for (i = 0; i < INOPB(fs); i++) {
1113
                        dip->di_gen = random() / 2 + 1;
1114
                        dip++;
1115
                }
1116
                ffs_wtfs(fsbtodb(fs, ino_to_fsba(fs,
1117
                                  cg * fs->fs_ipg + initediblk)),
1118
                    fs->fs_bsize, buf, fsopts);
1119
                initediblk += INOPB(fs);
1120
                cgp->cg_initediblk = ufs_rw32(initediblk, fsopts->needswap);
1121
        }
1122
 
1123
 
1124
        ffs_wtfs(fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, &sbbuf,
1125
            fsopts);
1126
 
1127
                                        /* now write inode */
1128
        d = fsbtodb(fs, ino_to_fsba(fs, ino));
1129
        ffs_rdfs(d, fs->fs_bsize, buf, fsopts);
1130
        if (fsopts->needswap) {
1131
                if (ffs_opts->version == 1)
1132
                        ffs_dinode1_swap(&dp->ffs1_din,
1133
                            &dp1[ino_to_fsbo(fs, ino)]);
1134
                else
1135
                        ffs_dinode2_swap(&dp->ffs2_din,
1136
                            &dp2[ino_to_fsbo(fs, ino)]);
1137
        } else {
1138
                if (ffs_opts->version == 1)
1139
                        dp1[ino_to_fsbo(fs, ino)] = dp->ffs1_din;
1140
                else
1141
                        dp2[ino_to_fsbo(fs, ino)] = dp->ffs2_din;
1142
        }
1143
        ffs_wtfs(d, fs->fs_bsize, buf, fsopts);
1144
        free(buf);
1145
}
1146
 
1147
void
1148
panic(const char *fmt, ...)
1149
{
1150
        va_list ap;
1151
 
1152
        va_start(ap, fmt);
1153
        vwarnx(fmt, ap);
1154
        va_end(ap);
1155
        exit(1);
1156
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.