/*
* Old version would die on largish filesystems. Change to mmap the
- * files one by one instaed of all simultaneously. - aeb, 2002-11-01
+ * files one by one instead of all simultaneously. - aeb, 2002-11-01
*/
#include <sys/types.h>
#include <string.h>
#include <getopt.h>
#include <zconf.h>
+
+/* We don't use our include/crc32.h, but crc32 from zlib!
+ *
+ * The zlib implementation performs pre/post-conditioning. The util-linux
+ * imlemenation requires post-conditioning (xor) in the applications.
+ */
#include <zlib.h>
+#include "blkdev.h"
#include "c.h"
#include "cramfs.h"
-#include "closestream.h"
#include "md5.h"
#include "nls.h"
#include "exitcodes.h"
#include "strutils.h"
+
+#define CLOSE_EXIT_CODE MKFS_EX_ERROR
+#include "closestream.h"
+
#define XALLOC_EXIT_CODE MKFS_EX_ERROR
#include "xalloc.h"
/* stats */
unsigned char *name;
unsigned int mode, size, uid, gid;
- unsigned char md5sum[MD5LENGTH];
+ unsigned char md5sum[UL_MD5LENGTH];
unsigned char flags; /* CRAMFS_EFLAG_* */
/* FS data */
#define CRAMFS_GID_WIDTH 8
#define CRAMFS_OFFSET_WIDTH 26
-/* Input status of 0 to print help and exit without an error. */
-static void
-usage(int status) {
- FILE *stream = status ? stderr : stdout;
-
- fprintf(stream,
- _("usage: %s [-h] [-v] [-b blksize] [-e edition] [-N endian] [-i file] "
- "[-n name] dirname outfile\n"
- " -h print this help\n"
- " -v be verbose\n"
- " -E make all warnings errors "
- "(non-zero exit status)\n"
- " -b blksize use this blocksize, must equal page size\n"
- " -e edition set edition number (part of fsid)\n"
- " -N endian set cramfs endianness (big|little|host), default host\n"
- " -i file insert a file image into the filesystem "
- "(requires >= 2.4.0)\n"
- " -n name set name of cramfs filesystem\n"
- " -p pad by %d bytes for boot code\n"
- " -s sort directory entries (old option, ignored)\n"
- " -z make explicit holes (requires >= 2.3.39)\n"
- " dirname root of the filesystem to be compressed\n"
- " outfile output file\n"),
- program_invocation_short_name, PAD_SIZE);
-
- exit(status);
+static void __attribute__((__noreturn__)) usage(void)
+{
+ fputs(USAGE_HEADER, stdout);
+ fprintf(stdout, _(" %s [-h] [-v] [-b blksize] [-e edition] [-N endian] [-i file] [-n name] dirname outfile\n"),
+ program_invocation_short_name);
+ fputs(USAGE_SEPARATOR, stdout);
+ fputs(_("Make compressed ROM file system."), stdout);
+ fputs(USAGE_OPTIONS, stdout);
+ fputs(_( " -v be verbose"), stdout);
+ fputs(_( " -E make all warnings errors (non-zero exit status)"), stdout);
+ fputs(_( " -b blksize use this blocksize, must equal page size"), stdout);
+ fputs(_( " -e edition set edition number (part of fsid)"), stdout);
+ fprintf(stdout, _(" -N endian set cramfs endianness (%s|%s|%s), default %s\n"), "big", "little", "host", "host");
+ fputs(_( " -i file insert a file image into the filesystem"), stdout);
+ fputs(_( " -n name set name of cramfs filesystem"), stdout);
+ fprintf(stdout, _(" -p pad by %d bytes for boot code\n"), PAD_SIZE);
+ fputs(_( " -s sort directory entries (old option, ignored)"), stdout);
+ fputs(_( " -z make explicit holes"), stdout);
+ fputs(_( " -l[=<mode>] use exclusive device lock (yes, no or nonblock)"), stdout);
+ fputs(_( " dirname root of the filesystem to be compressed"), stdout);
+ fputs(_( " outfile output file"), stdout);
+ fputs(USAGE_SEPARATOR, stdout);
+ fprintf(stdout, USAGE_HELP_OPTIONS(16));
+ fprintf(stdout, USAGE_MAN_TAIL("mkfs.cramfs(8)"));
+ exit(MKFS_EX_OK);
}
static char *
return NULL;
if (S_ISLNK(mode)) {
+ /* The link buffer is unnecessary to terminate by null as it's
+ * always used as buffer rather than a string */
start = xmalloc(size);
if (readlink(path, start, size) < 0) {
warn(_("readlink failed: %s"), path);
/* compute md5sums, so that we do not have to compare every pair of files */
static void
mdfile(struct entry *e) {
- MD5_CTX ctx;
char *start;
start = do_mmap(e->path, e->size, e->mode);
if (start == NULL) {
e->flags |= CRAMFS_EFLAG_INVALID;
} else {
- MD5Init(&ctx);
- MD5Update(&ctx, (unsigned char *) start, e->size);
- MD5Final(e->md5sum, &ctx);
+ UL_MD5_CTX ctx;
+
+ ul_MD5Init(&ctx);
+ ul_MD5Update(&ctx, (unsigned char *) start, e->size);
+ ul_MD5Final(e->md5sum, &ctx);
do_munmap(start, e->size, e->mode);
if ((orig->flags & CRAMFS_EFLAG_MD5) &&
(new->flags & CRAMFS_EFLAG_MD5) &&
- !memcmp(orig->md5sum, new->md5sum, MD5LENGTH) &&
+ !memcmp(orig->md5sum, new->md5sum, UL_MD5LENGTH) &&
identical_file(orig, new)) {
new->same = orig;
*fslen_ub -= new->size;
endpath++;
/* read in the directory and sort */
- dircount = scandir(name, &dirlist, 0, cramsort);
+ dircount = scandir(name, &dirlist, NULL, cramsort);
if (dircount < 0)
err(MKFS_EX_ERROR, _("could not read directory %s"), name);
if (dirent->d_name[0] == '.') {
if (dirent->d_name[1] == '\0')
continue;
- if (dirent->d_name[1] == '.') {
- if (dirent->d_name[2] == '\0')
- continue;
- }
+ if (dirent->d_name[1] == '.' &&
+ dirent->d_name[2] == '\0')
+ continue;
}
namelen = strlen(dirent->d_name);
- if (namelen > MAX_INPUT_NAMELEN)
- errx(MKFS_EX_ERROR,
- _("Very long (%zu bytes) filename `%s' found.\n"
- " Please increase MAX_INPUT_NAMELEN in "
- "mkcramfs.c and recompile. Exiting."),
- namelen, dirent->d_name);
+ if (namelen > MAX_INPUT_NAMELEN) {
+ namelen = MAX_INPUT_NAMELEN;
+ warn_namelen = 1;
+ }
+
memcpy(endpath, dirent->d_name, namelen + 1);
if (lstat(path, &st) < 0) {
continue;
}
entry = xcalloc(1, sizeof(struct entry));
- entry->name = (unsigned char *)xstrdup(dirent->d_name);
- if (namelen > 255) {
- /* Can't happen when reading from ext2fs. */
-
- /* TODO: we ought to avoid chopping in half
- multi-byte UTF8 characters. */
- entry->name[namelen = 255] = '\0';
- warn_namelen = 1;
- }
+ entry->name = (unsigned char *)xstrndup(dirent->d_name, namelen);
entry->mode = st.st_mode;
entry->size = st.st_size;
entry->uid = st.st_uid;
entry->size = parse_directory(root_entry, path, &entry->child, fslen_ub);
} else if (S_ISREG(st.st_mode)) {
entry->path = xstrdup(path);
- if (entry->size) {
- if (entry->size >= (1 << CRAMFS_SIZE_WIDTH)) {
- warn_size = 1;
- entry->size = (1 << CRAMFS_SIZE_WIDTH) - 1;
- }
+ if (entry->size >= (1 << CRAMFS_SIZE_WIDTH)) {
+ warn_size = 1;
+ entry->size = (1 << CRAMFS_SIZE_WIDTH) - 1;
}
} else if (S_ISLNK(st.st_mode)) {
entry->path = xstrdup(path);
super->size = size;
memcpy(super->signature, CRAMFS_SIGNATURE, sizeof(super->signature));
- super->fsid.crc = crc32(0L, Z_NULL, 0);
+ super->fsid.crc = crc32(0L, NULL, 0);
super->fsid.edition = opt_edition;
super->fsid.blocks = total_blocks;
super->fsid.files = total_nodes;
memset(super->name, 0x00, sizeof(super->name));
if (opt_name)
- strncpy((char *)super->name, opt_name, sizeof(super->name));
+ str2memcpy((char *)super->name, opt_name, sizeof(super->name));
else
- strncpy((char *)super->name, "Compressed", sizeof(super->name));
+ str2memcpy((char *)super->name, "Compressed", sizeof(super->name));
super->root.mode = root->mode;
super->root.uid = root->uid;
if (entry->child) {
if (stack_entries >= stack_size) {
stack_size *= 2;
- entry_stack = xrealloc(entry_stack, stack_size * sizeof(struct entry *));
+ entry_stack = xreallocarray(entry_stack, stack_size, sizeof(struct entry *));
}
entry_stack[stack_entries] = entry;
stack_entries++;
(len-- == 0 ||
(begin[3] == '\0' &&
memcmp(begin, begin + 4, len) == 0))))))));
- else
- /* Never create holes. */
- return 0;
+
+ /* Never create holes. */
+ return 0;
}
/*
loff_t fslen_ub = sizeof(struct cramfs_super);
unsigned int fslen_max;
char const *dirname, *outfile;
- uint32_t crc = crc32(0L, Z_NULL, 0);
+ char *lockmode = 0;
+ uint32_t crc = crc32(0L, NULL, 0);
int c;
cramfs_is_big_endian = HOST_IS_BIG_ENDIAN; /* default is to use host order */
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
- atexit(close_stdout);
+ close_stdout_atexit();
+
+ if (argc > 1) {
+ /* first arg may be one of our standard longopts */
+ if (!strcmp(argv[1], "--help"))
+ usage();
+ if (!strcmp(argv[1], "--version")) {
+ print_version(EXIT_SUCCESS);
+ exit(MKFS_EX_OK);
+ }
+ }
+ strutils_set_exitcode(MKFS_EX_USAGE);
/* command line options */
- while ((c = getopt(argc, argv, "hb:Ee:i:n:N:psVvz")) != EOF) {
+ while ((c = getopt(argc, argv, "hb:Ee:i:n:N:l::psVvz")) != EOF) {
switch (c) {
case 'h':
- usage(MKFS_EX_OK);
+ usage();
case 'b':
blksize = strtou32_or_err(optarg, _("invalid blocksize argument"));
break;
image_length = st.st_size; /* may be padded later */
fslen_ub += (image_length + 3); /* 3 is for padding */
break;
+ case 'l':
+ lockmode = "1";
+ if (optarg) {
+ if (*optarg == '=')
+ optarg++;
+ lockmode = optarg;
+ }
+ break;
case 'n':
opt_name = optarg;
break;
/* old option, ignored */
break;
case 'V':
- printf(UTIL_LINUX_VERSION);
- exit(MKFS_EX_OK);
+ print_version(MKFS_EX_OK);
case 'v':
verbose = 1;
break;
opt_holes = 1;
break;
default:
- usage(FSCK_EX_USAGE);
+ errtryhelp(MKFS_EX_USAGE);
}
}
- if ((argc - optind) != 2)
- usage(MKFS_EX_USAGE);
+ if ((argc - optind) != 2) {
+ warnx(_("bad usage"));
+ errtryhelp(MKFS_EX_USAGE);
+ }
dirname = argv[optind];
outfile = argv[optind + 1];
if (fd < 0)
err(MKFS_EX_USAGE, _("cannot open %s"), outfile);
+ if (blkdev_lock(fd, outfile, lockmode) != 0)
+ exit(MKFS_EX_ERROR);
+
root_entry = xcalloc(1, sizeof(struct entry));
root_entry->mode = st.st_mode;
root_entry->uid = st.st_uid;
if (warn_namelen)
/* Can't happen when reading from ext2fs. */
/* Bytes, not chars: think UTF8. */
- warnx(_("warning: filenames truncated to 255 bytes."));
+ warnx(_("warning: filenames truncated to %u bytes."), MAX_INPUT_NAMELEN);
if (warn_skip)
warnx(_("warning: files were skipped due to errors."));
if (warn_size)
(warn_namelen|warn_skip|warn_size|warn_uid|warn_gid|warn_dev))
exit(MKFS_EX_ERROR);
- return EXIT_SUCCESS;
+ return MKFS_EX_OK;
}