2 * SPDX-License-Identifier: GPL-2.0-or-later
4 * mkcramfs - make a cramfs file system
6 * Copyright (C) 1999-2002 Transmeta Corporation
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://gnu.org/licenses/>.
23 * Old version would die on largish filesystems. Change to mmap the
24 * files one by one instead of all simultaneously. - aeb, 2002-11-01
27 #include <sys/types.h>
41 /* We don't use our include/crc32.h, but crc32 from zlib!
43 * The zlib implementation performs pre/post-conditioning. The util-linux
44 * imlemenation requires post-conditioning (xor) in the applications.
53 #include "exitcodes.h"
56 #define CLOSE_EXIT_CODE MKFS_EX_ERROR
57 #include "closestream.h"
59 #define XALLOC_EXIT_CODE MKFS_EX_ERROR
62 /* The kernel only supports PAD_SIZE of 0 and 512. */
65 static int verbose
= 0;
67 static unsigned int blksize
= 0; /* settable via -b option, default page size */
68 static long total_blocks
= 0, total_nodes
= 1; /* pre-count the root node */
69 static int image_length
= 0;
70 static int cramfs_is_big_endian
= 0; /* target is big endian */
73 * If opt_holes is set, then mkcramfs can create explicit holes in the
74 * data, which saves 26 bytes per hole (which is a lot smaller a
75 * saving than for most filesystems).
77 * Note that kernels up to at least 2.3.39 don't support cramfs holes,
78 * which is why this is turned off by default.
80 static unsigned int opt_edition
= 0;
81 static int opt_errors
= 0;
82 static int opt_holes
= 0;
83 static int opt_pad
= 0;
84 static char *opt_image
= NULL
;
85 static char *opt_name
= NULL
;
87 static int warn_dev
= 0;
88 static int warn_gid
= 0;
89 static int warn_namelen
= 0;
90 static int warn_skip
= 0;
91 static int warn_size
= 0;
92 static int warn_uid
= 0;
95 #define CRAMFS_EFLAG_MD5 1
96 #define CRAMFS_EFLAG_INVALID 2
98 /* In-core version of inode / directory entry. */
102 unsigned int mode
, size
, uid
, gid
;
103 unsigned char md5sum
[UL_MD5LENGTH
];
104 unsigned char flags
; /* CRAMFS_EFLAG_* */
108 int fd
; /* temporarily open files while mmapped */
109 struct entry
*same
; /* points to other identical file */
110 unsigned int offset
; /* pointer to compressed data in archive */
111 unsigned int dir_offset
; /* offset of directory entry in archive */
114 struct entry
*child
; /* NULL for non-directory and empty dir */
119 * Width of various bitfields in struct cramfs_inode.
120 * Used only to generate warnings.
122 #define CRAMFS_SIZE_WIDTH 24
123 #define CRAMFS_UID_WIDTH 16
124 #define CRAMFS_GID_WIDTH 8
125 #define CRAMFS_OFFSET_WIDTH 26
127 static void __attribute__((__noreturn__
)) usage(void)
129 fputs(USAGE_HEADER
, stdout
);
130 fprintf(stdout
, _(" %s [options] dirname outfile\n"), program_invocation_short_name
);
132 fputs(USAGE_SEPARATOR
, stdout
);
133 fputsln(_("Make a compressed ROM file system."), stdout
);
135 fputs(USAGE_SEPARATOR
, stdout
);
136 fputsln(_(" dirname root of the filesystem to be compressed"), stdout
);
137 fputsln(_(" outfile output file"), stdout
);
139 fputs(USAGE_OPTIONS
, stdout
);
140 fputsln(_(" -v be verbose"), stdout
);
141 fputsln(_(" -E make all warnings errors (non-zero exit status)"), stdout
);
142 fputsln(_(" -b blksize use this blocksize, must equal page size"), stdout
);
143 fputsln(_(" -e edition set edition number (part of fsid)"), stdout
);
145 _(" -N endian set cramfs endianness (%s|%s|%s), default %s\n"), "big", "little", "host", "host");
146 fputsln(_(" -i file insert a file image into the filesystem"), stdout
);
147 fputsln(_(" -n name set name of cramfs filesystem"), stdout
);
149 _(" -p pad by %d bytes for boot code\n"), PAD_SIZE
);
150 fputsln(_(" -z make explicit holes"), stdout
);
151 fputsln(_(" -l[=<mode>] use exclusive device lock (yes, no or nonblock)"), stdout
);
153 fputs(USAGE_SEPARATOR
, stdout
);
154 fprintf(stdout
, USAGE_HELP_OPTIONS(16));
156 fprintf(stdout
, USAGE_MAN_TAIL("mkfs.cramfs(8)"));
161 do_mmap(char *path
, unsigned int size
, unsigned int mode
){
169 /* The link buffer is unnecessary to terminate by null as it's
170 * always used as buffer rather than a string */
171 start
= xmalloc(size
);
172 if (readlink(path
, start
, size
) < 0) {
173 warn(_("readlink failed: %s"), path
);
180 fd
= open(path
, O_RDONLY
);
182 warn(_("cannot open %s"), path
);
187 start
= mmap(NULL
, size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
189 if (start
== MAP_FAILED
)
190 err(MKFS_EX_ERROR
, "mmap");
198 do_munmap(char *start
, unsigned int size
, unsigned int mode
){
205 /* compute md5sums, so that we do not have to compare every pair of files */
207 mdfile(struct entry
*e
) {
210 start
= do_mmap(e
->path
, e
->size
, e
->mode
);
212 e
->flags
|= CRAMFS_EFLAG_INVALID
;
217 ul_MD5Update(&ctx
, (unsigned char *) start
, e
->size
);
218 ul_MD5Final(e
->md5sum
, &ctx
);
220 do_munmap(start
, e
->size
, e
->mode
);
222 e
->flags
|= CRAMFS_EFLAG_MD5
;
226 /* md5 digests are equal; files are almost certainly the same,
227 but just to be sure, do the comparison */
229 identical_file(struct entry
*e1
, struct entry
*e2
){
230 char *start1
, *start2
;
233 start1
= do_mmap(e1
->path
, e1
->size
, e1
->mode
);
236 start2
= do_mmap(e2
->path
, e2
->size
, e2
->mode
);
238 do_munmap(start1
, e1
->size
, e1
->mode
);
241 equal
= !memcmp(start1
, start2
, e1
->size
);
242 do_munmap(start1
, e1
->size
, e1
->mode
);
243 do_munmap(start2
, e2
->size
, e2
->mode
);
248 * The longest file name component to allow for in the input directory tree.
249 * Ext2fs (and many others) allow up to 255 bytes. A couple of filesystems
250 * allow longer (e.g. smbfs 1024), but there isn't much use in supporting
251 * >255-byte names in the input directory tree given that such names get
252 * truncated to 255 bytes when written to cramfs.
254 #define MAX_INPUT_NAMELEN 255
256 static int find_identical_file(struct entry
*orig
, struct entry
*new, loff_t
*fslen_ub
)
262 if (orig
->size
== new->size
&& orig
->path
) {
268 if ((orig
->flags
& CRAMFS_EFLAG_MD5
) &&
269 (new->flags
& CRAMFS_EFLAG_MD5
) &&
270 !memcmp(orig
->md5sum
, new->md5sum
, UL_MD5LENGTH
) &&
271 identical_file(orig
, new)) {
273 *fslen_ub
-= new->size
;
277 return find_identical_file(orig
->child
, new, fslen_ub
) ||
278 find_identical_file(orig
->next
, new, fslen_ub
);
281 static void eliminate_doubles(struct entry
*root
, struct entry
*orig
, loff_t
*fslen_ub
) {
283 if (orig
->size
&& orig
->path
)
284 find_identical_file(root
,orig
, fslen_ub
);
285 eliminate_doubles(root
,orig
->child
, fslen_ub
);
286 eliminate_doubles(root
,orig
->next
, fslen_ub
);
291 * We define our own sorting function instead of using alphasort which
292 * uses strcoll and changes ordering based on locale information.
294 static int cramsort (const struct dirent
**a
, const struct dirent
**b
)
296 return strcmp((*a
)->d_name
, (*b
)->d_name
);
299 static unsigned int parse_directory(struct entry
*root_entry
, const char *name
, struct entry
**prev
, loff_t
*fslen_ub
)
301 struct dirent
**dirlist
;
302 int totalsize
= 0, dircount
, dirindex
;
303 char *path
, *endpath
;
304 size_t len
= strlen(name
);
306 /* Set up the path. */
307 /* TODO: Reuse the parent's buffer to save memcpy'ing and duplication. */
308 path
= xmalloc(len
+ 1 + MAX_INPUT_NAMELEN
+ 1);
309 memcpy(path
, name
, len
);
310 endpath
= path
+ len
;
314 /* read in the directory and sort */
315 dircount
= scandir(name
, &dirlist
, NULL
, cramsort
);
318 err(MKFS_EX_ERROR
, _("could not read directory %s"), name
);
320 /* process directory */
321 for (dirindex
= 0; dirindex
< dircount
; dirindex
++) {
322 struct dirent
*dirent
;
328 dirent
= dirlist
[dirindex
];
330 /* Ignore "." and ".." - we won't be adding them
332 if (dirent
->d_name
[0] == '.') {
333 if (dirent
->d_name
[1] == '\0')
335 if (dirent
->d_name
[1] == '.' &&
336 dirent
->d_name
[2] == '\0')
339 namelen
= strlen(dirent
->d_name
);
340 if (namelen
> MAX_INPUT_NAMELEN
) {
341 namelen
= MAX_INPUT_NAMELEN
;
345 memcpy(endpath
, dirent
->d_name
, namelen
+ 1);
347 if (lstat(path
, &st
) < 0) {
348 warn(_("stat of %s failed"), endpath
);
352 entry
= xcalloc(1, sizeof(struct entry
));
353 entry
->name
= (unsigned char *)xstrndup(dirent
->d_name
, namelen
);
354 entry
->mode
= st
.st_mode
;
355 entry
->size
= st
.st_size
;
356 entry
->uid
= st
.st_uid
;
357 if (entry
->uid
>= 1 << CRAMFS_UID_WIDTH
)
359 entry
->gid
= st
.st_gid
;
360 if (entry
->gid
>= 1 << CRAMFS_GID_WIDTH
)
361 /* TODO: We ought to replace with a default
362 gid instead of truncating; otherwise there
363 are security problems. Maybe mode should
364 be &= ~070. Same goes for uid once Linux
365 supports >16-bit uids. */
367 size
= sizeof(struct cramfs_inode
) + ((namelen
+ 3) & ~3);
369 if (S_ISDIR(st
.st_mode
)) {
370 entry
->size
= parse_directory(root_entry
, path
, &entry
->child
, fslen_ub
);
371 } else if (S_ISREG(st
.st_mode
)) {
372 entry
->path
= xstrdup(path
);
373 if (entry
->size
>= (1 << CRAMFS_SIZE_WIDTH
)) {
375 entry
->size
= (1 << CRAMFS_SIZE_WIDTH
) - 1;
377 } else if (S_ISLNK(st
.st_mode
)) {
378 entry
->path
= xstrdup(path
);
379 } else if (S_ISFIFO(st
.st_mode
) || S_ISSOCK(st
.st_mode
)) {
380 /* maybe we should skip sockets */
383 entry
->size
= st
.st_rdev
;
384 if (entry
->size
& -(1<<CRAMFS_SIZE_WIDTH
))
388 if (S_ISREG(st
.st_mode
) || S_ISLNK(st
.st_mode
)) {
389 int blocks
= ((entry
->size
- 1) / blksize
+ 1);
391 /* block pointers & data expansion allowance + data */
393 *fslen_ub
+= (4+26)*blocks
+ entry
->size
+ 3;
396 /* Link it into the list */
402 free(dirlist
); /* allocated by scandir() with malloc() */
406 /* Returns sizeof(struct cramfs_super), which includes the root inode. */
407 static unsigned int write_superblock(struct entry
*root
, char *base
, int size
)
409 struct cramfs_super
*super
= (struct cramfs_super
*) base
;
410 unsigned int offset
= sizeof(struct cramfs_super
) + image_length
;
416 super
->magic
= CRAMFS_MAGIC
;
417 super
->flags
= CRAMFS_FLAG_FSID_VERSION_2
| CRAMFS_FLAG_SORTED_DIRS
;
419 super
->flags
|= CRAMFS_FLAG_HOLES
;
420 if (image_length
> 0)
421 super
->flags
|= CRAMFS_FLAG_SHIFTED_ROOT_OFFSET
;
423 memcpy(super
->signature
, CRAMFS_SIGNATURE
, sizeof(super
->signature
));
425 super
->fsid
.crc
= crc32(0L, NULL
, 0);
426 super
->fsid
.edition
= opt_edition
;
427 super
->fsid
.blocks
= total_blocks
;
428 super
->fsid
.files
= total_nodes
;
430 memset(super
->name
, 0x00, sizeof(super
->name
));
432 str2memcpy((char *)super
->name
, opt_name
, sizeof(super
->name
));
434 str2memcpy((char *)super
->name
, "Compressed", sizeof(super
->name
));
436 super
->root
.mode
= root
->mode
;
437 super
->root
.uid
= root
->uid
;
438 super
->root
.gid
= root
->gid
;
439 super
->root
.size
= root
->size
;
440 super
->root
.offset
= offset
>> 2;
442 super_toggle_endianness(cramfs_is_big_endian
, super
);
443 inode_from_host(cramfs_is_big_endian
, &super
->root
, &super
->root
);
448 static void set_data_offset(struct entry
*entry
, char *base
, unsigned long offset
)
450 struct cramfs_inode
*inode
= (struct cramfs_inode
*) (base
+ entry
->dir_offset
);
451 inode_to_host(cramfs_is_big_endian
, inode
, inode
);
452 if (offset
>= (1 << (2 + CRAMFS_OFFSET_WIDTH
)))
453 errx(MKFS_EX_ERROR
, _("filesystem too big. Exiting."));
454 inode
->offset
= (offset
>> 2);
455 inode_from_host(cramfs_is_big_endian
, inode
, inode
);
460 * We do a width-first printout of the directory
461 * entries, using a stack to remember the directories
464 static unsigned int write_directory_structure(struct entry
*entry
, char *base
, unsigned int offset
)
466 int stack_entries
= 0;
468 struct entry
**entry_stack
;
470 entry_stack
= xmalloc(stack_size
* sizeof(struct entry
*));
473 int dir_start
= stack_entries
;
475 struct cramfs_inode
*inode
=
476 (struct cramfs_inode
*) (base
+ offset
);
477 size_t len
= strlen((const char *)entry
->name
);
479 entry
->dir_offset
= offset
;
481 inode
->mode
= entry
->mode
;
482 inode
->uid
= entry
->uid
;
483 inode
->gid
= entry
->gid
;
484 inode
->size
= entry
->size
;
486 /* Non-empty directories, regfiles and symlinks will
487 write over inode->offset later. */
489 offset
+= sizeof(struct cramfs_inode
);
490 total_nodes
++; /* another node */
491 memcpy(base
+ offset
, entry
->name
, len
);
492 /* Pad up the name to a 4-byte boundary */
494 *(base
+ offset
+ len
) = '\0';
497 inode
->namelen
= len
>> 2;
501 printf(" %s\n", entry
->name
);
503 if (stack_entries
>= stack_size
) {
505 entry_stack
= xreallocarray(entry_stack
, stack_size
, sizeof(struct entry
*));
507 entry_stack
[stack_entries
] = entry
;
510 inode_from_host(cramfs_is_big_endian
, inode
, inode
);
515 * Reverse the order the stack entries pushed during
516 * this directory, for a small optimization of disk
517 * access in the created fs. This change makes things
521 struct entry
**lo
= entry_stack
+ dir_start
;
522 struct entry
**hi
= entry_stack
+ stack_entries
;
532 /* Pop a subdirectory entry from the stack, and recurse. */
536 entry
= entry_stack
[stack_entries
];
538 set_data_offset(entry
, base
, offset
);
540 printf("'%s':\n", entry
->name
);
541 entry
= entry
->child
;
547 static int is_zero(unsigned char const *begin
, unsigned len
)
550 /* Returns non-zero iff the first LEN bytes from BEGIN are
552 return (len
-- == 0 ||
560 memcmp(begin
, begin
+ 4, len
) == 0))))))));
562 /* Never create holes. */
567 * One 4-byte pointer per block and then the actual blocked
568 * output. The first block does not need an offset pointer,
569 * as it will start immediately after the pointer block;
570 * so the i'th pointer points to the end of the i'th block
571 * (i.e. the start of the (i+1)'th block or past EOF).
573 * Note that size > 0, as a zero-sized file wouldn't ever
574 * have gotten here in the first place.
577 do_compress(char *base
, unsigned int offset
, unsigned char const *name
,
578 char *path
, unsigned int size
, unsigned int mode
)
580 unsigned long original_size
, original_offset
, new_size
, blocks
, curr
;
585 /* get uncompressed data */
586 start
= do_mmap(path
, size
, mode
);
591 original_size
= size
;
592 original_offset
= offset
;
593 blocks
= (size
- 1) / blksize
+ 1;
594 curr
= offset
+ 4 * blocks
;
596 total_blocks
+= blocks
;
599 uLongf len
= 2 * blksize
;
604 if (!is_zero (p
, input
)) {
605 compress((Bytef
*)(base
+ curr
), &len
, p
, input
);
610 if (len
> blksize
*2) {
611 /* (I don't think this can happen with zlib.) */
612 printf(_("AIEEE: block \"compressed\" to > "
613 "2*blocklength (%ld)\n"),
618 *(uint32_t *) (base
+ offset
) = u32_toggle_endianness(cramfs_is_big_endian
, curr
);
622 do_munmap(start
, original_size
, mode
);
624 curr
= (curr
+ 3) & ~3;
625 new_size
= curr
- original_offset
;
626 /* TODO: Arguably, original_size in these 2 lines should be
627 st_blocks * 512. But if you say that, then perhaps
628 administrative data should also be included in both. */
629 change
= new_size
- original_size
;
631 printf(_("%6.2f%% (%+ld bytes)\t%s\n"),
632 (change
* 100) / (double) original_size
, change
, name
);
639 * Traverse the entry tree, writing data for every item that has
640 * non-null entry->path (i.e. every symlink and non-empty
644 write_data(struct entry
*entry
, char *base
, unsigned int offset
) {
647 for (e
= entry
; e
; e
= e
->next
) {
650 set_data_offset(e
, base
, e
->same
->offset
);
651 e
->offset
= e
->same
->offset
;
652 } else if (e
->size
) {
653 set_data_offset(e
, base
, offset
);
655 offset
= do_compress(base
, offset
, e
->name
,
656 e
->path
, e
->size
,e
->mode
);
659 offset
= write_data(e
->child
, base
, offset
);
664 static unsigned int write_file(char *file
, char *base
, unsigned int offset
)
669 fd
= open(file
, O_RDONLY
);
671 err(MKFS_EX_ERROR
, _("cannot open %s"), file
);
672 buf
= mmap(NULL
, image_length
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
673 memcpy(base
+ offset
, buf
, image_length
);
674 munmap(buf
, image_length
);
676 err(MKFS_EX_ERROR
, _("cannot close file %s"), file
);
677 /* Pad up the image_length to a 4-byte boundary */
678 while (image_length
& 3) {
679 *(base
+ offset
+ image_length
) = '\0';
682 return (offset
+ image_length
);
686 * Maximum size fs you can create is roughly 256MB. (The last file's
687 * data must begin within 256MB boundary but can extend beyond that.)
689 * Note that if you want it to fit in a ROM then you're limited to what the
690 * hardware and kernel can support (64MB?).
694 return (((1 << CRAMFS_OFFSET_WIDTH
) - 1) << 2) /* offset */
695 + (1 << CRAMFS_SIZE_WIDTH
) - 1 /* filesize */
696 + (1 << CRAMFS_SIZE_WIDTH
) * 4 / blksize
; /* block pointers */
702 * mkcramfs directory-name outfile
704 * where "directory-name" is simply the root of the directory
705 * tree that we want to generate a compressed filesystem out
708 int main(int argc
, char **argv
)
710 struct stat st
; /* used twice... */
711 struct entry
*root_entry
;
713 ssize_t offset
, written
;
715 /* initial guess (upper-bound) of required filesystem size */
716 loff_t fslen_ub
= sizeof(struct cramfs_super
);
717 unsigned int fslen_max
;
718 char const *dirname
, *outfile
;
720 uint32_t crc
= crc32(0L, NULL
, 0);
722 cramfs_is_big_endian
= HOST_IS_BIG_ENDIAN
; /* default is to use host order */
726 setlocale(LC_ALL
, "");
727 bindtextdomain(PACKAGE
, LOCALEDIR
);
729 close_stdout_atexit();
732 /* first arg may be one of our standard longopts */
733 if (!strcmp(argv
[1], "--help"))
735 if (!strcmp(argv
[1], "--version")) {
736 print_version(EXIT_SUCCESS
);
740 strutils_set_exitcode(MKFS_EX_USAGE
);
742 /* command line options */
743 while ((c
= getopt(argc
, argv
, "hb:Ee:i:n:N:l::psVvz")) != EOF
) {
748 blksize
= strtou32_or_err(optarg
, _("invalid blocksize argument"));
754 opt_edition
= strtou32_or_err(optarg
, _("invalid edition number argument"));
757 if (strcmp(optarg
, "big") == 0)
758 cramfs_is_big_endian
= 1;
759 else if (strcmp(optarg
, "little") == 0)
760 cramfs_is_big_endian
= 0;
761 else if (strcmp(optarg
, "host") == 0)
764 errx(MKFS_EX_USAGE
, _("invalid endianness given;"
765 " must be 'big', 'little', or 'host'"));
769 if (lstat(opt_image
, &st
) < 0)
770 err(MKFS_EX_USAGE
, _("stat of %s failed"), opt_image
);
771 image_length
= st
.st_size
; /* may be padded later */
772 fslen_ub
+= (image_length
+ 3); /* 3 is for padding */
787 fslen_ub
+= PAD_SIZE
;
790 /* old option, ignored */
793 print_version(MKFS_EX_OK
);
801 errtryhelp(MKFS_EX_USAGE
);
805 if ((argc
- optind
) != 2) {
806 warnx(_("bad usage"));
807 errtryhelp(MKFS_EX_USAGE
);
809 dirname
= argv
[optind
];
810 outfile
= argv
[optind
+ 1];
813 blksize
= getpagesize();
815 if (stat(dirname
, &st
) < 0)
816 err(MKFS_EX_USAGE
, _("stat of %s failed"), dirname
);
817 fd
= open(outfile
, O_WRONLY
| O_CREAT
| O_TRUNC
, 0666);
819 err(MKFS_EX_USAGE
, _("cannot open %s"), outfile
);
821 if (blkdev_lock(fd
, outfile
, lockmode
) != 0)
824 root_entry
= xcalloc(1, sizeof(struct entry
));
825 root_entry
->mode
= st
.st_mode
;
826 root_entry
->uid
= st
.st_uid
;
827 root_entry
->gid
= st
.st_gid
;
829 root_entry
->size
= parse_directory(root_entry
, dirname
, &root_entry
->child
, &fslen_ub
);
831 /* find duplicate files */
832 eliminate_doubles(root_entry
,root_entry
, &fslen_ub
);
834 /* always allocate a multiple of blksize bytes because that's
835 what we're going to write later on */
836 fslen_ub
= ((fslen_ub
- 1) | (blksize
- 1)) + 1;
837 fslen_max
= maxfslen();
839 if (fslen_ub
> fslen_max
) {
840 warnx( _("warning: guestimate of required size (upper bound) "
841 "is %lldMB, but maximum image size is %uMB. "
842 "We might die prematurely."),
843 (long long)fslen_ub
>> 20,
845 fslen_ub
= fslen_max
;
848 /* TODO: Why do we use a private/anonymous mapping here
849 followed by a write below, instead of just a shared mapping
850 and a couple of ftruncate calls? Is it just to save us
851 having to deal with removing the file afterwards? If we
852 really need this huge anonymous mapping, we ought to mmap
853 in smaller chunks, so that the user doesn't need nn MB of
854 RAM free. If the reason is to be able to write to
855 un-mmappable block devices, then we could try shared mmap
856 and revert to anonymous mmap if the shared mmap fails. */
857 rom_image
= mmap(NULL
,
859 PROT_READ
| PROT_WRITE
,
860 MAP_PRIVATE
| MAP_ANONYMOUS
,
863 if (-1 == (int) (long) rom_image
)
864 err(MKFS_EX_ERROR
, _("ROM image map"));
866 /* Skip the first opt_pad bytes for boot loader code */
868 memset(rom_image
, 0x00, opt_pad
);
870 /* Skip the superblock and come back to write it later. */
871 offset
+= sizeof(struct cramfs_super
);
873 /* Insert a file image. */
876 printf(_("Including: %s\n"), opt_image
);
877 offset
= write_file(opt_image
, rom_image
, offset
);
880 offset
= write_directory_structure(root_entry
->child
, rom_image
, offset
);
882 printf(_("Directory data: %zd bytes\n"), offset
);
884 offset
= write_data(root_entry
, rom_image
, offset
);
886 /* We always write a multiple of blksize bytes, so that
888 offset
= ((offset
- 1) | (blksize
- 1)) + 1;
890 printf(_("Everything: %zd kilobytes\n"), offset
>> 10);
892 /* Write the superblock now that we can fill in all of the fields. */
893 write_superblock(root_entry
, rom_image
+opt_pad
, offset
);
895 printf(_("Super block: %zd bytes\n"),
896 sizeof(struct cramfs_super
));
898 /* Put the checksum in. */
899 crc
= crc32(crc
, (unsigned char *) (rom_image
+opt_pad
), (offset
-opt_pad
));
900 ((struct cramfs_super
*) (rom_image
+opt_pad
))->fsid
.crc
= u32_toggle_endianness(cramfs_is_big_endian
, crc
);
902 printf(_("CRC: %x\n"), crc
);
904 /* Check to make sure we allocated enough space. */
905 if (fslen_ub
< offset
)
907 _("not enough space allocated for ROM image "
908 "(%lld allocated, %zu used)"),
909 (long long) fslen_ub
, offset
);
911 written
= write(fd
, rom_image
, offset
);
912 if (offset
!= written
)
913 errx(MKFS_EX_ERROR
, _("ROM image write failed (%zd %zd)"),
915 if (close_fd(fd
) != 0)
916 err(MKFS_EX_ERROR
, _("ROM image"));
919 * (These warnings used to come at the start, but they scroll off
920 * the screen too quickly.)
923 /* Can't happen when reading from ext2fs. */
924 /* Bytes, not chars: think UTF8. */
925 warnx(_("warning: filenames truncated to %u bytes."), MAX_INPUT_NAMELEN
);
927 warnx(_("warning: files were skipped due to errors."));
929 warnx(_("warning: file sizes truncated to %luMB "
930 "(minus 1 byte)."), 1L << (CRAMFS_SIZE_WIDTH
- 20));
932 /* (not possible with current Linux versions) */
933 warnx(_("warning: uids truncated to %u bits. "
934 "(This may be a security concern.)"), CRAMFS_UID_WIDTH
);
936 warnx(_("warning: gids truncated to %u bits. "
937 "(This may be a security concern.)"), CRAMFS_GID_WIDTH
);
939 warnx(_("WARNING: device numbers truncated to %u bits. "
940 "This almost certainly means\n"
941 "that some device files will be wrong."),
942 CRAMFS_OFFSET_WIDTH
);
944 (warn_namelen
|warn_skip
|warn_size
|warn_uid
|warn_gid
|warn_dev
))