/* * Copyright (c) 2007 - 2009 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.", " -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 #define LIBISOFS_WITHOUT_LIBBURN yes #include "libisofs.h" #include #include #include #include #include #include #include #include #ifndef PATH_MAX #define PATH_MAX Libisofs_default_path_maX #endif /* ------------------------- 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 = alloca(level * 2 + 1); for (i = 0; i < level * 2; i += 2) { sp[i] = '|'; sp[i+1] = ' '; } 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); } 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 *fd; 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(); exit(0); 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); exit(1); break; } } if (argc < 2) { printf ("Please pass directory from which to build ISO\n"); iso_usage(argv); return 1; } if (argc < 3) { printf ("Please supply output file\n"); iso_usage(argv); return 1; } fd = fopen(argv[optind+1], "w"); if (!fd) { err(1, "error opening output file"); } result = iso_init(); if (result < 0) { printf ("Can't initialize libisofs\n"); return 1; } iso_set_msgs_severities("NEVER", "ALL", ""); result = iso_image_new(volid, &image); if (result < 0) { printf ("Error creating image\n"); return 1; } 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); return 1; } 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); return 1; } el_torito_set_load_size(bootimg, 4); el_torito_patch_isolinux_image(bootimg); } result = iso_write_opts_new(&opts, 0); if (result < 0) { printf ("Cant create write opts, error %d\n", result); return 1; } 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 ("Cant create image, error %d\n", result); return 1; } iso_write_opts_free(opts); while (burn_src->read_xt(burn_src, buf, 2048) == 2048) { fwrite(buf, 1, 2048, fd); } fclose(fd); burn_src->free_data(burn_src); free(burn_src); iso_image_unref(image); iso_finish(); return 0; } /* ------------------------- 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 = alloca(level * 2 + 1); for (i = 0; i < level * 2; i += 2) { sp[i] = '|'; sp[i+1] = ' '; } 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"); } } int gesture_iso_read(int argc, char **argv) { int result; IsoImageFilesystem *fs; IsoDataSource *src; IsoFileSource *root; IsoReadOpts *ropts; if (argc != 2) { printf ("You need to specify a valid path\n"); return 1; } iso_init(); iso_set_msgs_severities("NEVER", "ALL", ""); result = iso_data_source_new_from_file(argv[1], &src); if (result < 0) { printf ("Error creating data source\n"); return 1; } result = iso_read_opts_new(&ropts, 0); if (result < 0) { fprintf(stderr, "Error creating read options\n"); return 1; } result = iso_image_filesystem_new(src, ropts, 1, &fs); iso_read_opts_free(ropts); if (result < 0) { printf ("Error creating filesystem\n"); return 1; } 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) { printf ("Can't get root %d\n", result); return 1; } /* iso_read_print_file_src(root); */ iso_read_print_dir(root, 0); iso_file_source_unref(root); fs->close(fs); iso_filesystem_unref((IsoFilesystem*)fs); iso_data_source_unref(src); iso_finish(); return 0; } /* ------------------------- from demo/iso_cat.c ----------------------- */ int gesture_iso_cat(int argc, char **argv) { int res; IsoFilesystem *fs; IsoFileSource *file; struct stat info; IsoDataSource *src; IsoReadOpts *opts; if (argc != 3) { fprintf(stderr, "Usage: isocat /path/to/image /path/to/file\n"); return 1; } res = iso_init(); if (res < 0) { fprintf(stderr, "Can't init libisofs\n"); return 1; } res = iso_data_source_new_from_file(argv[1], &src); if (res < 0) { fprintf(stderr, "Error creating data source\n"); return 1; } res = iso_read_opts_new(&opts, 0); if (res < 0) { fprintf(stderr, "Error creating read options\n"); return 1; } res = iso_image_filesystem_new(src, opts, 1, &fs); if (res < 0) { fprintf(stderr, "Error creating filesystem\n"); return 1; } iso_read_opts_free(opts); res = fs->get_by_path(fs, argv[2], &file); if (res < 0) { fprintf(stderr, "Can't get file, err = %d\n", res); return 1; } res = iso_file_source_lstat(file, &info); if (res < 0) { fprintf(stderr, "Can't stat file, err = %d\n", res); return 1; } if (S_ISDIR(info.st_mode)) { fprintf(stderr, "Path refers to a directory!!\n"); return 1; } else { char buf[1024]; res = iso_file_source_open(file); if (res < 0) { fprintf(stderr, "Can't open file, err = %d\n", res); return 1; } while ((res = iso_file_source_read(file, buf, 1024)) > 0) { fwrite(buf, 1, res, stdout); } if (res < 0) { fprintf(stderr, "Error reading, err = %d\n", res); return 1; } iso_file_source_close(file); } iso_file_source_unref(file); iso_filesystem_unref(fs); iso_data_source_unref(src); iso_finish(); return 0; } /* ------------------------- 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; IsoImage *image; IsoDataSource *src; struct burn_source *burn_src; unsigned char buf[2048]; FILE *fd; IsoWriteOpts *opts; IsoReadOpts *ropts; if (argc < 4) { iso_modify_usage(argv); return 1; } fd = fopen(argv[3], "w"); if (!fd) { err(1, "error opening output file"); } iso_init(); 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) { printf ("Error creating data source\n"); return 1; } /* create the image context */ result = iso_image_new("volume_id", &image); if (result < 0) { printf ("Error creating image\n"); return 1; } 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"); return 1; } result = iso_image_import(image, src, ropts, NULL); iso_read_opts_free(ropts); iso_data_source_unref(src); if (result < 0) { printf ("Error importing previous session %d\n", result); return 1; } /* add new dir */ result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[2]); if (result < 0) { printf ("Error adding directory %d\n", result); return 1; } /* generate a new image with both previous and added contents */ result = iso_write_opts_new(&opts, 1); if (result < 0) { printf("Cant create write opts, error %d\n", result); return 1; } /* for isolinux: iso_write_opts_set_allow_full_ascii(opts, 1); */ result = iso_image_create_burn_source(image, opts, &burn_src); if (result < 0) { printf ("Cant create image, error %d\n", result); return 1; } iso_write_opts_free(opts); while (burn_src->read_xt(burn_src, buf, 2048) == 2048) { fwrite(buf, 1, 2048, fd); } fclose(fd); burn_src->free_data(burn_src); free(burn_src); iso_image_unref(image); iso_finish(); return 0; } /* ------------------------- 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; IsoImage *image; IsoDataSource *src; struct burn_source *burn_src; unsigned char buf[2048]; FILE *fd; IsoWriteOpts *opts; IsoReadOpts *ropts; uint32_t ms_block; if (argc < 6) { iso_ms_usage(argv); return 1; } if (strcmp(argv[3], argv[5]) == 0) { fprintf(stderr, "image_file and output_file must not be the same file.\n"); return 1; } fd = fopen(argv[5], "w"); if (!fd) { err(1, "error opening output file"); } iso_init(); 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) { printf ("Error creating data source\n"); return 1; } /* create the image context */ result = iso_image_new("volume_id", &image); if (result < 0) { printf ("Error creating image\n"); return 1; } 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"); return 1; } iso_read_opts_set_start_block(ropts, atoi(argv[1])); result = iso_image_import(image, src, ropts, NULL); iso_read_opts_free(ropts); iso_data_source_unref(src); if (result < 0) { printf ("Error importing previous session %d\n", result); return 1; } /* add new dir */ result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[4]); if (result < 0) { printf ("Error adding directory %d\n", result); return 1; } /* generate a multisession image with new contents */ result = iso_write_opts_new(&opts, 1); if (result < 0) { printf("Cant create write opts, error %d\n", result); return 1; } /* 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 ("Cant create image, error %d\n", result); return 1; } iso_write_opts_free(opts); while (burn_src->read_xt(burn_src, buf, 2048) == 2048) { fwrite(buf, 1, 2048, fd); } fclose(fd); burn_src->free_data(burn_src); free(burn_src); iso_image_unref(image); iso_finish(); return 0; } /* ------------------------- 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); }