From f5b81c7b97e083bdc0dae89f1637f8b9d14edd96 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Sun, 7 Dec 2008 12:25:07 +0000 Subject: [PATCH] Got rid of call system() in Xorriso_mount(), new option -session_string --- xorriso/xorriso.1 | 52 ++++++---- xorriso/xorriso.c | 196 ++++++++++++++++++++++++++++++------ xorriso/xorriso_private.h | 6 ++ xorriso/xorriso_timestamp.h | 2 +- xorriso/xorrisoburn.c | 56 ++++++++--- 5 files changed, 245 insertions(+), 67 deletions(-) diff --git a/xorriso/xorriso.1 b/xorriso/xorriso.1 index a3afec61..3f6ae665 100644 --- a/xorriso/xorriso.1 +++ b/xorriso/xorriso.1 @@ -2,7 +2,7 @@ .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) -.TH XORRISO 1 "Dec 05, 2008" +.TH XORRISO 1 "Dec 07, 2008" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: @@ -59,6 +59,8 @@ Can perform multi-session tasks as emulation of mkisofs and cdrecord. .br Can restore files from ISO image to disk filesystem (see osirrox). .br +Can issue commands to mount older sessions on Linux or FreeBSD. +.br Can check media for damages and copy readable blocks to disk. .br Scans for optical drives, blanks re-useable optical media. @@ -1792,25 +1794,32 @@ to be the most recent real session then. Some read-only drives and media show no usable session history at all. Eventually option -rom_toc_scan might help. .TP -\fB\-mount_cmd\fR drive entity id command_form +\fB\-mount_cmd\fR drive entity id path Print to the result channel an appropriate command line for mounting the -ISO session which is depicted by drive, entity and id. The id can be a block -address with entity "sbsector", a track number with "track", a session number -with "session", a volume id search pattern with "volid", or any text with -"auto". See also option -load. +ISO session which is depicted by drive, entity and id. See option -mount +for direct execution of this command. .br drive can be "indev", "outdev" or the address of a not yet aquired drive. -Prefix "stdio:" for non MMC drives is not mandatory. +Prefix "stdio:" for non-MMC drives is not mandatory. .br -command_form is either "linux:"path , or "freebsd:"path, or "shell:"command, -or a path. -The path will be used as moint point and has already to exist as directory. -A command line with suitable options is then generated. -If no recognizable prefix is given then xorriso guesses on which kind of -system it runs and uses the whole command_form as path. +The id can be a block address with entity "sbsector", a track number with +"track", a session number with "session", a volume id search pattern with +"volid", or a dummy text with "auto". See also option -load. .br -If shell:command is given, then xorriso will substitute in the command text -the following parameter names: +path will be used as mount point and has already to exist as directory. +.br +xorriso determines on which kind of system it runs. Supported are Linux and +FreeBSD. +.TP +\fB\-session_string\fR drive entity id format +Print to the result channel a text which gets composed according to +format and the parameters of the addressed session. +.br +Formats "linux:"path or "freebsd:"path produce the output of -mount_cmd +for the given operating systems. +.br +In other texts xorriso will substitute the following parameter names. +An optional prefix "string:" will be removed. .br "%device%" will be substituted by the mountable device path of the drive address. @@ -2197,13 +2206,12 @@ Read the content of a ISO data file and write it into a data file on disk beginning at the byte_offset. Write at most byte_count bytes. This is the inverse of option -cut_out. .TP -\fB\-mount\fR drive entity id command_form -Produce the same line as -mount_cmd and then execute it as shell command +\fB\-mount\fR drive entity id path +Produce the same line as -mount_cmd and then execute it as external program run after giving up the depicted drive. This demands -osirrox to be enabled and normally will succeed only for the -superuser. For safety reasons it will refuse to execute the command line -if it stems from command_form shell:command or if setuid or setgid are in -effect. In these cases -mount will default to -mount_cmd and a SORRY event. +superuser. For safety reasons the mount program is only executed if it is +reachable as /bin/mount or /sbin/mount. .TP .B Command compatibility emulations: .PP @@ -2853,7 +2861,9 @@ the newly written session (here for mount point /mnt): -mount_cmd "indev" "auto" "auto" /mnt .br Options -mount_cmd and -mount are also able to produce the mount commands for -older sessions in the table-of-content. +older sessions in the table-of-content. E.g. as superuser: +.br + \fB$\fR osirrox -mount /dev/sr0 "volid" '*2008_12_05*' /mnt .br Sessions on multi-session media are separated by several MB of unused blocks. So with small sessions the payload capacity can become substantially lower diff --git a/xorriso/xorriso.c b/xorriso/xorriso.c index 0bdb6437..27b7422c 100644 --- a/xorriso/xorriso.c +++ b/xorriso/xorriso.c @@ -723,12 +723,12 @@ int Sfile_make_argv(char *progname, char *line, int *argc, char ***argv, bit2= abort with return(0) if incomplete quotes are found bit3= eventually prepend missing '-' to first argument read from line bit4= like bit2 but only check quote completeness, do not allocate memory ->>> bit5+6= interpretation of backslashes: 0= no interpretation, leave unchanged 1= only inside double quotes 2= outside single quotes 3= everywhere + bit7= append a NULL element to argv */ { int i,pass,maxl=0,l,argzaehl=0,bufl,line_start_argc, bsl_mode, ret= 0, eaten; @@ -848,8 +848,9 @@ int Sfile_make_argv(char *progname, char *line, int *argc, char ***argv, if(flag & 16) {ret= 1; goto ex;} *argc= argzaehl; - if(argzaehl>0) { - *argv= (char **) Smem_malloC(argzaehl*sizeof(char *)); + if(argzaehl>0 || (flag & 128)) { + *argv= (char **) Smem_malloC((argzaehl + !!(flag & 128)) + * sizeof(char *)); if(*argv==NULL) {ret= -1; goto ex;} } @@ -858,6 +859,8 @@ int Sfile_make_argv(char *progname, char *line, int *argc, char ***argv, if((*argv)[i]==NULL) {ret= -1; goto ex;} } + if(flag & 128) + (*argv)[*argc]= NULL; } } ret= 1; @@ -10338,7 +10341,11 @@ int Xorriso_open_job_data_to(struct XorrisO *xorriso, return(1); } - +/* + @param flag bit0= make absolute command paths with known systems + bit1= do not allow prefixes with cmd + bit2= interpret unprefixed cmd as shell: +*/ int Xorriso_make_mount_cmd(struct XorrisO *xorriso, char *cmd, int lba, int track, int session, char *volid, char *devadr, char result[SfileadrL], int flag) @@ -10352,22 +10359,24 @@ int Xorriso_make_mount_cmd(struct XorrisO *xorriso, char *cmd, /* too_long:; */ - /* >>> complain about argument too long */; - + Xorriso_msgs_submit(xorriso, 0, "Argument much too long", 0, "FAILURE", 0); return(0); } ret= stat(devadr, &stbuf); if(ret != -1) if(S_ISREG(stbuf.st_mode)) reg_file= 1; - if(strncmp(cmd, "linux:", 6) == 0) { + if(strncmp(cmd, "linux:", 6) == 0 && !(flag & 2)) { cpt= cmd + 6; sys_code= 1; - } else if(strncmp(cmd, "freebsd:", 8) == 0) { + } else if(strncmp(cmd, "freebsd:", 8) == 0 && !(flag & 2)) { cpt= cmd + 8; sys_code= 2; - } else if(strncmp(cmd, "shell:", 6) == 0) { - cpt= cmd + 6; + } else if(strncmp(cmd, "string:", 7) == 0 && !(flag & 2)) { + cpt= cmd + 7; + strcpy(form, cpt); + } else if(flag & 4) { + cpt= cmd; strcpy(form, cpt); } else { cpt= cmd; @@ -10391,22 +10400,23 @@ too_long:; if(sys_code == 1) { /* Linux */ sprintf(form, - "mount -t iso9660 -o %snodev,noexec,nosuid,ro,sbsector=%%sbsector%% %%device%% %s", - (reg_file ? "loop," : ""), Text_shellsafe(cpt, sfe, 0)); + "%smount -t iso9660 -o %snodev,noexec,nosuid,ro,sbsector=%%sbsector%% %%device%% %s", + (flag & 1 ? "/bin/" : ""), (reg_file ? "loop," : ""), + Text_shellsafe(cpt, sfe, 0)); is_safe= 1; } else if(sys_code == 2) { /* FreeBSD */ - /* eventually create vnode as of J.R. Oldroyd , 20 Nov 2008: - # mdconfig -a -t vnode -f xfburn.iso - /dev/md0 - (Real CD drives look like /dev/cd0) - */ if(reg_file) { -/* <<< + +/* <<< Considered to create vnode as of + J.R. Oldroyd , 20 Nov 2008 + but for now refraining from creating that persistent file object + strcpy(form, "n=$(mdconfig -a -t vnode -f %device%)"); sprintf(form + strlen(form), " && mount -t cd9660 -o noexec,nosuid -s %%sbsector%% /dev/\"$n\" %s", Text_shellsafe(cmd+8, sfe, 0)); */ + Xorriso_msgs_submit(xorriso, 0, "Detected regular file as mount device with FreeBSD style command.", 0, "FAILURE", 0); @@ -10416,8 +10426,8 @@ too_long:; return(0); } else sprintf(form, - "mount -t cd9660 -o noexec,nosuid -s %%sbsector%% %%device%% %s", - Text_shellsafe(cmd+8, sfe, 0)); + "%smount -t cd9660 -o noexec,nosuid -s %%sbsector%% %%device%% %s", + (flag & 1 ? "/sbin/" : ""), Text_shellsafe(cmd+8, sfe, 0)); is_safe= 1; } sprintf(session_text, "%d", session); @@ -10486,6 +10496,111 @@ int Xorriso_decode_load_adr(struct XorrisO *xorriso, char *cmd, } +/* + @param flag bit0= use env_path to find the desired program +return: + <=0 : error + 1 : done +*/ +int Xorriso_execv(struct XorrisO *xorriso, char *cmd, char *env_path, + int *status, int flag) +{ + int ret, argc= 0; + char **argv= NULL, *pathlist= NULL, *cpt, *npt, prog[SfileadrL]; + char sfe[5*SfileadrL]; + pid_t child_pid; + struct stat stbuf; + + wait3(NULL,WNOHANG,NULL); /* just to remove any old dead child */ + + ret= Sfile_make_argv("", cmd, &argc, &argv, 1|4|128); + if(ret <= 0) + goto ex; + if(argc < 1) + {ret= 0; goto ex;} + + strcpy(prog, argv[0]); + if((flag & 1) && strchr(argv[0], '/') == NULL) { + if(env_path == NULL) + env_path= "/bin:/sbin"; + else if(env_path[0] == 0) + env_path= "/bin:/sbin"; + if(Sregex_string(&pathlist, env_path, 0) <= 0) + {ret= -1; goto ex;} + for(cpt= npt= pathlist; npt != NULL; cpt= npt + 1) { + npt= strchr(cpt, ':'); + if(npt != NULL) + *npt= 0; + if(strlen(cpt) + strlen(argv[0]) + 1 >= SfileadrL) + {ret= -1; goto ex;} + sprintf(prog, "%s/%s", cpt, argv[0]); + ret= stat(prog, &stbuf); + if(ret != -1) + break; + prog[0]= 0; + } + if(prog[0] == 0) { + sprintf(xorriso->info_text, "Cannot find external program %s", + Text_shellsafe(argv[0], sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + } + + child_pid= fork(); + if(child_pid==-1) + return(-1); + + if(child_pid==0) { + /* this is the child process */ + + sprintf(xorriso->info_text, "Executing external program %s", + Text_shellsafe(prog, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); + + execv(prog, argv); /* should never come back */ + fprintf(stderr,"--- execution of shell command failed:\n"); + fprintf(stderr," %s\n",cmd); + exit(127); + } + + + /* this is the original process waiting for child to exit */ + do { + /* try to read and print the reply */; + ret= waitpid(child_pid,status,WNOHANG); + if(ret==-1) { + if(errno!=EINTR) + ret= 0; goto ex; + } else if(ret==0) { + +#ifdef NIX + + /* >>> An interrupt key would be nice. */ + + if((flag&4)) { + ret= Asqueue_event_is_pending(agent->queue,0,0); + if(ret>0) { + Asagent_stderr(agent,"--- shell command interrupted",1); + kill(child_pid,SIGTERM); + ret= 2; goto ex; + } + } +#endif /* NIX */ + + continue; + } else { + break; + } + } while(1); + ret= 1; +ex: + Sfile_make_argv("", "", &argc, &argv, 2); + Sregex_string(&pathlist, NULL, 0); + return(ret); +} + + /* ---------------------------- Options API ------------------------ */ @@ -12785,9 +12900,11 @@ int Xorriso_option_help(struct XorrisO *xorriso, int flag) "", " -toc Show media specific table of content (sessions).", "", -" -mount_cmd drive entity id \"linux:\"path|\"freebsd:\"path|\"shell:\"form", +" -mount_cmd drive entity id path", " Print to result channel a command suitable to mount the", " depicted entity (see -load) at the given directory path.", +" -session_string drive entity id \"linux:\"path|\"freebsd:\"path|form", +" Print foreign OS command or custom line.", "", " -list_formats Show media specific list of format descriptors.", "", @@ -13023,9 +13140,9 @@ int Xorriso_option_help(struct XorrisO *xorriso, int flag) " Like -cp_rx but trying to restore timestamps and ownership.", " -paste_in iso_rr_path disk_path byte_offset byte_count", " Copy ISO file content into a byte interval of a disk file.", -" -mount drive entity id \"linux:\"path|\"freebsd:\"path|\"shell:\"form", +" -mount drive entity id path", " Like -mount_cmd but actually performing that command if it", -" is not from a shell:form and no setuid or setgid is active.", +" not setuid or setgid is active.", "", "Evaluation of readability:", " -check_media [options] --", @@ -13751,17 +13868,21 @@ ex:; } -/* Option -mount */ -/* @param bit0= print mount command to result channel rather than performing it +/* Options -mount , -mount_mds , -session_string */ +/* @param bit0= -mount_cmd: print mount command to result channel rather + than performing it + bit1= preform -session_string rather than -mount_cmd */ int Xorriso_option_mount(struct XorrisO *xorriso, char *dev, char *adr_mode, char *adr, char *cmd, int flag) { - int ret, entity_code= 0; + int ret, entity_code= 0, m_flag; char entity_id[81], *mnt; if(flag & 1) mnt= "-mount_cmd"; + else if(flag & 2) + mnt= "-session_string"; else { mnt= "-mount"; if(!xorriso->allow_restore) { @@ -13781,7 +13902,11 @@ int Xorriso_option_mount(struct XorrisO *xorriso, char *dev, char *adr_mode, &entity_code, entity_id, 0); if(ret <= 0) return(ret); - ret= Xorriso_mount(xorriso, dev, entity_code, entity_id, cmd, flag & 1); + if(flag & 2) + m_flag= 1 | 4; + else + m_flag= (flag & 1) | 2; + ret= Xorriso_mount(xorriso, dev, entity_code, entity_id, cmd, m_flag); return(ret); } @@ -15239,7 +15364,7 @@ int Xorriso_count_args(struct XorrisO *xorriso, int argc, char **argv, "" }; static char arg4_commands[][40]= { - "cut_out","extract_cut","mount","mount_cmd","paste_in", + "cut_out","extract_cut","mount","mount_cmd","paste_in","session_string", "" }; static char argn_commands[][40]= { @@ -15670,7 +15795,8 @@ next_command:; (*idx)+= 4; if((*idx)>argc) { sprintf(xorriso->info_text, - "-mount: Not enough arguments. Needed are: device entity id command"); + "-%s: Not enough arguments. Needed are: device entity id command", + cmd); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); ret= 0; } else @@ -15847,6 +15973,18 @@ next_command:; (*idx)++; ret= Xorriso_option_session_log(xorriso, arg1, 0); + } else if(strcmp(cmd, "session_string") == 0) { + (*idx)+= 4; + if((*idx)>argc) { + sprintf(xorriso->info_text, + "-%s: Not enough arguments. Needed are: device entity id command", + cmd); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; + } else + ret= Xorriso_option_mount(xorriso, arg1, arg2, + argv[(*idx)-2], argv[(*idx)-1], 2); + } else if(strcmp(cmd,"speed")==0) { (*idx)++; ret= Xorriso_option_speed(xorriso, arg1, 0); diff --git a/xorriso/xorriso_private.h b/xorriso/xorriso_private.h index f390b327..f4f468aa 100644 --- a/xorriso/xorriso_private.h +++ b/xorriso/xorriso_private.h @@ -598,6 +598,12 @@ int Xorriso_make_mount_cmd(struct XorrisO *xorriso, char *cmd, char *devadr, char result[SfileadrL], int flag); +/* @param flag bit0= use env_path to find the desired program +*/ +int Xorriso_execv(struct XorrisO *xorriso, char *cmd, char *env_path, + int *status, int flag); + + int Sfile_str(char target[SfileadrL], char *source, int flag); double Sfile_microtime(int flag); diff --git a/xorriso/xorriso_timestamp.h b/xorriso/xorriso_timestamp.h index 017c26cf..a0900fe4 100644 --- a/xorriso/xorriso_timestamp.h +++ b/xorriso/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2008.12.06.140828" +#define Xorriso_timestamP "2008.12.07.122439" diff --git a/xorriso/xorrisoburn.c b/xorriso/xorrisoburn.c index 10dd4436..3a544b27 100644 --- a/xorriso/xorrisoburn.c +++ b/xorriso/xorrisoburn.c @@ -8416,12 +8416,14 @@ int Xorriso_get_relax_text(struct XorrisO *xorriso, char mode[1024], /** @param flag bit0= print mount command to result channel rather than performing it + bit1= do not allow prefixes with cmd + bit2= interpret unprefixed cmd as shell: */ int Xorriso_mount(struct XorrisO *xorriso, char *dev, int adr_mode, char *adr_value, char *cmd, int flag) { int ret, lba, track, session, params_flag= 0, is_safe= 0, is_extra_drive= 0; - int give_up= 0, mount_chardev= 0; + int give_up= 0, mount_chardev= 0, status; char volid[33], *devadr, mount_command[SfileadrL], adr_data[163], *adr_pt; char *dev_path, libburn_adr[BURN_DRIVE_ADR_LEN + SfileadrL]; char sfe[5 * SfileadrL], *dpt, *sysname= ""; @@ -8436,7 +8438,9 @@ int Xorriso_mount(struct XorrisO *xorriso, char *dev, int adr_mode, "on attempt to perform -mount \"indev\"", 0); if(ret<=0) goto ex; - devadr= xorriso->indev; + dev_path= devadr= xorriso->indev; + if(strncmp(dev_path, "stdio:", 6) == 0) + dev_path+= 6; if(xorriso->in_drive_handle == xorriso->out_drive_handle) give_up= 3; else @@ -8447,7 +8451,9 @@ int Xorriso_mount(struct XorrisO *xorriso, char *dev, int adr_mode, 2); if(ret<=0) goto ex; - devadr= xorriso->outdev; + dev_path= devadr= xorriso->outdev; + if(strncmp(dev_path, "stdio:", 6) == 0) + dev_path+= 6; if(xorriso->in_drive_handle == xorriso->out_drive_handle) give_up= 3; else @@ -8513,7 +8519,7 @@ int Xorriso_mount(struct XorrisO *xorriso, char *dev, int adr_mode, if(strstr(devadr, "stdio:") == devadr) devadr+= 6; ret= Xorriso_make_mount_cmd(xorriso, cmd, lba, track, session, volid, devadr, - mount_command, 0); + mount_command, flag & (2 | 4)); if(ret <= 0) goto ex; if(ret == 2) @@ -8539,23 +8545,24 @@ int Xorriso_mount(struct XorrisO *xorriso, char *dev, int adr_mode, } else { sprintf(xorriso->info_text, "Mount command: %s\n", mount_command); Xorriso_info(xorriso, 0); - if(geteuid() != getuid() || getgid() != getegid()) { - Xorriso_msgs_submit(xorriso, 0, - "-mount : Detected own setuid/gid identity. Will not perform mount command.", - 0, "SORRY", 0); - sprintf(xorriso->result_line, "%s\n", mount_command); - Xorriso_result(xorriso,0); - } else if(!is_safe) { + if(!is_safe) { Xorriso_msgs_submit(xorriso, 0, "-mount : Will not perform mount command which stems from command template.", 0, "SORRY", 0); sprintf(xorriso->result_line, "%s\n", mount_command); Xorriso_result(xorriso,0); - } else { +#ifdef NIX + + } else if(geteuid() != getuid() || getgid() != getegid()) { + Xorriso_msgs_submit(xorriso, 0, + "-mount : Detected own setuid/gid identity. Will not perform mount command.", + 0, "SORRY", 0); + sprintf(xorriso->result_line, "%s\n", mount_command); + Xorriso_result(xorriso,0); + } else { /* >>> find safer way to perform command */; ret= system(mount_command); - if(WIFEXITED(ret) && WEXITSTATUS(ret) != 0) { sprintf(xorriso->info_text, "-mount : mount command failed with exit value %d", @@ -8563,13 +8570,30 @@ int Xorriso_mount(struct XorrisO *xorriso, char *dev, int adr_mode, Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); ret= 0; goto ex; } - sprintf(xorriso->info_text, "Mounted session %d of device %s", + +#else + + } else { + ret= Xorriso_execv(xorriso, mount_command, "/bin:/sbin", &status, 1); + if(WIFEXITED(status) && WEXITSTATUS(status) != 0) { + sprintf(xorriso->info_text, + "-mount : mount command failed with exit value %d", + (int) WEXITSTATUS(ret)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } + +#endif + + sprintf(xorriso->info_text, "\nMounted session %d of device %s", session, Text_shellsafe(dev_path, sfe, 0)); dpt= strchr(cmd, ':'); if(dpt == NULL) - dpt= cmd; + dpt= cmd ; + else + dpt++; sprintf(xorriso->info_text + strlen(xorriso->info_text), - " as directory %s\n", Text_shellsafe(dpt + 1, sfe, 0)); + " as directory %s\n", Text_shellsafe(dpt, sfe, 0)); Xorriso_info(xorriso, 0); } }