]> git.ipfire.org Git - thirdparty/util-linux.git/blobdiff - disk-utils/fsck.cramfs.c
agetty: fix output of escaped characters
[thirdparty/util-linux.git] / disk-utils / fsck.cramfs.c
index d4967dccb7c38bd9f7b4689a0466539978fdf0b2..0d9bdadf779f25846888b34337d49ac83c6977ee 100644 (file)
 #include <getopt.h>
 #include <utime.h>
 #include <fcntl.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 <sys/types.h>
 #include <sys/stat.h>
 #include <sys/mman.h>
-#include <sys/sysmacros.h>     /* for major, minor */
 
+#include "c.h"
 #include "cramfs.h"
 #include "nls.h"
 #include "blkdev.h"
-#include "c.h"
 #include "exitcodes.h"
 #include "strutils.h"
 #include "closestream.h"
 
 static int fd;                 /* ROM image file descriptor */
 static char *filename;         /* ROM image filename */
-struct cramfs_super super;     /* just find the cramfs superblock once */
+static struct cramfs_super super;      /* just find the cramfs superblock once */
 static int cramfs_is_big_endian = 0;   /* source is big endian */
 static int opt_verbose = 0;    /* 1 = verbose (-v), 2+ = very verbose (-vv) */
 static int opt_extract = 0;    /* extract cramfs (-x) */
-char *extract_dir = "";                /* optional extraction directory (-x) */
+static char *extract_dir = "";         /* optional extraction directory (-x) */
 
 #define PAD_SIZE 512
 
@@ -97,26 +102,28 @@ static char *outbuffer;
 
 static size_t blksize = 0;
 
-
-/* Input status of 0 to print help and exit without an error. */
-static void __attribute__((__noreturn__)) usage(int status)
+static void __attribute__((__noreturn__)) usage(void)
 {
-       FILE *stream = status ? stderr : stdout;
-
-       fputs(USAGE_HEADER, stream);
-       fprintf(stream,
-               _(" %s [options] file\n"), program_invocation_short_name);
-       fputs(USAGE_OPTIONS, stream);
-       fputs(_(" -a                       for compatibility only, ignored\n"), stream);
-       fputs(_(" -v, --verbose            be more verbose\n"), stream);
-       fputs(_(" -y                       for compatibility only, ignored\n"), stream);
-       fputs(_(" -b, --blocksize <size>   use this blocksize, defaults to page size\n"), stream);
-       fputs(_("     --extract[=<dir>]    test uncompression, optionally extract into <dir>\n"), stream);
-       fputs(USAGE_SEPARATOR, stream);
-       fputs(USAGE_HELP, stream);
-       fputs(USAGE_VERSION, stream);
-       fputs(USAGE_SEPARATOR, stream);
-       exit(status);
+       FILE *out = stdout;
+
+       fputs(USAGE_HEADER, out);
+       fprintf(out,
+               _(" %s [options] <file>\n"), program_invocation_short_name);
+
+       fputs(USAGE_SEPARATOR, out);
+       fputs(_("Check and repair a compressed ROM filesystem.\n"), out);
+
+       fputs(USAGE_OPTIONS, out);
+       fputs(_(" -a                       for compatibility only, ignored\n"), out);
+       fputs(_(" -v, --verbose            be more verbose\n"), out);
+       fputs(_(" -y                       for compatibility only, ignored\n"), out);
+       fputs(_(" -b, --blocksize <size>   use this blocksize, defaults to page size\n"), out);
+       fputs(_("     --extract[=<dir>]    test uncompression, optionally extract into <dir>\n"), out);
+       fputs(USAGE_SEPARATOR, out);
+       printf(USAGE_HELP_OPTIONS(26));
+
+       printf(USAGE_MAN_TAIL("fsck.cramfs(8)"));
+       exit(FSCK_EX_OK);
 }
 
 static int get_superblock_endianness(uint32_t magic)
@@ -138,7 +145,7 @@ static void test_super(int *start, size_t * length)
 
        /* find the physical size of the file or block device */
        if (stat(filename, &st) < 0)
-               err(FSCK_EX_ERROR, _("stat failed %s"), filename);
+               err(FSCK_EX_ERROR, _("stat of %s failed"), filename);
 
        fd = open(filename, O_RDONLY);
        if (fd < 0)
@@ -185,7 +192,7 @@ static void test_super(int *start, size_t * length)
                errx(FSCK_EX_ERROR, _("unsupported filesystem features"));
 
        /* What are valid superblock sizes? */
