/* * #include * off_t lseek(int fd, off_t offset, int whence = SEEK_SET) * retunrs -1 on error */ /* * mkudf.c * * PURPOSE * Create a Linux native UDF file system image. * * DESCRIPTION * It is _vital_ that all possible error conditions be checked when * writing to the file system image file! * * All errors should be output on stderr (not stdout)! * * CONTACTS * E-mail regarding any portion of the Linux UDF file system should be * directed to the development team mailing list (run by majordomo): * linux_udf@hootie.lvld.hp.com * * COPYRIGHT * This file is distributed under the terms of the GNU General Public * License (GPL) version 2.0. Copies of the GPL can be obtained from: * ftp://prep.ai.mit.edu/pub/gnu/GPL * Each contributing author retains all rights to their own work. */ #include #include #include #include #include #include #include #include /* These should be changed if you make any code changes */ #define VERSION_MAJOR 0 #define VERSION_MINOR 0 #define VERSION_BUILD 2 /* * Command line option token values. * 0x0000-0x00ff Single characters * 0x1000-0x1fff Long switches (no arg) * 0x2000-0x2fff Long settings (arg required) */ #define OPT_HELP 0x1010 #define OPT_VERBOSE 0x1020 #define OPT_VERSION 0x1030 #define OPT_BLOCKS 0x2010 #define OPT_BLK_SIZE 0x2020 #define OPT_DIR 0x2030 #define OPT_LVOL_ID 0x2040 #define OPT_MEDIA 0x2050 #define OPT_OFFSET 0x2060 #define OPT_ABSTRACT 0x2070 #define OPT_COPYRIGHT 0x2080 #define OPT_VOL_ID 0x2090 #define OPT_VOL_NUM 0x20a0 #define OPT_SET_ID 0x20b0 #define OPT_SET_SIZE 0x20c0 /* Long command line options */ struct option long_options[] = { { "help", no_argument, NULL, OPT_HELP }, { "verbose", no_argument, NULL, OPT_VERBOSE }, { "version", no_argument, NULL, OPT_VERSION }, { "blocks", required_argument, NULL, OPT_BLOCKS }, { "block-size", required_argument, NULL, OPT_BLK_SIZE }, { "directory", required_argument, NULL, OPT_DIR }, { "logical-volume-id", required_argument, NULL, OPT_LVOL_ID }, { "media-type", required_argument, NULL, OPT_MEDIA }, { "offset", required_argument, NULL, OPT_OFFSET }, { "volume-abstract", required_argument, NULL, OPT_ABSTRACT }, { "volume-copyright", required_argument, NULL, OPT_COPYRIGHT }, { "volume-id", required_argument, NULL, OPT_VOL_ID }, { "volume-number", required_argument, NULL, OPT_VOL_NUM }, { "volume-set-id", required_argument, NULL, OPT_SET_ID }, { "volume-set-size", required_argument, NULL, OPT_SET_SIZE } }; /* Command line globals */ char *filename; unsigned opt_blocksize = 0U; unsigned opt_blocks = 0U; char *opt_dir = NULL; char *opt_lvol_id = NULL; unsigned opt_media = E167_MEDIA_OW; unsigned opt_offset = 0U; char *opt_abstract = NULL; char *opt_copyright = NULL; char *opt_vol_id = NULL; char *opt_set_id = NULL; unsigned opt_set_size = 1U; /* Generic globals */ int fs_img; unsigned blocksize; __u8 buffer[PAGE_SIZE]; /* * usage * * DESCRIPTION * Output a usage message to stderr, and exit. * * HISTORY * December 2, 1997 - Andrew E. Mileski * Written, tested, and released. */ void usage(void) { fprintf(stderr, "usage:\n" "\tmkudf [options] FILE\n" "Switches:\n" "\t--help\n" "\t--verbose\n" "\t--version\n" "Settings:\n" "\t--blocks=NUMBER\n" "\t--block-size=NUMBER\n" "\t--directory=DIRECTORY\n" "\t--logical-volume-id=STRING\n" "\t--media-type=ow|ro|rw|wo\n" "\t--offset=NUMBER\n" "\t--volume-abstract=FILE\n" "\t--volume-copyright=FILE\n" "\t--volume-id=STRING\n" "\t--volume-number=NUMBER\n" "\t--volume-set-id=STRING\n" "\t--volume-set-size=NUMBER\n" ); exit(0); } /* * parse_args * * PURPOSE * Parse the command line args. * * HISTORY * December 2, 1997 - Andrew E. Mileski * Written, tested, and released */ void parse_args(int argc, char *argv[]) { int retval; while (argc > 1) { retval = getopt_long(argc, argv, "V", long_options, NULL); switch (retval) { case OPT_BLOCKSIZE: opt_blocksize = strtoul(optarg, 0, 0); break; case OPT_DIR: opt_directory = optarg; break; case EOF: return; case OPT_HELP: usage(); case OPT_SIZE: opt_blocks = strtoul(optarg, 0, 0); break; case OPT_VERSION: case 'V': fprintf(stderr, "mkudf (Linux UDF tools) " "%d.%d (%d)\n", VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD "\n"); exit(0); default: fprintf(stderr, "Try `mkudf --help' " "for more information\n"); exit(-1); } } if (optind == argc) opt_filename = argv[optind]; else { fprintf(stderr, "Try `mkudf --help' for more information\n"); exit(-1) } } void block_to_offset(unsigned block, unsigned *high, unsigned *low) { *low = block << blocksize_bits; *high = block >> (32 - blocksize_bits); } /* * write_vrs * * PURPOSE * Write the Volume Recognition Sequence (VRS). * * DESCRIPTION * The Linux native VRS contains only 3 descriptors: * BEA01 NSR02 TEA01 * This is covered in ECMA-167 part 2, and 3/9. * * HISTORY * December 3, 1997 - Andrew E. Mileski * Written, tested, and released. */ void write_vrs(void) { struct E167VolDesc *vd; unsigned index; memset(buffer, 0, sizeof(buffer)); vd->structVersion = 0x01U; memcpy(vd->stdID, E167_STDID_BEA01, E167_STDID_LEN); for (index = 0; index < 2048; index += blocksize) retval = write(fs_img, buffer + index, blocksize) if (retval == -1) { perror("error writing BEA01 descriptor"); exit(-1); } } memcpy(vd->stdID, E167_STDID_NSR02, E167_STDID_LEN); for (index = 0; index < 2048; index += blocksize) retval = write(fs_img, buffer + index, blocksize) if (retval == -1) { perror("error writing NSR02 descriptor"); exit(-1); } } memcpy(vd->stdID, E167_STDID_TEA01, E167_STDID_LEN); for (index = 0; index < 2048; index += blocksize) retval = write(fs_img, buffer + index, blocksize) if (retval == -1) { perror("error writing TEA01 descriptor"); exit(-1); } } } int main(int argc, char *argv[]) { int retval; parse_args(argc, argv); fs_img = open(argv[1], O_WRONLY | O_CREAT); if (fs_img == -1) { perror("error opening image file"); return -1; } get_blocksize(); write_system_area(); write_vrs(); close(fs_img); return 0; }