libisofs/demo/demo.c
Thomas Schmitt ba11413a6f Corrected several memory leaks and potential NULL pointer evaluations
in case of memory shortage. All reported by George Danchev.
2010-09-01 10:45:10 +02:00

868 lines
22 KiB
C

/*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <getopt.h>
#include <fcntl.h>
#include <err.h>
#include <limits.h>
#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;
sp = calloc(1, 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);
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 <num> 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 ("Cant 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 ("Cant create image, error %d\n", result);
goto ex;
}
iso_write_opts_free(opts);
while (burn_src->read_xt(burn_src, buf, 2048) == 2048) {
fwrite(buf, 1, 2048, fp);
}
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] = ' ';
}
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;
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 *fp = NULL;
IsoWriteOpts *opts;
IsoReadOpts *ropts;
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;
}
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");
goto ex;
}
/* create the image context */
result = iso_image_new("volume_id", &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);
/* import previous image */
result = iso_read_opts_new(&ropts, 0);
if (result < 0) {
fprintf(stderr, "Error creating read options\n");
goto ex;
}
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);
goto ex;
}
/* 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);
goto ex;
}
/* 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);
goto ex;
}
/* 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);
goto ex;
}
iso_write_opts_free(opts);
while (burn_src->read_xt(burn_src, buf, 2048) == 2048) {
fwrite(buf, 1, 2048, fp);
}
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_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 *fp = NULL;
IsoWriteOpts *opts;
IsoReadOpts *ropts;
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;
}
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");
goto ex;
}
/* create the image context */
result = iso_image_new("volume_id", &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);
/* 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);
iso_data_source_unref(src);
if (result < 0) {
printf ("Error importing previous session %d\n", result);
goto ex;
}
/* 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);
goto ex;
}
/* 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);
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 ("Cant create image, error %d\n", result);
goto ex;
}
iso_write_opts_free(opts);
while (burn_src->read_xt(burn_src, buf, 2048) == 2048) {
fwrite(buf, 1, 2048, fp);
}
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;
}
/* ------------------------- 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);
}