@ -1,2 +1,3 @@ | |||
Vreixo Formoso | |||
Mario Danic | |||
Thomas Schmitt |
@ -1,4 +0,0 @@ | |||
Joe Neeman | |||
Philippe Rouquier | |||
Suriyan Laohaprapanon | |||
Vreixo Formoso Lopes |
@ -1,13 +1 @@ | |||
Development | |||
=========== | |||
- Support for reading of plain iso images. | |||
- Support for reading RR extensions | |||
Version 0.2.8 | |||
============= | |||
TODO |
@ -1 +1,20 @@ | |||
nothing here now | |||
== unknown == | |||
Libisofs v0.6.4 | |||
=============== | |||
- | |||
== Fri Feb 22 2008 == | |||
Libisofs v0.6.2.1 | |||
================= | |||
- FIX: missing buffer.h in tarball | |||
== Thu Feb 14 2008 == | |||
Libisofs v0.6.2 | |||
================ | |||
- Initial release |
@ -0,0 +1,33 @@ | |||
>>>>>>>>>> RELEASE 0.6.1 (development) >>>>>>>>>>>>>>>>>>>>> | |||
- Review error severities | |||
OK - Prepare API for stability and compatibility check | |||
- Documentation | |||
>>>>>>>>>> RELEASE 0.6.2 (stable) >>>>>>>>>>>>>>>>>>>>>>>>>> | |||
- Intensive testing and bug fixing | |||
>>>>>>>>>> RELEASE 0.6.3 (development) >>>>>>>>>>>>>>>>>>>>> | |||
- Improves to public tree | |||
-> Expose node extended info. Always compile it. | |||
(little memory cost) | |||
-> Review builder / tree / node relation | |||
-> Optimize storage of children in node? | |||
-> Inode object? | |||
- Expose Builder and Streams | |||
- Implement filters: compression, encryption... | |||
- Consider some kind of plugin system for Builders, Filesystems and Filters. | |||
- ECMA-119, Joliet, and ISO-9660:1999 writers can share most of the code. | |||
Create a new writer as a generalization of these. | |||
- Update Java bindings | |||
>>>>>>>>>>> ...... | |||
>>>>>>>>>>> RELEASE 1.0.0 (stable) >>>>>>>>>>>>>>>>>>>>>>>>>> | |||
- UDF | |||
- HFS | |||
@ -1,64 +1,35 @@ | |||
GENERAL | |||
======= | |||
Improve documentation | |||
Build system improvements | |||
Clarify licencing (GPL2 only (!) with exception) | |||
FEATURES | |||
======== | |||
El-Torito | |||
Support for multiple images | |||
HFS/HFS+ | |||
CD reading | |||
[ok] plain iso | |||
[ok] Rock Ridge | |||
[ok] Joliet | |||
Merge RR and Joliet trees | |||
[ok] User options to customize reading | |||
[ok] Read El-Torito info | |||
[ok] Multisession | |||
[ok] DVD+RW image growing | |||
El-Torito images from previous session | |||
Add new el-torito image from prev. session file | |||
Path for isolinux from prev. session | |||
UDF | |||
[ok] ISO relaxed contraints | |||
ISO 9660:1998 | |||
Support for special files (only dirs, reg. files and symlinks are supported). | |||
Modification of timestamps attribs on nodes | |||
TESTS | |||
===== | |||
[several done] | |||
Test all util.h functions, especially date-related ones | |||
Test for RR read functions | |||
For all | |||
IMPLEMENTATION | |||
============== | |||
a way to return NULL sources meaning a failure!! | |||
[ok] Error message queue | |||
Better charset support | |||
[ok] default input charset to locale one, no always UTF-8 | |||
add charset management on image reading | |||
use iso-8859-1 instead of UTF-8 on RR? | |||
[ok] Improve date handling | |||
for DVD+RW, the VD to be written at the beginning of disc must be | |||
returned as 32KB block | |||
Sources to write file contents | |||
encyrption/compression of files | |||
auto cut of files to 2gb limit | |||
BUGS | |||
TODO | |||
==== | |||
Joliet names need ";1" at the end | |||
RR Continuation Areas can't be in Directory Record block | |||
[ok] Fix mangle names when iso relaxed constraints | |||
#00001 (node.h) -> consider adding new timestamps to IsoTreeNode | |||
#00004 (libisofs.h) -> Add a get_mime_type() function. | |||
#00005 (node.c) -> optimize iso_dir_iter_take. | |||
#00006 (libisofs.h) -> define more replace values when adding a node to a dir | |||
#00007 (libisofs.h) -> expose iso_tree_add_new_file | |||
#00008 (data_dource.c) -> guard against partial reads | |||
#00009 (ecma119_tree.c/h) -> add true support for harlinks and inode numbers | |||
#00010 (buffer.c) -> optimize ring buffer | |||
#00011 (ecma119.c) -> guard against bad path table usage with more than 65535 dirs | |||
#00012 (fs_image.c) -> support follow symlinks on imafe filesystem | |||
#00013 (fs_image.c) -> check for unsupported flags when reading a dir record | |||
#00014 (fs_image.c) -> more sanity checks to ensure dir record info is valid | |||
#00015 (fs_image.c) -> take care of CD-ROM XA discs when reading SP entry | |||
#00016 (fs_image.c) -> handle non RR ER entries | |||
#00017 (fs_image.c) -> take advantage of other atts of PVD | |||
#00018 (fs_image.c) -> check if there are more entries in the boot catalog | |||
#00019 (fs_image.c) -> set IsoImage attribs from Joliet SVD? | |||
#00020 (fs_image.c) -> handle RR info in Joliet tree | |||
#00021 (fs_image.c) -> handle RR info in ISO 9660:1999 tree | |||
#00022 (joliet.c) -> support relaxed constraints in joliet filenames | |||
#00024 (libisofs.h) -> option to convert names to lower case for iso reading | |||
#00025 (libisofs.h) -> support for merging old image files | |||
#00026 (libisofs.h) -> add support for "hidden" bootable images. | |||
#00027 (iso1999.h) -> Follow ISO 9660:1999 specs when sorting files | |||
FIXME | |||
===== | |||
@ -0,0 +1,74 @@ | |||
/* | |||
* Copyright (c) 2007 Vreixo Formoso | |||
* | |||
* 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 as | |||
* published by the Free Software Foundation. See COPYING file for details. | |||
*/ | |||
#include "libisofs.h" | |||
#include "fsource.h" | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
/* | |||
* Little test program to test filesystem implementations. | |||
* Outputs file contents to stdout! | |||
*/ | |||
int main(int argc, char **argv) | |||
{ | |||
int res; | |||
IsoFilesystem *fs; | |||
IsoFileSource *file; | |||
struct stat info; | |||
if (argc != 2) { | |||
fprintf(stderr, "Usage: cat /path/to/file\n"); | |||
return 1; | |||
} | |||
/* create filesystem object */ | |||
res = iso_local_filesystem_new(&fs); | |||
if (res < 0) { | |||
fprintf(stderr, "Can't get local fs object, err = %d\n", res); | |||
return 1; | |||
} | |||
res = fs->get_by_path(fs, argv[1], &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); | |||
return 0; | |||
} |
@ -0,0 +1,127 @@ | |||
/* | |||
* Copyright (c) 2007 Vreixo Formoso | |||
* | |||
* 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 as | |||
* published by the Free Software Foundation. See COPYING file for details. | |||
*/ | |||
#include "libisofs.h" | |||
#include "buffer.h" | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <pthread.h> | |||
#include <sys/types.h> | |||
#include <sys/stat.h> | |||
#include <fcntl.h> | |||
#include <unistd.h> | |||
/* | |||
* Little test program that reads a file and outputs it to stdout, using | |||
* the libisofs ring buffer as intermediate memory | |||
*/ | |||
struct th_data | |||
{ | |||
IsoRingBuffer *rbuf; | |||
char *path; | |||
}; | |||
#define WRITE_CHUNK 2048 | |||
#define READ_CHUNK 2048 | |||
static | |||
void *write_function(void *arg) | |||
{ | |||
ssize_t bytes; | |||
int res; | |||
unsigned char tmp[WRITE_CHUNK]; | |||
struct th_data *data = (struct th_data *) arg; | |||
int fd = open(data->path, O_RDONLY); | |||
if (fd < 0) { | |||
fprintf(stderr, "Writer thread error: Can't open file"); | |||
iso_ring_buffer_writer_close(data->rbuf, 1); | |||
pthread_exit(NULL); | |||
} | |||
res = 1; | |||
while ( (bytes = read(fd, tmp, WRITE_CHUNK)) > 0) { | |||
res = iso_ring_buffer_write(data->rbuf, tmp, bytes); | |||
if (res <= 0) { | |||
break; | |||
} | |||
/* To test premature reader exit >>>>>>>>>>> | |||
iso_ring_buffer_writer_close(data->rbuf); | |||
pthread_exit(NULL); | |||
<<<<<<<<<<<<<<<<<<<<<<<<< */ | |||
// if (rand() > 2000000000) { | |||
// fprintf(stderr, "Writer sleeping\n"); | |||
// sleep(1); | |||
// } | |||
} | |||
fprintf(stderr, "Writer finish: %d\n", res); | |||
close(fd); | |||
iso_ring_buffer_writer_close(data->rbuf, 0); | |||
pthread_exit(NULL); | |||
} | |||
static | |||
void *read_function(void *arg) | |||
{ | |||
unsigned char tmp[READ_CHUNK]; | |||
int res = 1; | |||
struct th_data *data = (struct th_data *) arg; | |||
while ( (res = iso_ring_buffer_read(data->rbuf, tmp, READ_CHUNK)) > 0) { | |||
write(1, tmp, READ_CHUNK); | |||
/* To test premature reader exit >>>>>>>>>>> | |||
iso_ring_buffer_reader_close(data->rbuf); | |||
pthread_exit(NULL); | |||
<<<<<<<<<<<<<<<<<<<<<<<<< */ | |||
// if (rand() > 2000000000) { | |||
// fprintf(stderr, "Reader sleeping\n"); | |||
// sleep(1); | |||
// } | |||
} | |||
fprintf(stderr, "Reader finish: %d\n", res); | |||
iso_ring_buffer_reader_close(data->rbuf, 0); | |||
pthread_exit(NULL); | |||
} | |||
int main(int argc, char **argv) | |||
{ | |||
int res; | |||
struct th_data data; | |||
pthread_t reader; | |||
pthread_t writer; | |||
if (argc != 2) { | |||
fprintf(stderr, "Usage: catbuffer /path/to/file\n"); | |||
return 1; | |||
} | |||
res = iso_ring_buffer_new(1024, &data.rbuf); | |||
if (res < 0) { | |||
fprintf(stderr, "Can't create buffer\n"); | |||
return 1; | |||
} | |||
data.path = argv[1]; | |||
res = pthread_create(&writer, NULL, write_function, (void *) &data); | |||
res = pthread_create(&reader, NULL, read_function, (void *) &data); | |||
pthread_join(writer, NULL); | |||
pthread_join(reader, NULL); | |||
fprintf(stderr, "Buffer was %d times full and %d times empty.\n", | |||
iso_ring_buffer_get_times_full(data.rbuf), | |||
iso_ring_buffer_get_times_empty(data.rbuf)); | |||
free(data.rbuf); | |||
return 0; | |||
} |
@ -0,0 +1,136 @@ | |||
/* | |||
* Little program that imports a directory to iso image, generates the | |||
* ecma119 low level tree and prints it. | |||
* Note that this is not an API example, but a little program for test | |||
* purposes. | |||
*/ | |||
#include "libisofs.h" | |||
#include "ecma119.h" | |||
#include "ecma119_tree.h" | |||
#include "util.h" | |||
#include "filesrc.h" | |||
#include "node.h" | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#include <sys/types.h> | |||
#include <sys/stat.h> | |||
#include <unistd.h> | |||
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 | |||
print_dir(Ecma119Node *dir, int level) | |||
{ | |||
int i; | |||
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'; | |||
for (i = 0; i < dir->info.dir->nchildren; i++) { | |||
Ecma119Node *child = dir->info.dir->children[i]; | |||
if (child->type == ECMA119_DIR) { | |||
printf("%s+[D] ", sp); | |||
print_permissions(iso_node_get_permissions(child->node)); | |||
printf(" %s\n", child->iso_name); | |||
print_dir(child, level+1); | |||
} else if (child->type == ECMA119_FILE) { | |||
printf("%s-[F] ", sp); | |||
print_permissions(iso_node_get_permissions(child->node)); | |||
printf(" %s {%p}\n", child->iso_name, (void*)child->info.file); | |||
} else if (child->type == ECMA119_SYMLINK) { | |||
printf("%s-[L] ", sp); | |||
print_permissions(iso_node_get_permissions(child->node)); | |||
printf(" %s -> %s\n", child->iso_name, | |||
((IsoSymlink*)child->node)->dest); | |||
} else if (child->type == ECMA119_SPECIAL) { | |||
printf("%s-[S] ", sp); | |||
print_permissions(iso_node_get_permissions(child->node)); | |||
printf(" %s\n", child->iso_name); | |||
} else if (child->type == ECMA119_PLACEHOLDER) { | |||
printf("%s-[RD] ", sp); | |||
print_permissions(iso_node_get_permissions(child->node)); | |||
printf(" %s\n", child->iso_name); | |||
} else { | |||
printf("%s-[????] ", sp); | |||
} | |||
} | |||
} | |||
int main(int argc, char **argv) | |||
{ | |||
int result; | |||
IsoImage *image; | |||
Ecma119Image *ecma119; | |||
if (argc != 2) { | |||
printf ("You need to specify a valid path\n"); | |||
return 1; | |||
} | |||
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; | |||
} | |||
ecma119 = calloc(1, sizeof(Ecma119Image)); | |||
iso_rbtree_new(iso_file_src_cmp, &(ecma119->files)); | |||
ecma119->iso_level = 1; | |||
ecma119->rockridge = 1; | |||
ecma119->image = image; | |||
ecma119->input_charset = strdup("UTF-8"); | |||
/* create low level tree */ | |||
result = ecma119_tree_create(ecma119); | |||
if (result < 0) { | |||
printf ("Error creating ecma-119 tree: %d\n", result); | |||
return 1; | |||
} | |||
printf("================= ECMA-119 TREE =================\n"); | |||
print_dir(ecma119->root, 0); | |||
printf("\n\n"); | |||
ecma119_node_free(ecma119->root); | |||
iso_rbtree_destroy(ecma119->files, iso_file_src_free); | |||
free(ecma119->input_charset); | |||
free(ecma119); | |||
iso_image_unref(image); | |||
iso_finish(); | |||
return 0; | |||
} |
@ -0,0 +1,176 @@ | |||
/* | |||
* Little program to show how to create an iso image from a local | |||
* directory. | |||
*/ | |||
#include "libisofs.h" | |||
#include "libburn/libburn.h" | |||
#include <stdio.h> | |||
#include <getopt.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#include <sys/types.h> | |||
#include <sys/stat.h> | |||
#include <unistd.h> | |||
#include <fcntl.h> | |||
#include <err.h> | |||
const char * const optstring = "JRIL:b:hV:"; | |||
extern char *optarg; | |||
extern int optind; | |||
void usage(char **argv) | |||
{ | |||
printf("%s [OPTIONS] DIRECTORY OUTPUT\n", argv[0]); | |||
} | |||
void 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 callback(IsoFileSource *src) | |||
{ | |||
char *path = iso_file_source_get_path(src); | |||
printf("CALLBACK: %s\n", path); | |||
free(path); | |||
return 1; | |||
} | |||
int main(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': | |||
usage(argv); | |||
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 '?': | |||
usage(argv); | |||
exit(1); | |||
break; | |||
} | |||
} | |||
if (argc < 2) { | |||
printf ("Please pass directory from which to build ISO\n"); | |||
usage(argv); | |||
return 1; | |||
} | |||
if (argc < 3) { | |||
printf ("Please supply output file\n"); | |||
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; | |||
} |
@ -0,0 +1,95 @@ | |||
/* | |||
* Copyright (c) 2007 Vreixo Formoso | |||
* | |||
* 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 as | |||
* published by the Free Software Foundation. See COPYING file for details. | |||
*/ | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include "libisofs.h" | |||
/* | |||
* Little test program that extracts a file form a given ISO image. | |||
* Outputs file contents to stdout! | |||
*/ | |||
int main(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; | |||
} |
@ -0,0 +1,257 @@ | |||
/* | |||
* Very simple program to show how to grow an iso image. | |||
*/ | |||
#include "libisofs.h" | |||
#include "libburn/libburn.h" | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#include <sys/types.h> | |||
#include <sys/stat.h> | |||
#include <unistd.h> | |||
#include <fcntl.h> | |||
#include <err.h> | |||
static IsoDataSource *libburn_data_source_new(struct burn_drive *d); | |||
void usage(char **argv) | |||
{ | |||
printf("%s DISC DIRECTORY\n", argv[0]); | |||
} | |||
int main(int argc, char **argv) | |||
{ | |||
int result; | |||
IsoImage *image; | |||
IsoDataSource *src; | |||
struct burn_source *burn_src; | |||
struct burn_drive_info *drives; | |||
struct burn_drive *drive; | |||
unsigned char buf[32 * 2048]; | |||
IsoWriteOpts *opts; | |||
int ret = 0; | |||
IsoReadImageFeatures *features; | |||
uint32_t ms_block; | |||
IsoReadOpts *ropts; | |||
if (argc < 3) { | |||
usage(argv); | |||
return 1; | |||
} | |||
iso_init(); | |||
iso_set_msgs_severities("NEVER", "ALL", ""); | |||
/* 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); | |||
if (!burn_initialize()) { | |||
err(1, "Can't init libburn"); | |||
} | |||
burn_msgs_set_severities("NEVER", "SORRY", "libburner : "); | |||
if (burn_drive_scan_and_grab(&drives, argv[1], 0) != 1) { | |||
err(1, "Can't open device. Are you sure it is a valid drive?\n"); | |||
} | |||
drive = drives[0].drive; | |||
#ifdef ISO_GROW_CHECK_MEDIA | |||
{ | |||
/* some check before going on */ | |||
enum burn_disc_status state; | |||
int pno; | |||
char name[80]; | |||
state = burn_disc_get_status(drive); | |||
burn_disc_get_profile(drive, &pno, name); | |||
/* | |||
* my drives report BURN_DISC_BLANK on a DVD+RW with data. | |||
* is that correct? | |||
*/ | |||
if ( (pno != 0x1a) /*|| (state != BURN_DISC_FULL)*/ ) { | |||
printf("You need to insert a DVD+RW with some data.\n"); | |||
printf("Profile: %x, state: %d.\n", pno, state); | |||
ret = 1; | |||
goto exit_cleanup; | |||
} | |||
} | |||
#endif | |||
/* create the data source to accesss previous image */ | |||
src = libburn_data_source_new(drive); | |||
if (src == NULL) { | |||
printf("Can't create data source.\n"); | |||
ret = 1; | |||
goto exit_cleanup; | |||
} | |||
/* import previous image */ | |||
ret = iso_read_opts_new(&ropts, 0); | |||
if (ret < 0) { | |||
fprintf(stderr, "Error creating read options\n"); | |||
return 1; | |||
} | |||
result = iso_image_import(image, src, ropts, &features); | |||
iso_data_source_unref(src); | |||
if (result < 0) { | |||
printf ("Error importing previous session %d\n", result); | |||
return 1; | |||
} | |||
iso_read_opts_free(ropts); | |||
iso_tree_set_replace_mode(image, ISO_REPLACE_IF_NEWER); | |||
/* 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 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 = ((iso_read_image_features_get_size(features) + 15) / 16 ) * 16; | |||
iso_write_opts_set_ms_block(opts, ms_block); | |||
iso_write_opts_set_appendable(opts, 1); | |||
iso_write_opts_set_overwrite_buf(opts, buf); | |||
iso_read_image_features_destroy(features); | |||
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); | |||
/* a. write the new image */ | |||
printf("Adding new data...\n"); | |||
{ | |||
struct burn_disc *target_disc; | |||
struct burn_session *session; | |||
struct burn_write_opts *burn_options; | |||
struct burn_track *track; | |||
struct burn_progress progress; | |||
char reasons[BURN_REASONS_LEN]; | |||
target_disc = burn_disc_create(); | |||
session = burn_session_create(); | |||
burn_disc_add_session(target_disc, session, BURN_POS_END); | |||
track = burn_track_create(); | |||
burn_track_set_source(track, burn_src); | |||
burn_session_add_track(session, track, BURN_POS_END); | |||
burn_options = burn_write_opts_new(drive); | |||
burn_drive_set_speed(drive, 0, 0); | |||
burn_write_opts_set_underrun_proof(burn_options, 1); | |||
/* mmm, check for 32K alignment? */ | |||
burn_write_opts_set_start_byte(burn_options, ms_block * 2048); | |||
if (burn_write_opts_auto_write_type(burn_options, target_disc, | |||
reasons, 0) == BURN_WRITE_NONE) { | |||
printf("Failed to find a suitable write mode:\n%s\n", reasons); | |||
ret = 1; | |||
goto exit_cleanup; | |||
} | |||
/* ok, write the new track */ | |||
burn_disc_write(burn_options, target_disc); | |||
burn_write_opts_free(burn_options); | |||
while (burn_drive_get_status(drive, NULL) == BURN_DRIVE_SPAWNING) | |||
usleep(1002); | |||
while (burn_drive_get_status(drive, &progress) != BURN_DRIVE_IDLE) { | |||
printf("Writing: sector %d of %d\n", progress.sector, progress.sectors); | |||
sleep(1); | |||
} | |||
} | |||
/* b. write the new vol desc */ | |||
printf("Writing the new vol desc...\n"); | |||
ret = burn_random_access_write(drive, 0, (char*)buf, 32*2048, 0); | |||
if (ret != 1) { | |||
printf("Ups, new vol desc write failed\n"); | |||
} | |||
iso_image_unref(image); | |||
exit_cleanup:; | |||
burn_drive_release(drives[0].drive, 0); | |||
burn_finish(); | |||
iso_finish(); | |||
exit(ret); | |||
} | |||
static int | |||
libburn_ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer) | |||
{ | |||
struct burn_drive *d; | |||
off_t data_count; | |||
d = (struct burn_drive*)src->data; | |||
if ( burn_read_data(d, (off_t) lba * (off_t) 2048, (char*)buffer, | |||
2048, &data_count, 0) < 0 ) { | |||
return -1; /* error */ | |||
} | |||
return 1; | |||
} | |||
static | |||
int libburn_ds_open(IsoDataSource *src) | |||
{ | |||
/* nothing to do, device is always opened */ | |||
return 1; | |||
} | |||
static | |||
int libburn_ds_close(IsoDataSource *src) | |||
{ | |||
/* nothing to do, device is always opened */ | |||
return 1; | |||
} | |||
static void | |||
libburn_ds_free_data(IsoDataSource *src) | |||
{ | |||
/* nothing to do */ | |||
} | |||
static IsoDataSource * | |||
libburn_data_source_new(struct burn_drive *d) | |||
{ | |||
IsoDataSource *ret; | |||
ret = malloc(sizeof(IsoDataSource)); | |||
ret->version = 0; | |||
ret->refcount = 1; | |||
ret->read_block = libburn_ds_read_block; | |||
ret->open = libburn_ds_open; | |||
ret->close = libburn_ds_close; | |||
ret->free_data = libburn_ds_free_data; | |||
ret->data = d; | |||
return ret; | |||
} |
@ -0,0 +1,109 @@ | |||
/* | |||
* Little program to show how to modify an iso image. | |||
*/ | |||
#include "libisofs.h" | |||
#include "libburn/libburn.h" | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#include <sys/types.h> | |||
#include <sys/stat.h> | |||
#include <unistd.h> | |||
#include <fcntl.h> | |||
#include <err.h> | |||
void usage(char **argv) | |||
{ | |||
printf("%s [OPTIONS] IMAGE DIRECTORY OUTPUT\n", argv[0]); | |||
} | |||
int main(int argc, char **argv) | |||
{ | |||
int result; | |||