2 * mkcramfs - make a cramfs file system
4 * Copyright (C) 1999-2002 Transmeta Corporation
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * Old version would die on largish filesystems. Change to mmap the
23 * files one by one instaed of all simultaneously. - aeb, 2002-11-01
26 #include <sys/types.h>
41 #include "cramfs_common.h"
45 /* Exit codes used by mkfs-type programs */
46 #define MKFS_OK 0 /* No errors */
47 #define MKFS_ERROR 8 /* Operational error */
48 #define MKFS_USAGE 16 /* Usage or syntax error */
50 /* The kernel only supports PAD_SIZE of 0 and 512. */
53 static const char *progname = "mkcramfs";
54 static int verbose = 0;
56 static unsigned int blksize; /* settable via -b option */
57 static long total_blocks = 0, total_nodes = 1; /* pre-count the root node */
58 static int image_length = 0;
59 static int cramfs_is_big_endian = 0; /* target is big endian */
62 * If opt_holes is set, then mkcramfs can create explicit holes in the
63 * data, which saves 26 bytes per hole (which is a lot smaller a
64 * saving than for most filesystems).
66 * Note that kernels up to at least 2.3.39 don't support cramfs holes,
67 * which is why this is turned off by default.
69 static int opt_edition = 0;
70 static int opt_errors = 0;
71 static int opt_holes = 0;
72 static int opt_pad = 0;
73 static char *opt_image = NULL;
74 static char *opt_name = NULL;
76 static int warn_dev = 0;
77 static int warn_gid = 0;
78 static int warn_namelen = 0;
79 static int warn_skip = 0;
80 static int warn_size = 0;
81 static int warn_uid = 0;
84 # define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
88 #define CRAMFS_EFLAG_MD5 1
89 #define CRAMFS_EFLAG_INVALID 2
91 /* In-core version of inode / directory entry. */
95 unsigned int mode, size, uid, gid;
96 unsigned char md5sum[16];
97 unsigned char flags; /* CRAMFS_EFLAG_* */
101 int fd; /* temporarily open files while mmapped */
102 struct entry *same; /* points to other identical file */
103 unsigned int offset; /* pointer to compressed data in archive */
104 unsigned int dir_offset; /* offset of directory entry in archive */
107 struct entry *child; /* NULL for non-directory and empty dir */
112 * Width of various bitfields in struct cramfs_inode.
113 * Used only to generate warnings.
115 #define CRAMFS_SIZE_WIDTH 24
116 #define CRAMFS_UID_WIDTH 16
117 #define CRAMFS_GID_WIDTH 8
118 #define CRAMFS_OFFSET_WIDTH 26
120 /* Input status of 0 to print help and exit without an error. */
123 FILE *stream = status ? stderr : stdout;
126 _("usage: %s [-h] [-v] [-b blksize] [-e edition] [-N endian] [-i file] "
127 "[-n name] dirname outfile\n"
128 " -h print this help\n"
130 " -E make all warnings errors "
131 "(non-zero exit status)\n"
132 " -b blksize use this blocksize, must equal page size\n"
133 " -e edition set edition number (part of fsid)\n"
134 " -N endian set cramfs endianness (big|little|host), default host\n"
135 " -i file insert a file image into the filesystem "
136 "(requires >= 2.4.0)\n"
137 " -n name set name of cramfs filesystem\n"
138 " -p pad by %d bytes for boot code\n"
139 " -s sort directory entries (old option, ignored)\n"
140 " -z make explicit holes (requires >= 2.3.39)\n"
141 " dirname root of the filesystem to be compressed\n"
142 " outfile output file\n"),
150 xmalloc (size_t size) {
151 void *t = malloc(size);
154 exit(8); /* out of memory */
160 do_mmap(char *path, unsigned int size, unsigned int mode){
168 start = xmalloc(size);
169 if (readlink(path, start, size) < 0) {
177 fd = open(path, O_RDONLY);
184 start = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
185 if (-1 == (int) (long) start) {
195 do_munmap(char *start, unsigned int size, unsigned int mode){
202 /* compute md5sums, so that we do not have to compare every pair of files */
204 mdfile(struct entry *e) {
208 start = do_mmap(e->path, e->size, e->mode);
210 e->flags |= CRAMFS_EFLAG_INVALID;
213 MD5Update(&ctx, (unsigned char *) start, e->size);
214 MD5Final(e->md5sum, &ctx);
216 do_munmap(start, e->size, e->mode);
218 e->flags |= CRAMFS_EFLAG_MD5;
222 /* md5 digests are equal; files are almost certainly the same,
223 but just to be sure, do the comparison */
225 identical_file(struct entry *e1, struct entry *e2){
226 char *start1, *start2;
229 start1 = do_mmap(e1->path, e1->size, e1->mode);
232 start2 = do_mmap(e2->path, e2->size, e2->mode);
235 equal = !memcmp(start1, start2, e1->size);
236 do_munmap(start1, e1->size, e1->mode);
237 do_munmap(start2, e2->size, e2->mode);
242 * The longest file name component to allow for in the input directory tree.
243 * Ext2fs (and many others) allow up to 255 bytes. A couple of filesystems
244 * allow longer (e.g. smbfs 1024), but there isn't much use in supporting
245 * >255-byte names in the input directory tree given that such names get
246 * truncated to 255 bytes when written to cramfs.
248 #define MAX_INPUT_NAMELEN 255
250 static int find_identical_file(struct entry *orig, struct entry *new, loff_t *fslen_ub)
256 if (orig->size == new->size && orig->path) {
262 if ((orig->flags & CRAMFS_EFLAG_MD5) &&
263 (new->flags & CRAMFS_EFLAG_MD5) &&
264 !memcmp(orig->md5sum, new->md5sum, 16) &&
265 identical_file(orig, new)) {
267 *fslen_ub -= new->size;
271 return find_identical_file(orig->child, new, fslen_ub) ||
272 find_identical_file(orig->next, new, fslen_ub);
275 static void eliminate_doubles(struct entry *root, struct entry *orig, loff_t *fslen_ub) {
277 if (orig->size && orig->path)
278 find_identical_file(root,orig, fslen_ub);
279 eliminate_doubles(root,orig->child, fslen_ub);
280 eliminate_doubles(root,orig->next, fslen_ub);
285 * We define our own sorting function instead of using alphasort which
286 * uses strcoll and changes ordering based on locale information.
288 static int cramsort (const void *a, const void *b)
290 return strcmp ((*(const struct dirent **) a)->d_name,
291 (*(const struct dirent **) b)->d_name);
294 static unsigned int parse_directory(struct entry *root_entry, const char *name, struct entry **prev, loff_t *fslen_ub)
296 struct dirent **dirlist;
297 int totalsize = 0, dircount, dirindex;
298 char *path, *endpath;
299 size_t len = strlen(name);
301 /* Set up the path. */
302 /* TODO: Reuse the parent's buffer to save memcpy'ing and duplication. */
303 path = xmalloc(len + 1 + MAX_INPUT_NAMELEN + 1);
304 memcpy(path, name, len);
305 endpath = path + len;
309 /* read in the directory and sort */
310 dircount = scandir(name, &dirlist, 0, cramsort);
317 /* process directory */
318 for (dirindex = 0; dirindex < dircount; dirindex++) {
319 struct dirent *dirent;
325 dirent = dirlist[dirindex];
327 /* Ignore "." and ".." - we won't be adding them
329 if (dirent->d_name[0] == '.') {
330 if (dirent->d_name[1] == '\0')
332 if (dirent->d_name[1] == '.') {
333 if (dirent->d_name[2] == '\0')
337 namelen = strlen(dirent->d_name);
338 if (namelen > MAX_INPUT_NAMELEN) {
340 _("Very long (%zu bytes) filename `%s' found.\n"
341 " Please increase MAX_INPUT_NAMELEN in "
342 "mkcramfs.c and recompile. Exiting.\n"),
343 namelen, dirent->d_name);
346 memcpy(endpath, dirent->d_name, namelen + 1);
348 if (lstat(path, &st) < 0) {
353 entry = calloc(1, sizeof(struct entry));
358 entry->name = (unsigned char *)strdup(dirent->d_name);
364 /* Can't happen when reading from ext2fs. */
366 /* TODO: we ought to avoid chopping in half
367 multi-byte UTF8 characters. */
368 entry->name[namelen = 255] = '\0';
371 entry->mode = st.st_mode;
372 entry->size = st.st_size;
373 entry->uid = st.st_uid;
374 if (entry->uid >= 1 << CRAMFS_UID_WIDTH)
376 entry->gid = st.st_gid;
377 if (entry->gid >= 1 << CRAMFS_GID_WIDTH)
378 /* TODO: We ought to replace with a default
379 gid instead of truncating; otherwise there
380 are security problems. Maybe mode should
381 be &= ~070. Same goes for uid once Linux
382 supports >16-bit uids. */
384 size = sizeof(struct cramfs_inode) + ((namelen + 3) & ~3);
386 if (S_ISDIR(st.st_mode)) {
387 entry->size = parse_directory(root_entry, path, &entry->child, fslen_ub);
388 } else if (S_ISREG(st.st_mode)) {
389 entry->path = strdup(path);
391 if (entry->size >= (1 << CRAMFS_SIZE_WIDTH)) {
393 entry->size = (1 << CRAMFS_SIZE_WIDTH) - 1;
396 } else if (S_ISLNK(st.st_mode)) {
397 entry->path = strdup(path);
398 } else if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
399 /* maybe we should skip sockets */
402 entry->size = st.st_rdev;
403 if (entry->size & -(1<<CRAMFS_SIZE_WIDTH))
407 if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
408 int blocks = ((entry->size - 1) / blksize + 1);
410 /* block pointers & data expansion allowance + data */
412 *fslen_ub += (4+26)*blocks + entry->size + 3;
415 /* Link it into the list */
421 free(dirlist); /* allocated by scandir() with malloc() */
425 /* Returns sizeof(struct cramfs_super), which includes the root inode. */
426 static unsigned int write_superblock(struct entry *root, char *base, int size)
428 struct cramfs_super *super = (struct cramfs_super *) base;
429 unsigned int offset = sizeof(struct cramfs_super) + image_length;
435 super->magic = CRAMFS_MAGIC;
436 super->flags = CRAMFS_FLAG_FSID_VERSION_2 | CRAMFS_FLAG_SORTED_DIRS;
438 super->flags |= CRAMFS_FLAG_HOLES;
439 if (image_length > 0)
440 super->flags |= CRAMFS_FLAG_SHIFTED_ROOT_OFFSET;
442 memcpy(super->signature, CRAMFS_SIGNATURE, sizeof(super->signature));
444 super->fsid.crc = crc32(0L, Z_NULL, 0);
445 super->fsid.edition = opt_edition;
446 super->fsid.blocks = total_blocks;
447 super->fsid.files = total_nodes;
449 memset(super->name, 0x00, sizeof(super->name));
451 strncpy((char *)super->name, opt_name, sizeof(super->name));
453 strncpy((char *)super->name, "Compressed", sizeof(super->name));
455 super->root.mode = root->mode;
456 super->root.uid = root->uid;
457 super->root.gid = root->gid;
458 super->root.size = root->size;
459 super->root.offset = offset >> 2;
461 super_toggle_endianness(cramfs_is_big_endian, super);
462 inode_from_host(cramfs_is_big_endian, &super->root, &super->root);
467 static void set_data_offset(struct entry *entry, char *base, unsigned long offset)
469 struct cramfs_inode *inode = (struct cramfs_inode *) (base + entry->dir_offset);
470 inode_to_host(cramfs_is_big_endian, inode, inode);
471 if (offset >= (1 << (2 + CRAMFS_OFFSET_WIDTH))) {
472 fprintf(stderr, _("filesystem too big. Exiting.\n"));
475 inode->offset = (offset >> 2);
476 inode_from_host(cramfs_is_big_endian, inode, inode);
481 * We do a width-first printout of the directory
482 * entries, using a stack to remember the directories
485 static unsigned int write_directory_structure(struct entry *entry, char *base, unsigned int offset)
487 int stack_entries = 0;
489 struct entry **entry_stack;
491 entry_stack = xmalloc(stack_size * sizeof(struct entry *));
494 int dir_start = stack_entries;
496 struct cramfs_inode *inode =
497 (struct cramfs_inode *) (base + offset);
498 size_t len = strlen((const char *)entry->name);
500 entry->dir_offset = offset;
502 inode->mode = entry->mode;
503 inode->uid = entry->uid;
504 inode->gid = entry->gid;
505 inode->size = entry->size;
507 /* Non-empty directories, regfiles and symlinks will
508 write over inode->offset later. */
510 offset += sizeof(struct cramfs_inode);
511 total_nodes++; /* another node */
512 memcpy(base + offset, entry->name, len);
513 /* Pad up the name to a 4-byte boundary */
515 *(base + offset + len) = '\0';
518 inode->namelen = len >> 2;
522 printf(" %s\n", entry->name);
524 if (stack_entries >= stack_size) {
526 entry_stack = realloc(entry_stack, stack_size * sizeof(struct entry *));
529 exit(8); /* out of memory */
532 entry_stack[stack_entries] = entry;
535 inode_from_host(cramfs_is_big_endian, inode, inode);
540 * Reverse the order the stack entries pushed during
541 * this directory, for a small optimization of disk
542 * access in the created fs. This change makes things
546 struct entry **lo = entry_stack + dir_start;
547 struct entry **hi = entry_stack + stack_entries;
557 /* Pop a subdirectory entry from the stack, and recurse. */
561 entry = entry_stack[stack_entries];
563 set_data_offset(entry, base, offset);
565 printf("'%s':\n", entry->name);
566 entry = entry->child;
572 static int is_zero(unsigned char const *begin, unsigned len)
575 /* Returns non-zero iff the first LEN bytes from BEGIN are
577 return (len-- == 0 ||
585 memcmp(begin, begin + 4, len) == 0))))))));
587 /* Never create holes. */
592 * One 4-byte pointer per block and then the actual blocked
593 * output. The first block does not need an offset pointer,
594 * as it will start immediately after the pointer block;
595 * so the i'th pointer points to the end of the i'th block
596 * (i.e. the start of the (i+1)'th block or past EOF).
598 * Note that size > 0, as a zero-sized file wouldn't ever
599 * have gotten here in the first place.
602 do_compress(char *base, unsigned int offset, unsigned char const *name,
603 char *path, unsigned int size, unsigned int mode)
605 unsigned long original_size, original_offset, new_size, blocks, curr;
610 /* get uncompressed data */
611 start = do_mmap(path, size, mode);
616 original_size = size;
617 original_offset = offset;
618 blocks = (size - 1) / blksize + 1;
619 curr = offset + 4 * blocks;
621 total_blocks += blocks;
624 uLongf len = 2 * blksize;
629 if (!is_zero (p, input)) {
630 compress((Bytef *)(base + curr), &len, p, input);
635 if (len > blksize*2) {
636 /* (I don't think this can happen with zlib.) */
637 printf(_("AIEEE: block \"compressed\" to > "
638 "2*blocklength (%ld)\n"),
643 *(u32 *) (base + offset) = u32_toggle_endianness(cramfs_is_big_endian, curr);
647 do_munmap(start, original_size, mode);
649 curr = (curr + 3) & ~3;
650 new_size = curr - original_offset;
651 /* TODO: Arguably, original_size in these 2 lines should be
652 st_blocks * 512. But if you say that, then perhaps
653 administrative data should also be included in both. */
654 change = new_size - original_size;
656 printf(_("%6.2f%% (%+ld bytes)\t%s\n"),
657 (change * 100) / (double) original_size, change, name);
664 * Traverse the entry tree, writing data for every item that has
665 * non-null entry->path (i.e. every symlink and non-empty
669 write_data(struct entry *entry, char *base, unsigned int offset) {
672 for (e = entry; e; e = e->next) {
675 set_data_offset(e, base, e->same->offset);
676 e->offset = e->same->offset;
677 } else if (e->size) {
678 set_data_offset(e, base, offset);
680 offset = do_compress(base, offset, e->name,
681 e->path, e->size,e->mode);
684 offset = write_data(e->child, base, offset);
689 static unsigned int write_file(char *file, char *base, unsigned int offset)
694 fd = open(file, O_RDONLY);
699 buf = mmap(NULL, image_length, PROT_READ, MAP_PRIVATE, fd, 0);
700 memcpy(base + offset, buf, image_length);
701 munmap(buf, image_length);
703 /* Pad up the image_length to a 4-byte boundary */
704 while (image_length & 3) {
705 *(base + offset + image_length) = '\0';
708 return (offset + image_length);
712 * Maximum size fs you can create is roughly 256MB. (The last file's
713 * data must begin within 256MB boundary but can extend beyond that.)
715 * Note that if you want it to fit in a ROM then you're limited to what the
716 * hardware and kernel can support (64MB?).
720 return (((1 << CRAMFS_OFFSET_WIDTH) - 1) << 2) /* offset */
721 + (1 << CRAMFS_SIZE_WIDTH) - 1 /* filesize */
722 + (1 << CRAMFS_SIZE_WIDTH) * 4 / blksize; /* block pointers */
728 * mkcramfs directory-name outfile
730 * where "directory-name" is simply the root of the directory
731 * tree that we want to generate a compressed filesystem out
734 int main(int argc, char **argv)
736 struct stat st; /* used twice... */
737 struct entry *root_entry;
739 ssize_t offset, written;
741 /* initial guess (upper-bound) of required filesystem size */
742 loff_t fslen_ub = sizeof(struct cramfs_super);
743 unsigned int fslen_max;
744 char const *dirname, *outfile;
745 u32 crc = crc32(0L, Z_NULL, 0);
747 cramfs_is_big_endian = HOST_IS_BIG_ENDIAN; /* default is to use host order */
749 blksize = getpagesize();
755 if ((p = strrchr(progname, '/')) != NULL)
759 setlocale(LC_ALL, "");
760 bindtextdomain(PACKAGE, LOCALEDIR);
763 /* command line options */
764 while ((c = getopt(argc, argv, "hb:Ee:i:n:N:psVvz")) != EOF) {
769 blksize = atoi(optarg);
777 opt_edition = atoi(optarg);
780 if (strcmp(optarg, "big") == 0) {
781 cramfs_is_big_endian = 1;
783 else if (strcmp(optarg, "little") == 0) {
784 cramfs_is_big_endian = 0;
786 else if (strcmp(optarg, "host") == 0); /* default */
788 perror("invalid endianness given. Must be 'big', 'little', or 'host'");
795 if (lstat(opt_image, &st) < 0) {
799 image_length = st.st_size; /* may be padded later */
800 fslen_ub += (image_length + 3); /* 3 is for padding */
807 fslen_ub += PAD_SIZE;
810 /* old option, ignored */
813 printf(_("%s (%s)\n"),
814 progname, PACKAGE_STRING);
825 if ((argc - optind) != 2)
827 dirname = argv[optind];
828 outfile = argv[optind + 1];
830 if (stat(dirname, &st) < 0) {
834 fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
836 root_entry = calloc(1, sizeof(struct entry));
841 root_entry->mode = st.st_mode;
842 root_entry->uid = st.st_uid;
843 root_entry->gid = st.st_gid;
845 root_entry->size = parse_directory(root_entry, dirname, &root_entry->child, &fslen_ub);
847 /* always allocate a multiple of blksize bytes because that's
848 what we're going to write later on */
849 fslen_ub = ((fslen_ub - 1) | (blksize - 1)) + 1;
850 fslen_max = maxfslen();
852 if (fslen_ub > fslen_max) {
854 _("warning: guestimate of required size (upper bound) "
855 "is %lldMB, but maximum image size is %uMB. "
856 "We might die prematurely.\n"),
857 (long long)fslen_ub >> 20,
859 fslen_ub = fslen_max;
862 /* find duplicate files */
863 eliminate_doubles(root_entry,root_entry, &fslen_ub);
865 /* TODO: Why do we use a private/anonymous mapping here
866 followed by a write below, instead of just a shared mapping
867 and a couple of ftruncate calls? Is it just to save us
868 having to deal with removing the file afterwards? If we
869 really need this huge anonymous mapping, we ought to mmap
870 in smaller chunks, so that the user doesn't need nn MB of
871 RAM free. If the reason is to be able to write to
872 un-mmappable block devices, then we could try shared mmap
873 and revert to anonymous mmap if the shared mmap fails. */
874 rom_image = mmap(NULL,
876 PROT_READ | PROT_WRITE,
877 MAP_PRIVATE | MAP_ANONYMOUS,
880 if (-1 == (int) (long) rom_image) {
881 perror(_("ROM image map"));
885 /* Skip the first opt_pad bytes for boot loader code */
887 memset(rom_image, 0x00, opt_pad);
889 /* Skip the superblock and come back to write it later. */
890 offset += sizeof(struct cramfs_super);
892 /* Insert a file image. */
895 printf(_("Including: %s\n"), opt_image);
896 offset = write_file(opt_image, rom_image, offset);
899 offset = write_directory_structure(root_entry->child, rom_image, offset);
901 printf(_("Directory data: %zd bytes\n"), offset);
903 offset = write_data(root_entry, rom_image, offset);
905 /* We always write a multiple of blksize bytes, so that
907 offset = ((offset - 1) | (blksize - 1)) + 1;
909 printf(_("Everything: %zd kilobytes\n"), offset >> 10);
911 /* Write the superblock now that we can fill in all of the fields. */
912 write_superblock(root_entry, rom_image+opt_pad, offset);
914 printf(_("Super block: %zd bytes\n"),
915 sizeof(struct cramfs_super));
917 /* Put the checksum in. */
918 crc = crc32(crc, (unsigned char *) (rom_image+opt_pad), (offset-opt_pad));
919 ((struct cramfs_super *) (rom_image+opt_pad))->fsid.crc = u32_toggle_endianness(cramfs_is_big_endian, crc);
921 printf(_("CRC: %x\n"), crc);
923 /* Check to make sure we allocated enough space. */
924 if (fslen_ub < offset) {
926 _("not enough space allocated for ROM image "
927 "(%lld allocated, %zu used)\n"),
928 (long long) fslen_ub, offset);
932 written = write(fd, rom_image, offset);
934 perror(_("ROM image"));
937 if (offset != written) {
938 fprintf(stderr, _("ROM image write failed (%zd %zd)\n"),
943 /* (These warnings used to come at the start, but they scroll off the
944 screen too quickly.) */
945 if (warn_namelen) /* (can't happen when reading from ext2fs) */
946 fprintf(stderr, /* bytes, not chars: think UTF8. */
947 _("warning: filenames truncated to 255 bytes.\n"));
950 _("warning: files were skipped due to errors.\n"));
953 _("warning: file sizes truncated to %luMB "
954 "(minus 1 byte).\n"),
955 1L << (CRAMFS_SIZE_WIDTH - 20));
956 if (warn_uid) /* (not possible with current Linux versions) */
958 _("warning: uids truncated to %u bits. "
959 "(This may be a security concern.)\n"),
963 _("warning: gids truncated to %u bits. "
964 "(This may be a security concern.)\n"),
968 _("WARNING: device numbers truncated to %u bits. "
969 "This almost certainly means\n"
970 "that some device files will be wrong.\n"),
971 CRAMFS_OFFSET_WIDTH);
973 (warn_namelen|warn_skip|warn_size|warn_uid|warn_gid|warn_dev))