/* * Copyright (c) 2007 - 2016 Vreixo Formoso, Thomas Schmitt * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * or later as published by the Free Software Foundation. * See COPYING file for details. */ static char helptext[][80] = { "", "This is a collection of libisofs gestures which formerly were distinct", "programs. The first argument chooses the gesture:", " -tree absolute_directory_path", " Import a directory and print the resulting iso tree.", " -find absolute_directory_path", " Import a directory, find matching nodes and print the", " resulting iso tree.", " -iso [options] directory output_file", " Create an iso image from a local directory. For options see", " output of -iso -h", " -iso_read image_file", " Output the contents of an iso image.", " -iso_cat image_file path_in_image", " Extract a file from a given ISO image and put out its content", " to stdout. The file is addressed by path_in_image. The ISO", " image does not get loaded but rather the lookups are done", " directly in the image file.", " -iso_modify image_file absolute_directory_path output_file", " Load an iso image, add a directory, and write complete image.", " -iso_ms image_lba nwa image_file directory_path output_file", " Load an iso image, add a directory, and write as add-on", " session which shall be appended to the old image.", " image_lba gives the block address of the start of the most", " recent session in the image_file. nwa gives the block address", " where the add-on session will be appended to the image.", "@" }; #define LIBISOFS_WITHOUT_LIBBURN yes #include "libisofs.h" #include #include #include #include #include #include #include #include #include #include #include #ifndef PATH_MAX #define PATH_MAX Libisofs_default_path_maX #endif /* ----------------------------- utilities -------------------------- */ void demo_report_iso_err(int err, char *occasion) { char *severity; fprintf(stderr, "%s : err = 0x%X", occasion, (unsigned int) err); if (err < 0) { iso_sev_to_text(iso_error_get_severity(err), &severity); fprintf(stderr, " -> %s '%s'", severity, iso_error_to_msg(err)); } fprintf(stderr, "\n"); } /* ------------------------- from demo/tree.c ----------------------- */ static void print_permissions(mode_t mode) { char perm[10]; /* TODO suid, sticky... */ perm[9] = '\0'; perm[8] = mode & S_IXOTH ? 'x' : '-'; perm[7] = mode & S_IWOTH ? 'w' : '-'; perm[6] = mode & S_IROTH ? 'r' : '-'; perm[5] = mode & S_IXGRP ? 'x' : '-'; perm[4] = mode & S_IWGRP ? 'w' : '-'; perm[3] = mode & S_IRGRP ? 'r' : '-'; perm[2] = mode & S_IXUSR ? 'x' : '-'; perm[1] = mode & S_IWUSR ? 'w' : '-'; perm[0] = mode & S_IRUSR ? 'r' : '-'; printf("[%s]",perm); } static void tree_print_dir(IsoDir *dir, int level) { int i; IsoDirIter *iter; IsoNode *node; char *sp; sp = calloc(1, level * 2 + 1); for (i = 0; i < level * 2; i += 2) { sp[i] = '|'; sp[i+1] = ' '; } if (level > 0) sp[level * 2 - 1] = '-'; sp[level * 2] = '\0'; iso_dir_get_children(dir, &iter); while (iso_dir_iter_next(iter, &node) == 1) { if (ISO_NODE_IS_DIR(node)) { printf("%s+[D] ", sp); print_permissions(iso_node_get_permissions(node)); printf(" %s\n", iso_node_get_name(node)); tree_print_dir(ISO_DIR(node), level+1); } else if (ISO_NODE_IS_FILE(node)) { printf("%s-[F] ", sp); print_permissions(iso_node_get_permissions(node)); printf(" %s\n", iso_node_get_name(node) ); } else if (ISO_NODE_IS_SYMLINK(node)) { printf("%s-[L] ", sp); print_permissions(iso_node_get_permissions(node)); printf(" %s -> %s \n", iso_node_get_name(node), iso_symlink_get_dest(ISO_SYMLINK(node)) ); } else { printf("%s-[C] ", sp); print_permissions(iso_node_get_permissions(node)); printf(" %s\n", iso_node_get_name(node) ); } } iso_dir_iter_free(iter); free(sp); } int gesture_tree(int argc, char **argv) { int result; IsoImage *image; if (argc != 2) { need_abs_path:; fprintf (stderr, "You need to specify a valid absolute path\n"); return 1; } if (argv[1][0] != '/') goto need_abs_path; iso_init(); iso_set_msgs_severities("NEVER", "ALL", ""); result = iso_image_new("volume_id", &image); if (result < 0) { printf ("Error creating image\n"); return 1; } result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[1]); if (result < 0) { printf ("Error adding directory %d\n", result); return 1; } printf("================= IMAGE =================\n"); tree_print_dir(iso_image_get_root(image), 0); printf("\n\n"); iso_image_unref(image); iso_finish(); return 0; } /* ------------------------- from demo/find.c ----------------------- */ static void find_print_dir(IsoDir *dir) { IsoDirIter *iter; IsoNode *node; IsoFindCondition *cond, *c1, *c2; c1 = iso_new_find_conditions_name("*a*"); c2 = iso_new_find_conditions_mode(S_IFREG); cond = iso_new_find_conditions_and(c1, c2); iso_dir_find_children(dir, cond, &iter); while (iso_dir_iter_next(iter, &node) == 1) { char *path = iso_tree_get_node_path(node); printf(" %s\n", path); free(path); } iso_dir_iter_free(iter); } int gesture_find(int argc, char **argv) { int result; IsoImage *image; if (argc != 2) { need_abs_path:; fprintf (stderr, "You need to specify a valid absolute path\n"); return 1; } if (argv[1][0] != '/') goto need_abs_path; iso_init(); iso_set_msgs_severities("NEVER", "ALL", ""); result = iso_image_new("volume_id", &image); if (result < 0) { printf ("Error creating image\n"); return 1; } result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[1]); if (result < 0) { printf ("Error adding directory %d\n", result); return 1; } find_print_dir(iso_image_get_root(image)); iso_image_unref(image); iso_finish(); return 0; } /* ------------------------- from demo/iso.c ----------------------- */ static const char * const optstring = "JRIL:b:hV:"; extern char *optarg; extern int optind; void iso_usage(char **argv) { printf("%s [OPTIONS] DIRECTORY OUTPUT\n", argv[0]); } void iso_help() { printf( "Options:\n" " -J Add Joliet support\n" " -R Add Rock Ridge support\n" " -I Add ISO 9660:1999 support\n" " -V label Volume Label\n" " -L Set the ISO level (1 or 2)\n" " -b file Specifies a boot image to add to image\n" " -h Print this message\n" ); } int iso_callback(IsoFileSource *src) { char *path = iso_file_source_get_path(src); printf("CALLBACK: %s\n", path); free(path); return 1; } int gesture_iso(int argc, char **argv) { int result; int c; IsoImage *image; struct burn_source *burn_src; unsigned char buf[2048]; FILE *fp = NULL; IsoWriteOpts *opts; char *volid = "VOLID"; char *boot_img = NULL; int rr = 0, j = 0, iso1999 = 0, level = 1; while ((c = getopt(argc, argv, optstring)) != -1) { switch(c) { case 'h': iso_usage(argv); iso_help(); goto ex; break; case 'J': j = 1; break; case 'R': rr = 1; break; case 'I': iso1999 = 1; break; case 'L': level = atoi(optarg); break; case 'b': boot_img = optarg; break; case 'V': volid = optarg; break; case '?': iso_usage(argv); goto ex; break; } } if (argc < 2) { printf ("Please pass directory from which to build ISO\n"); iso_usage(argv); goto ex; } if (argc < 3) { printf ("Please supply output file\n"); iso_usage(argv); goto ex; } fp = fopen(argv[optind+1], "w"); if (fp == NULL) { err(1, "error opening output file"); goto ex; } result = iso_init(); if (result < 0) { printf ("Can't initialize libisofs\n"); goto ex; } iso_set_msgs_severities("NEVER", "ALL", ""); result = iso_image_new(volid, &image); if (result < 0) { printf ("Error creating image\n"); goto ex; } iso_tree_set_follow_symlinks(image, 0); iso_tree_set_ignore_hidden(image, 0); iso_tree_set_ignore_special(image, 0); iso_set_abort_severity("SORRY"); /*iso_tree_set_report_callback(image, callback);*/ result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[optind]); if (result < 0) { printf ("Error adding directory %d\n", result); goto ex; } if (boot_img) { /* adds El-Torito boot info. Tunned for isolinux */ ElToritoBootImage *bootimg; result = iso_image_set_boot_image(image, boot_img, ELTORITO_NO_EMUL, "/isolinux/boot.cat", &bootimg); if (result < 0) { printf ("Error adding boot image %d\n", result); goto ex; } el_torito_set_load_size(bootimg, 4); el_torito_patch_isolinux_image(bootimg); } result = iso_write_opts_new(&opts, 0); if (result < 0) { printf ("Cannot create write opts, error %d\n", result); goto ex; } iso_write_opts_set_iso_level(opts, level); iso_write_opts_set_rockridge(opts, rr); iso_write_opts_set_joliet(opts, j); iso_write_opts_set_iso1999(opts, iso1999); result = iso_image_create_burn_source(image, opts, &burn_src); if (result < 0) { printf ("Cannot create image, error %d\n", result); goto ex; } iso_write_opts_free(opts); while (burn_src->read_xt(burn_src, buf, 2048) == 2048) { result = fwrite(buf, 1, 2048, fp); if (result < 2048) { printf ("Cannot write block. errno= %d\n", errno); goto ex; } } fclose(fp); burn_src->free_data(burn_src); free(burn_src); iso_image_unref(image); iso_finish(); return 0; ex:; if (fp != NULL) fclose(fp); return 1; } /* ------------------------- from demo/iso_read.c ----------------------- */ static void iso_read_print_type(mode_t mode) { switch(mode & S_IFMT) { case S_IFSOCK: printf("[S] "); break; case S_IFLNK: printf("[L] "); break; case S_IFREG: printf("[R] "); break; case S_IFBLK: printf("[B] "); break; case S_IFDIR: printf("[D] "); break; case S_IFIFO: printf("[F] "); break; } } static void iso_read_print_file_src(IsoFileSource *file) { struct stat info; char *name; iso_file_source_lstat(file, &info); iso_read_print_type(info.st_mode); print_permissions(info.st_mode); printf(" %10.f ", (double) info.st_size); /* printf(" {%ld,%ld} ", (long)info.st_dev, (long)info.st_ino); */ name = iso_file_source_get_name(file); printf(" %s", name); free(name); if (S_ISLNK(info.st_mode)) { char buf[PATH_MAX]; iso_file_source_readlink(file, buf, PATH_MAX); printf(" -> %s\n", buf); } printf("\n"); } static void iso_read_print_dir(IsoFileSource *dir, int level) { int ret, i; IsoFileSource *file; struct stat info; char *sp; sp = calloc(1, level * 2 + 1); for (i = 0; i < level * 2; i += 2) { sp[i] = '|'; sp[i+1] = ' '; } if (level > 0) sp[level * 2 - 1] = '-'; sp[level * 2] = '\0'; ret = iso_file_source_open(dir); if (ret < 0) { printf ("Can't open dir %d\n", ret); } while ((ret = iso_file_source_readdir(dir, &file)) == 1) { printf("%s", sp); iso_read_print_file_src(file); ret = iso_file_source_lstat(file, &info); if (ret < 0) { break; } if (S_ISDIR(info.st_mode)) { iso_read_print_dir(file, level + 1); } iso_file_source_unref(file); } iso_file_source_close(dir); if (ret < 0) { printf ("Can't print dir\n"); } free(sp); } int gesture_iso_read(int argc, char **argv) { int result, initialized = 0, return_val = 1; IsoImageFilesystem *fs = NULL; IsoDataSource *src = NULL; IsoFileSource *root = NULL; IsoReadOpts *ropts = NULL; if (argc != 2) { printf ("You need to specify a valid path\n"); goto ex; } result = iso_init(); if (result < 0) { demo_report_iso_err(result, "Cannot init libisofs"); goto ex; } initialized = 1; iso_set_msgs_severities("NEVER", "ALL", ""); result = iso_data_source_new_from_file(argv[1], &src); if (result < 0) { demo_report_iso_err(result, "Error creating data source"); goto ex; } result = iso_read_opts_new(&ropts, 0); if (result < 0) { demo_report_iso_err(result, "Error creating read options"); goto ex; } result = iso_image_filesystem_new(src, ropts, 1, &fs); if (result < 0) { demo_report_iso_err(result, "Error creating filesystem"); goto ex; } iso_read_opts_free(ropts); ropts = NULL; printf("\nVOLUME INFORMATION\n"); printf("==================\n\n"); printf("Vol. id: %s\n", iso_image_fs_get_volume_id(fs)); printf("Publisher: %s\n", iso_image_fs_get_publisher_id(fs)); printf("Data preparer: %s\n", iso_image_fs_get_data_preparer_id(fs)); printf("System: %s\n", iso_image_fs_get_system_id(fs)); printf("Application: %s\n", iso_image_fs_get_application_id(fs)); printf("Copyright: %s\n", iso_image_fs_get_copyright_file_id(fs)); printf("Abstract: %s\n", iso_image_fs_get_abstract_file_id(fs)); printf("Biblio: %s\n", iso_image_fs_get_biblio_file_id(fs)); printf("\nDIRECTORY TREE\n"); printf("==============\n"); result = fs->get_root(fs, &root); if (result < 0) { demo_report_iso_err(result, "Cannot get root object"); goto ex; } /* iso_read_print_file_src(root); */ iso_read_print_dir(root, 0); return_val = 0; ex:; if (root != NULL) iso_file_source_unref(root); if (ropts != NULL) iso_read_opts_free(ropts); if (fs != NULL) { fs->close(fs); iso_filesystem_unref((IsoFilesystem*)fs); } if (src != NULL) iso_data_source_unref(src); if (initialized) iso_finish(); return return_val; } /* ------------------------- from demo/iso_cat.c ----------------------- */ int gesture_iso_cat(int argc, char **argv) { int res, write_ret, ret; IsoFilesystem *fs = NULL; IsoFileSource *file = NULL; struct stat info; IsoDataSource *src = NULL; IsoReadOpts *opts = NULL; if (argc != 3) { fprintf(stderr, "Usage: -iso_cat /path/to/image /path/to/file\n"); return 1; } res = iso_init(); if (res < 0) { demo_report_iso_err(res, "Cannot init libisofs"); return 1; } /* Important Note: From here on memory objects get created which need to be freed in the end. Therefore in case of problems no direct return, but rather a hop to label "ex:", where cleanup happens. */ res = iso_data_source_new_from_file(argv[1], &src); if (res < 0) { demo_report_iso_err(res, "Error creating data source object"); ret = 1; goto ex; } res = iso_read_opts_new(&opts, 0); if (res < 0) { demo_report_iso_err(res, "Error creating read options object"); ret = 1; goto ex; } res = iso_image_filesystem_new(src, opts, 1, &fs); if (res < 0) { demo_report_iso_err(res, "Error creating filesystem object"); ret = 1; goto ex; } iso_read_opts_free(opts); opts = NULL; res = fs->get_by_path(fs, argv[2], &file); if (res < 0) { demo_report_iso_err(res, "Cannot get file object with given path"); ret = 1; goto ex; } res = iso_file_source_lstat(file, &info); if (res < 0) { demo_report_iso_err(res, "Cannot inquire type of file object with given path"); ret = 1; goto ex; } if (S_ISDIR(info.st_mode)) { fprintf(stderr, "Path refers to a directory!!\n"); ret = 1; goto ex; } else { char buf[1024]; res = iso_file_source_open(file); if (res < 0) { demo_report_iso_err(res, "Cannot open file object with given path"); ret = 1; goto ex; } while ((res = iso_file_source_read(file, buf, 1024)) > 0) { write_ret = fwrite(buf, 1, res, stdout); if (write_ret < res) { printf ("Cannot write block to stdout. errno= %d\n", errno); iso_file_source_close(file); ret = 1; goto ex; } } iso_file_source_close(file); if (res < 0) { demo_report_iso_err(res, "Error while reading data content"); fprintf(stderr, "Error reading, err = 0x%X\n", (unsigned int) res); ret = 1; goto ex; } } ret = 0; ex:; if (file != NULL) iso_file_source_unref(file); if (fs != NULL) iso_filesystem_unref(fs); if (opts != NULL) iso_read_opts_free(opts); if (src != NULL) iso_data_source_unref(src); iso_finish(); return ret; } /* ------------------------- from demo/iso_modify.c ----------------------- */ void iso_modify_usage(char **argv) { printf("%s IMAGE DIRECTORY OUTPUT\n", argv[0]); } int gesture_iso_modify(int argc, char **argv) { int result, return_val = 1, initialized = 0; IsoImage *image = NULL; IsoDataSource *src = NULL; struct burn_source *burn_src = NULL; unsigned char buf[2048]; FILE *fp = NULL; IsoWriteOpts *opts = NULL; IsoReadOpts *ropts = NULL; if (argc < 4) { iso_modify_usage(argv); goto ex; } fp = fopen(argv[3], "w"); if (fp == NULL) { err(1, "error opening output file"); goto ex; } result = iso_init(); if (result < 0) { demo_report_iso_err(result, "Cannot init libisofs"); goto ex; } initialized = 1; iso_set_msgs_severities("NEVER", "ALL", ""); /* create the data source to accesss previous image */ result = iso_data_source_new_from_file(argv[1], &src); if (result < 0) { demo_report_iso_err(result, "Error creating data source"); goto ex; } /* create the image context */ result = iso_image_new("volume_id", &image); if (result < 0) { demo_report_iso_err(result, "Error creating image"); goto ex; } iso_tree_set_follow_symlinks(image, 0); iso_tree_set_ignore_hidden(image, 0); /* import previous image */ result = iso_read_opts_new(&ropts, 0); if (result < 0) { demo_report_iso_err(result, "Error creating read options"); goto ex; } result = iso_image_import(image, src, ropts, NULL); if (result < 0) { demo_report_iso_err(result, "Error importing previous session"); goto ex; } /* (One could of course keep them alive until cleanup) */ iso_read_opts_free(ropts); ropts = NULL; iso_data_source_unref(src); src = NULL; /* add new dir */ result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[2]); if (result < 0) { demo_report_iso_err(result, "Error adding directory"); goto ex; } /* Generate a new image with both previous and added contents. Profile 1 means Rock Ridge and ISO level 3. */ result = iso_write_opts_new(&opts, 1); if (result < 0) { demo_report_iso_err(result, "Cannot create write opts"); goto ex; } /* Prefer specs violation over relocation deep directories */ iso_write_opts_set_allow_deep_paths(opts, 1); /* For MS-Windows readers : iso_write_opts_set_joliet(opts, 1); */ result = iso_image_create_burn_source(image, opts, &burn_src); if (result < 0) { demo_report_iso_err(result, "Cannot create image object"); goto ex; } iso_write_opts_free(opts); opts = NULL; while (burn_src->read_xt(burn_src, buf, 2048) == 2048) { result = fwrite(buf, 1, 2048, fp); if (result < 2048) { fprintf (stderr, "Cannot write block. errno= %d\n", errno); goto ex; } } return_val = 0; ex: if (fp != NULL) fclose(fp); if (opts != NULL) iso_write_opts_free(opts); if (burn_src != NULL) { burn_src->free_data(burn_src); free(burn_src); } if (image != NULL) iso_image_unref(image); if (ropts != NULL) iso_read_opts_free(ropts); if (src != NULL) iso_data_source_unref(src); if (initialized) iso_finish(); return return_val; } /* ------------------------- from demo/iso_ms.c ----------------------- */ void iso_ms_usage(char **argv) { printf("%s LSS NWA DISC DIRECTORY OUTPUT\n", argv[0]); } int gesture_iso_ms(int argc, char **argv) { int result, return_val = 1, initialized = 0; IsoImage *image = NULL; IsoDataSource *src = NULL; struct burn_source *burn_src = NULL; unsigned char buf[2048]; FILE *fp = NULL; IsoWriteOpts *opts = NULL; IsoReadOpts *ropts = NULL; uint32_t ms_block; if (argc < 6) { iso_ms_usage(argv); goto ex; } if (strcmp(argv[3], argv[5]) == 0) { fprintf(stderr, "image_file and output_file must not be the same file.\n"); goto ex; } fp = fopen(argv[5], "w"); if (!fp) { err(1, "error opening output file"); goto ex; } result = iso_init(); if (result < 0) { demo_report_iso_err(result, "Cannot init libisofs"); goto ex; } initialized = 1; iso_set_msgs_severities("NEVER", "ALL", ""); /* create the data source to accesss previous image */ result = iso_data_source_new_from_file(argv[3], &src); if (result < 0) { demo_report_iso_err(result, "Error creating data source"); goto ex; } /* create the image context */ result = iso_image_new("volume_id", &image); if (result < 0) { demo_report_iso_err(result, "Error creating image"); goto ex; } iso_tree_set_follow_symlinks(image, 0); iso_tree_set_ignore_hidden(image, 0); /* import previous image */ result = iso_read_opts_new(&ropts, 0); if (result < 0) { fprintf(stderr, "Error creating read options\n"); goto ex; } iso_read_opts_set_start_block(ropts, atoi(argv[1])); result = iso_image_import(image, src, ropts, NULL); iso_read_opts_free(ropts); ropts = NULL; iso_data_source_unref(src); src = NULL; if (result < 0) { demo_report_iso_err(result, "Error importing previous session"); goto ex; } /* add new dir */ result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[4]); if (result < 0) { demo_report_iso_err(result, "Error adding directory"); goto ex; } /* generate a multisession image with new contents */ result = iso_write_opts_new(&opts, 1); if (result < 0) { demo_report_iso_err(result, "Cannot create write opts"); goto ex; } /* round up to 32kb aligment = 16 block */ ms_block = atoi(argv[2]); iso_write_opts_set_ms_block(opts, ms_block); iso_write_opts_set_appendable(opts, 1); result = iso_image_create_burn_source(image, opts, &burn_src); if (result < 0) { printf ("Cannot create image, error %d\n", result); goto ex; } iso_write_opts_free(opts); opts = NULL; while (burn_src->read_xt(burn_src, buf, 2048) == 2048) { result = fwrite(buf, 1, 2048, fp); if (result < 2048) { printf ("Cannot write block. errno= %d\n", errno); goto ex; } } return_val = 0; ex:; if (burn_src != NULL) { burn_src->free_data(burn_src); free(burn_src); } if (opts != NULL) iso_write_opts_free(opts); if (image) iso_image_unref(image); if (ropts != NULL) iso_read_opts_free(ropts); if (src != NULL) iso_data_source_unref(src); if (initialized) iso_finish(); if (fp != NULL) fclose(fp); return return_val; } /* ------------------------- switcher ----------------------- */ int main(int argc, char **argv) { char *gesture; int i; if (argc < 2) { usage:; fprintf(stderr, "usage: %s gesture [gesture_options]\n", argv[0]); for (i = 0; helptext[i][0] != '@'; i++) fprintf(stderr, "%s\n", helptext[i]); exit(1); } for (gesture = argv[1]; *gesture == '-'; gesture++); if (strcmp(gesture, "tree") == 0) { gesture_tree(argc - 1, &(argv[1])); } else if(strcmp(gesture, "find") == 0) { gesture_find(argc - 1, &(argv[1])); } else if(strcmp(gesture, "iso") == 0) { gesture_iso(argc - 1, &(argv[1])); } else if(strcmp(gesture, "iso_read") == 0) { gesture_iso_read(argc - 1, &(argv[1])); } else if(strcmp(gesture, "iso_cat") == 0) { gesture_iso_cat(argc - 1, &(argv[1])); } else if(strcmp(gesture, "iso_modify") == 0) { gesture_iso_modify(argc - 1, &(argv[1])); } else if(strcmp(gesture, "iso_ms") == 0) { gesture_iso_ms(argc - 1, &(argv[1])); } else { goto usage; } exit(0); }