From 6ba4b25045c516aa88d794aabf2a2ca84fa9ce0c Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Sat, 24 May 2008 09:25:26 +0000 Subject: [PATCH] Enabled osirrox of more file types, curbed with device files --- xorriso/xorriso.1 | 23 ++++- xorriso/xorriso.c | 43 +++++---- xorriso/xorriso_private.h | 2 +- xorriso/xorriso_timestamp.h | 2 +- xorriso/xorrisoburn.c | 185 ++++++++++++++++++++++++++++++------ 5 files changed, 205 insertions(+), 50 deletions(-) diff --git a/xorriso/xorriso.1 b/xorriso/xorriso.1 index faf155de..4ff8ddf3 100644 --- a/xorriso/xorriso.1 +++ b/xorriso/xorriso.1 @@ -1596,18 +1596,31 @@ pseudo-drives or as log files. But its alter ego, osirrox, is able to extract file objects from ISO images and to create, overwrite, or delete file objects on disk. .TP -\fB\-osirrox\fR "on"|"off" +\fB\-osirrox\fR "on"|"device_files"|"off" Setting "off" disables disk filesystem manipulations. This is the default unless the program was started with leafname "osirrox". Elsewise the capability to restore files can be enabled explicitly by -osirrox "on". +.br +To enable restoring of special files by "device_files" is potentially +dangerous. +The meaning of the number st_rdev (see man 2 stat) depends much on the +operating system. Best is to restore device files only to the same system +from where they were copied. If not enabled, device files in the ISO image +are ignored during restore operations. +.br +Due to a bug of previous versions, device files from previous sessions might +have been altered to major=0, minor=1. So this combination does not get +restored. .TP \fB\-cpx\fR iso_rr_path [***] disk_path -Extract regular files from the ISO image and store them under the address given -by disk_path. If more then one iso_rr_path is given then disk_path must be -a directory or non-existent. In the latter case it gets created and the -extracted files get installed in it with the same leafnames. +Extract single leaf file objects from the ISO image and store them under +the address given by disk_path. If more then one iso_rr_path is given then +disk_path must be a directory or non-existent. In the latter case it gets +created. The extracted files get installed in it with the same leafnames. .br Missing directory components in disk_path will get created, if possible. +Disk file exclusions are in effect. If this is undesired then perform +-not_mgt "off" first. .TP .B Command compatibility emulations: .PP diff --git a/xorriso/xorriso.c b/xorriso/xorriso.c index f298482b..cbd71340 100644 --- a/xorriso/xorriso.c +++ b/xorriso/xorriso.c @@ -3823,8 +3823,10 @@ int Xorriso_status(struct XorrisO *xorriso, char *filter, FILE *fp, int flag) Xorriso_status_result(xorriso,filter,fp,flag&2); } - is_default= !(xorriso->allow_restore); - sprintf(line,"-osirrox %s\n", xorriso->allow_restore ? "on" : "off"); + is_default= (xorriso->allow_restore==0); + sprintf(line,"-osirrox %s\n", + xorriso->allow_restore ? xorriso->allow_restore==2 ? "device_files" : "on" + : "off"); if(!(is_default && no_defaults)) Xorriso_status_result(xorriso,filter,fp,flag&2); @@ -5996,7 +5998,8 @@ int Xorriso__mode_to_perms(mode_t st_mode, char perms[10], int flag) int Xorriso_format_ls_l(struct XorrisO *xorriso, struct stat *stbuf, int flag) { - char *rpt, perms[10]; + int show_major_minor= 0; + char *rpt, perms[10], mm_text[80]; mode_t st_mode; rpt= xorriso->result_line; @@ -6009,11 +6012,13 @@ int Xorriso_format_ls_l(struct XorrisO *xorriso, struct stat *stbuf, int flag) strcat(rpt, "-"); else if(S_ISLNK(st_mode)) strcat(rpt, "l"); - else if(S_ISBLK(st_mode)) + else if(S_ISBLK(st_mode)) { strcat(rpt, "b"); - else if(S_ISCHR(st_mode)) + show_major_minor= 1; + } else if(S_ISCHR(st_mode)) { strcat(rpt, "c"); - else if(S_ISFIFO(st_mode)) + show_major_minor= 1; + } else if(S_ISFIFO(st_mode)) strcat(rpt, "p"); else if(S_ISSOCK(st_mode)) strcat(rpt, "s"); @@ -6027,7 +6032,12 @@ int Xorriso_format_ls_l(struct XorrisO *xorriso, struct stat *stbuf, int flag) sprintf(rpt+strlen(rpt), "%-8lu ", (unsigned long) stbuf->st_uid); sprintf(rpt+strlen(rpt), "%-8lu ", (unsigned long) stbuf->st_gid); - sprintf(rpt+strlen(rpt), "%8.f ", (double) stbuf->st_size); + if(show_major_minor) { + sprintf(mm_text, "%d,%d", (int) ((stbuf->st_rdev>>8)&0xfff), + (int) (((stbuf->st_rdev&~0xfffff)>>12) | (stbuf->st_rdev&0xff))); + sprintf(rpt+strlen(rpt), "%8s ", mm_text); + } else + sprintf(rpt+strlen(rpt), "%8.f ", (double) stbuf->st_size); Ftimetxt(stbuf->st_mtime, rpt+strlen(rpt), 0); strcat(rpt, " "); @@ -7975,7 +7985,7 @@ int Xorriso_option_blank(struct XorrisO *xorriso, char *mode, int flag) if(ret<=0) return(2); - if(strcmp(mode, "as_needed")==0) + if(strcmp(mode, "as_needed")==0 || mode[0]==0) as_needed= 1; else if(strcmp(mode, "all")==0 || strcmp(mode, "full")==0) mode_flag= 0; @@ -8008,9 +8018,7 @@ unusable_index:; if(idx<0 || idx>255) goto unusable_index; mode_flag|= (idx<<8); - } else if(mode[0]==0) - mode_flag= !(flag&1); - else { + } else { sprintf(xorriso->info_text, "%s: Unknown %s mode '%s'", cmd, ((flag&1) ? "-format" : "-blank"), mode); @@ -8658,7 +8666,7 @@ int Xorriso_option_cpx(struct XorrisO *xorriso, int argc, char **argv, if(ret==3 || (flag&1)) continue; sprintf(xorriso->info_text, - "Copied from ISO image to disk: %s '%s'='%s'\n", + "Copied from ISO image to disk: %s '%s' = '%s'\n", (ret>1 ? "directory" : "file"), eff_origin, eff_dest); Xorriso_info(xorriso, 0); continue; /* regular bottom of loop */ @@ -8669,8 +8677,9 @@ problem_handler:; continue; goto ex; } - Xorriso_pacifier_callback(xorriso, "files copied", xorriso->pacifier_count, - xorriso->pacifier_total, "", 1); + if(xorriso->pacifier_count>0) + Xorriso_pacifier_callback(xorriso, "files copied", xorriso->pacifier_count, + xorriso->pacifier_total, "", 1); ret= !was_failure; ex:; Xorriso_opt_args(xorriso, "-cpx", @@ -9589,12 +9598,12 @@ int Xorriso_option_help(struct XorrisO *xorriso, int flag) " Like -compare but affecting all files below directories.", "", "Restore options (copying file objects from ISO image to disk filesystem):", -" -osirrox \"on\"|\"off\"", +" -osirrox \"on\"|\"device_files\"|\"off\"", " By default \"off\" the inverse operation of xorriso from ISO", " image to disk filesystem is disabled. \"on\" allows xorriso", " to create, overwrite, delete files in the disk filesystem.", " -cpx iso_rr_path [***] disk_path", -" Copy regular files from ISO image to disk filesystem.", +" Copy leaf file objects from ISO image to disk filesystem.", "", "Compatibility emulation (argument list may be ended by --):", " -as mkisofs [-help|-o|-R|-J|-V|-P|-f|-graft-points|-path-list|pathspecs]", @@ -10473,6 +10482,8 @@ int Xorriso_option_osirrox(struct XorrisO *xorriso, char *mode, int flag) { if(strcmp(mode, "off")==0) xorriso->allow_restore= 0; + else if(strcmp(mode, "device_files")==0) + xorriso->allow_restore= 2; else if(strcmp(mode, "on")==0 || mode[0]==0) xorriso->allow_restore= 1; else { diff --git a/xorriso/xorriso_private.h b/xorriso/xorriso_private.h index 267c4f7e..46c1af45 100644 --- a/xorriso/xorriso_private.h +++ b/xorriso/xorriso_private.h @@ -158,7 +158,7 @@ struct XorrisO { /* the global context of xorriso */ /* XORRISO options */ int allow_graft_points; - int allow_restore; + int allow_restore; /* 0= disallowed, 1=allowed, 2=device files allowed */ int dialog; diff --git a/xorriso/xorriso_timestamp.h b/xorriso/xorriso_timestamp.h index a24cf544..969ed268 100644 --- a/xorriso/xorriso_timestamp.h +++ b/xorriso/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2008.05.22.210835" +#define Xorriso_timestamP "2008.05.24.092546" diff --git a/xorriso/xorrisoburn.c b/xorriso/xorrisoburn.c index cb5e1a30..647153d3 100644 --- a/xorriso/xorrisoburn.c +++ b/xorriso/xorrisoburn.c @@ -1474,6 +1474,87 @@ int Xorriso_get_node_by_path(struct XorrisO *xorriso, } +/* <<< this is not safe +#define Xorriso_can_get_dev_T 1 +#define Xorriso_get_dev_by_botcH 1 +*/ + + +#ifndef Xorriso_can_get_dev_T +#ifdef Xorriso_standalonE +/* this is safe */ +#define Xorriso_can_get_dev_T 1 +#define Xorriso_get_dev_by_botcH 1 +#endif /* Xorriso_standalonE */ +#endif /* Xorriso_can_get_dev_T */ + + +/* @param flag bit0= do not complain about being unable to retrieve info +*/ +int Xorriso_node_get_dev(struct XorrisO *xorriso, IsoNode *node, + char *path, dev_t *dev, int flag) +{ + +#ifdef Xorriso_can_get_dev_T + +/* >>> insert future API call here and remove botch below */ + +/* <<< */ +#ifdef Xorriso_get_dev_by_botcH +/* Drilling a hole into libisofs-0.6.4 in order to substitute for the lack + of an API call which returns the dev_t number of a IsoSpecial (block or + character device). +*/ + +/* These are clones from libisofs/node.h */ + +typedef struct iso_extended_info IsoExtendedInfo_0_6_4_xorrisO; + +struct Iso_Node_0_6_4_xorrisO +{ + int refcount; + enum IsoNodeType type; + char *name; + mode_t mode; + uid_t uid; + gid_t gid; + time_t atime; + time_t mtime; + time_t ctime; + + int hidden; + IsoDir *parent; + IsoNode *next; + IsoExtendedInfo_0_6_4_xorrisO *xinfo; +}; + +struct Iso_Special_0_6_4_xorrisO +{ + struct Iso_Node_0_6_4_xorrisO node; + dev_t dev; +}; + + *dev= ((struct Iso_Special_0_6_4_xorrisO *) node)->dev; + return(1); + +#endif /* Xorriso_get_dev_by_botcH */ + +#else /* Xorriso_can_get_dev_T */ + + char sfe[SfileadrL]; + + if(flag&1) + return(0); + sprintf(xorriso->info_text, + "Cannot obtain device major,minor from ISO image file %s", + Text_shellsafe(path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + return(0); + +#endif /* ! Xorriso_can_get_dev_T */ +} + + /* @param flag bit0= *node is already valid bit1= add extra block for size estimation */ @@ -1505,11 +1586,13 @@ int Xorriso_fake_stbuf(struct XorrisO *xorriso, char *path, struct stat *stbuf, stbuf->st_mode|= S_IFREG; else if(LIBISO_ISLNK(*node)) stbuf->st_mode|= S_IFLNK; - else if(LIBISO_ISCHR(*node)) + else if(LIBISO_ISCHR(*node)) { stbuf->st_mode|= S_IFCHR; - else if(LIBISO_ISBLK(*node)) + Xorriso_node_get_dev(xorriso, *node, path, &(stbuf->st_rdev), 1); + } else if(LIBISO_ISBLK(*node)) { stbuf->st_mode|= S_IFBLK; - else if(LIBISO_ISFIFO(*node)) + Xorriso_node_get_dev(xorriso, *node, path, &(stbuf->st_rdev), 1); + } else if(LIBISO_ISFIFO(*node)) stbuf->st_mode|= S_IFIFO; else if(LIBISO_ISSOCK(*node)) stbuf->st_mode|= S_IFSOCK; @@ -1524,8 +1607,6 @@ int Xorriso_fake_stbuf(struct XorrisO *xorriso, char *path, struct stat *stbuf, stbuf->st_uid= iso_node_get_uid(*node); stbuf->st_gid= iso_node_get_gid(*node); - /* >>> stbuf->st_rdev */ - if(LIBISO_ISREG(*node)) stbuf->st_size= iso_file_get_size((IsoFile *) *node)+ (2048 * !!(flag&2)); else @@ -2439,16 +2520,22 @@ int Xorriso_restore_implict_properties(struct XorrisO *xorriso, IsoDir *dir, #endif /* Osirrox_not_yeT */ -/* @param flag bit0= minimal transfer: access permissions only - @return <0 severe error , 0 failure , 1 success +/* @param flag bit0= Minimal transfer: access permissions only + bit2= This is not a parameter. Do not report if ignored + @return <0 severe error , 0 failure , 1 success , + 2 regularly not installed (disallowed device, UNIX domain socket) */ int Xorriso_tree_restore_node(struct XorrisO *xorriso, IsoNode *node, char *img_path, char *disk_path, int flag) { int ret= 0, write_fd= -1, wanted, wret; - char *what= "[unknown filetype]", sfe[5*SfileadrL], buf[32*1024]; + char *what= "[unknown filetype]", sfe[5*SfileadrL], sfe2[5*SfileadrL]; + char buf[32*1024]; + char *link_target; off_t todo, size; - void *stream2= NULL; + void *data_stream= NULL; + mode_t mode; + dev_t dev= 0; if(LIBISO_ISDIR(node)) { what= "directory"; @@ -2456,8 +2543,10 @@ int Xorriso_tree_restore_node(struct XorrisO *xorriso, IsoNode *node, } else if(LIBISO_ISREG(node)) { what= "regular file"; + /* >>> need to exploit node rather than img_path */ - ret= Xorriso_iso_file_open(xorriso, img_path, &stream2, 0); + ret= Xorriso_iso_file_open(xorriso, img_path, &data_stream, 0); + if(ret<=0) goto ex; write_fd= open(disk_path,O_WRONLY|O_EXCL|O_CREAT); @@ -2468,7 +2557,7 @@ int Xorriso_tree_restore_node(struct XorrisO *xorriso, IsoNode *node, wanted= sizeof(buf); if(wanted>todo) wanted= todo; - ret= Xorriso_iso_file_read(xorriso, stream2, buf, wanted, 0); + ret= Xorriso_iso_file_read(xorriso, data_stream, buf, wanted, 0); if(ret<=0) break; wret= write(write_fd, buf, ret); @@ -2484,40 +2573,77 @@ int Xorriso_tree_restore_node(struct XorrisO *xorriso, IsoNode *node, } close(write_fd); write_fd= -1; - Xorriso_iso_file_close(xorriso, &stream2, 0); - stream2= NULL; + Xorriso_iso_file_close(xorriso, &data_stream, 0); + data_stream= NULL; ret= (todo==0); } else if(LIBISO_ISLNK(node)) { what= "symbolic link"; - - goto not_this_type; - /* >>> restore symbolic link */; + link_target= (char *) iso_symlink_get_dest((IsoSymlink *) node); + ret= symlink(link_target, disk_path); } else if(LIBISO_ISCHR(node)) { what= "character device"; + if(xorriso->allow_restore!=2) { +ignored:; + if(!(flag&4)) { + sprintf(xorriso->info_text, "Ignored file type: %s %s = %s", what, + Text_shellsafe(img_path,sfe,0), Text_shellsafe(disk_path,sfe2,0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); + } + {ret= 2; goto ex;} + } +#ifdef Xorriso_can_get_dev_T + mode= S_IFCHR | 0777; + ret= Xorriso_node_get_dev(xorriso, node, img_path, &dev, 0); + if(ret<=0) + goto ex; + if(dev == (dev_t) 1) { +probably_damaged:; + sprintf(xorriso->info_text, + "Most probably damaged device file not restored: mknod %s %s 0 1", + Text_shellsafe(disk_path, sfe, 0), LIBISO_ISCHR(node) ? "c" : "b"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + ret= 0; goto ex; + } + ret= mknod(disk_path, mode, dev); +#else goto not_this_type; - /* >>> restore character device */; +#endif } else if(LIBISO_ISBLK(node)) { what= "block device"; + if(xorriso->allow_restore!=2) + goto ignored; +#ifdef Xorriso_can_get_dev_T + mode= S_IFBLK | 0777; + ret= Xorriso_node_get_dev(xorriso, node, img_path, &dev, 0); + if(ret<=0) + goto ex; + if(dev == (dev_t) 1) + goto probably_damaged; + ret= mknod(disk_path, mode, dev); +#else goto not_this_type; - /* >>> restore block device */; +#endif } else if(LIBISO_ISFIFO(node)) { what= "named pipe"; - - goto not_this_type; - /* >>> restore fifo */; + mode= S_IFIFO | 0777; + ret= mknod(disk_path, mode, dev); } else if(LIBISO_ISSOCK(node)) { - what= ""; - /* restoring a socket file makes no sense */; + what= "unix socket"; + /* Restoring a socket file is not possible. One rather needs to restart + the service which temporarily created the socket. */ + goto ignored; } else { +#ifndef Xorriso_can_get_dev_T not_this_type:; +#endif sprintf(xorriso->info_text, "Cannot restore file type '%s'", what); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); ret= 0; goto ex; @@ -2530,11 +2656,15 @@ cannot_restore:; Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); ret= 0; goto ex; } - ret= Xorriso_restore_properties(xorriso, disk_path, node, flag&1); + if(LIBISO_ISLNK(node)) + ret= 1; + else + ret= Xorriso_restore_properties(xorriso, disk_path, node, flag&1); ex:; if(write_fd>0) close(write_fd); - Xorriso_iso_file_close(xorriso, &stream2, 0); + if(data_stream!=NULL) + Xorriso_iso_file_close(xorriso, &data_stream, 0); return(ret); } @@ -2718,14 +2848,15 @@ attach_source:; img_path_pt= img_path; ret= Xorriso_tree_restore_node(xorriso, node, img_path_pt, path, - !!(flag&64)); + (flag&4) | !!(flag&64)); if(ret<=0) { sprintf(xorriso->info_text, "Restoring failed: %s = %s", Text_shellsafe(img_path,sfe,0), Text_shellsafe(disk_path,sfe2,0)); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); return(0); } - + if(ret==2) + return(3); xorriso->pacifier_count++; if(xorriso->pacifier_count%100 && !(flag&2)) Xorriso_pacifier_callback(xorriso, "files restored",