-       if (super.size < sizeof(struct cramfs_super))
+       if (super.size < *start + sizeof(struct cramfs_super))
                errx(FSCK_EX_UNCORRECTED, _("superblock size (%d) too small"),
                     super.size);
 
@@ -210,7 +217,7 @@ static void test_crc(int start)
                return;
        }
 
-       crc = crc32(0L, Z_NULL, 0);
+       crc = crc32(0L, NULL, 0);
 
        buf =
            mmap(NULL, super.size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
@@ -219,15 +226,20 @@ static void test_crc(int start)
                    mmap(NULL, super.size, PROT_READ | PROT_WRITE,
                         MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
                if (buf != MAP_FAILED) {
+                       ssize_t tmp;
                        if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
                                err(FSCK_EX_ERROR, _("seek on %s failed"), filename);
-                       if (read(fd, buf, super.size) < 0)
+                       tmp = read(fd, buf, super.size);
+                       if (tmp < 0)
                                err(FSCK_EX_ERROR, _("cannot read %s"), filename);
+                       if (tmp != (ssize_t) super.size)
+                               errx(FSCK_EX_ERROR, _("failed to read %"PRIu32" bytes from file %s"),
+                                       super.size, filename);
                }
        }
        if (buf != MAP_FAILED) {
                ((struct cramfs_super *)((unsigned char *) buf + start))->fsid.crc =
-                   crc32(0L, Z_NULL, 0);
+                   crc32(0L, NULL, 0);
                crc = crc32(crc, (unsigned char *) buf + start, super.size - start);
                munmap(buf, super.size);
        } else {
@@ -245,7 +257,7 @@ static void test_crc(int start)
                                break;
                        if (length == 0)
                                ((struct cramfs_super *)buf)->fsid.crc =
-                                   crc32(0L, Z_NULL, 0);
+                                   crc32(0L, NULL, 0);
                        length += retval;
                        if (length > (super.size - start)) {
                                crc = crc32(crc, buf,
@@ -360,7 +372,7 @@ static int uncompress_block(void *src, size_t len)
 #define lchown chown
 #endif
 
-static void do_uncompress(char *path, int fd, unsigned long offset,
+static void do_uncompress(char *path, int outfd, unsigned long offset,
                          unsigned long size)
 {
        unsigned long curr = offset + 4 * ((size + blksize - 1) / blksize);
@@ -377,14 +389,14 @@ static void do_uncompress(char *path, int fd, unsigned long offset,
                offset += 4;
                if (curr == next) {
                        if (opt_verbose > 1)
-                               printf(_("  hole at %ld (%zd)\n"), curr,
+                               printf(_("  hole at %lu (%zu)\n"), curr,
                                       blksize);
                        if (size < blksize)
                                out = size;
                        memset(outbuffer, 0x00, out);
                } else {
                        if (opt_verbose > 1)
-                               printf(_("  uncompressing block at %ld to %ld (%ld)\n"),
+                               printf(_("  uncompressing block at %lu to %lu (%lu)\n"),
                                       curr, next, next - curr);
                        out = uncompress_block(romfs_read(curr), next - curr);
                }
@@ -399,10 +411,8 @@ static void do_uncompress(char *path, int fd, unsigned long offset,
                                     size);
                }
                size -= out;
-               if (*extract_dir != '\0')
-                       if (write(fd, outbuffer, out) < 0)
-                               err(FSCK_EX_ERROR, _("write failed: %s"),
-                                   path);
+               if (*extract_dir != '\0' && write(outfd, outbuffer, out) < 0)
+                       err(FSCK_EX_ERROR, _("write failed: %s"), path);
                curr = next;
        } while (size);
 }
@@ -484,7 +494,7 @@ static void do_directory(char *path, struct cramfs_inode *i)
 static void do_file(char *path, struct cramfs_inode *i)
 {
        unsigned long offset = i->offset << 2;
-       int fd = 0;
+       int outfd = 0;
 
        if (offset == 0 && i->size != 0)
                errx(FSCK_EX_UNCORRECTED,
@@ -497,14 +507,14 @@ static void do_file(char *path, struct cramfs_inode *i)
        if (opt_verbose)
                print_node('f', i, path);
        if (*extract_dir != '\0') {
-               fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, i->mode);
-               if (fd < 0)
+               outfd = open(path, O_WRONLY | O_CREAT | O_TRUNC, i->mode);
+               if (outfd < 0)
                        err(FSCK_EX_ERROR, _("cannot open %s"), path);
        }
        if (i->size)
-               do_uncompress(path, fd, offset, i->size);
+               do_uncompress(path, outfd, offset, i->size);
        if ( *extract_dir != '\0') {
-               if (close_fd(fd) != 0)
+               if (close_fd(outfd) != 0)
                        err(FSCK_EX_ERROR, _("write failed: %s"), path);
                change_file_status(path, i);
        }
@@ -539,7 +549,7 @@ static void do_symlink(char *path, struct cramfs_inode *i)
                xasprintf(&str, "%s -> %s", path, outbuffer);
                print_node('l', i, str);
                if (opt_verbose > 1)
-                       printf(_("  uncompressing block at %ld to %ld (%ld)\n"),
+                       printf(_("  uncompressing block at %lu to %lu (%lu)\n"),
                               curr, next, next - curr);
                free(str);
        }
@@ -618,16 +628,15 @@ static void test_fs(int start)
        if (start_data != ~0UL) {
                if (start_data < (sizeof(struct cramfs_super) + start))
                        errx(FSCK_EX_UNCORRECTED,
-                            _("directory data start (%ld) < sizeof(struct cramfs_super) + start (%ld)"),
+                            _("directory data start (%lu) < sizeof(struct cramfs_super) + start (%zu)"),
                             start_data, sizeof(struct cramfs_super) + start);
                if (end_dir != start_data)
                        errx(FSCK_EX_UNCORRECTED,
-                            _("directory data end (%ld) != file data start (%ld)"),
+                            _("directory data end (%lu) != file data start (%lu)"),
                             end_dir, start_data);
        }
-       if (super.flags & CRAMFS_FLAG_FSID_VERSION_2)
-               if (end_data > super.size)
-                       errx(FSCK_EX_UNCORRECTED, _("invalid file data offset"));
+       if (super.flags & CRAMFS_FLAG_FSID_VERSION_2 && end_data > super.size)
+               errx(FSCK_EX_UNCORRECTED, _("invalid file data offset"));
 
        iput(root);             /* free(root) */
 }
@@ -639,12 +648,12 @@ int main(int argc, char **argv)
        size_t length = 0;
 
        static const struct option longopts[] = {
-               {"verbose", no_argument, 0, 'v'},
-               {"version", no_argument, 0, 'V'},
-               {"help", no_argument, 0, 'h'},
-               {"blocksize", required_argument, 0, 'b'},
-               {"extract", optional_argument, 0, 'x'},
-               {NULL, no_argument, 0, '0'},
+               {"verbose",   no_argument,       NULL, 'v'},
+               {"version",   no_argument,       NULL, 'V'},
+               {"help",      no_argument,       NULL, 'h'},
+               {"blocksize", required_argument, NULL, 'b'},
+               {"extract",   optional_argument, NULL, 'x'},
+               {NULL, 0, NULL, 0},
        };
 
        setlocale(LC_MESSAGES, "");
@@ -653,6 +662,8 @@ int main(int argc, char **argv)
        textdomain(PACKAGE);
        atexit(close_stdout);
 
+       strutils_set_exitcode(FSCK_EX_USAGE);
+
        /* command line options */
        while ((c = getopt_long(argc, argv, "ayvVhb:", longopts, NULL)) != EOF)
                switch (c) {
@@ -660,11 +671,11 @@ int main(int argc, char **argv)
                case 'y':
                        break;
                case 'h':
-                       usage(FSCK_EX_OK);
+                       usage();
                        break;
                case 'V':
                        printf(UTIL_LINUX_VERSION);
-                       return EXIT_SUCCESS;
+                       return FSCK_EX_OK;
                case 'x':
                        opt_extract = 1;
                        if(optarg)
@@ -677,11 +688,13 @@ int main(int argc, char **argv)
                        blksize = strtou32_or_err(optarg, _("invalid blocksize argument"));
                        break;
                default:
-                       usage(FSCK_EX_USAGE);
+                       errtryhelp(FSCK_EX_USAGE);
                }
 
-       if ((argc - optind) != 1)
-               usage(FSCK_EX_USAGE);
+       if ((argc - optind) != 1){
+               warnx(_("bad usage"));
+               errtryhelp(FSCK_EX_USAGE);
+       }
        filename = argv[optind];
 
        test_super(&start, &length);