You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2326 lines
90 KiB

/* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
Copyright 2007-2014 Thomas Schmitt, <scdbackup@gmx.net>
Provided under GPL version 2 or later.
This file contains the implementation of options as mentioned in man page
or info file derived from xorriso.texi.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <ctype.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <time.h>
#include <errno.h>
#include "xorriso.h"
#include "xorriso_private.h"
#include "xorrisoburn.h"
/* Command -data_cache_size */
int Xorriso_option_data_cache_size(struct XorrisO *xorriso, char *num_tiles,
char *tile_blocks, int flag)
{
int ret, blocks= -1, tiles= -1, to_default= 0;
sscanf(num_tiles, "%d", &tiles);
sscanf(tile_blocks, "%d", &blocks);
if(strcmp(num_tiles, "default") == 0 || num_tiles[0] == 0)
to_default|= 1;
if(strcmp(tile_blocks, "default") == 0 || tile_blocks[0] == 0)
to_default|= 2;
ret= Xorriso_set_data_cache(xorriso, NULL, tiles, blocks, to_default);
if(ret > 0) {
xorriso->cache_num_tiles= tiles;
xorriso->cache_tile_blocks= blocks;
xorriso->cache_default= to_default;
}
return(ret);
}
/* Options -dev , -indev, -outdev */
/** @param flag bit0= use as indev
bit1= use as outdev
bit2= do not -reassure
bit3= regard overwriteable media as blank
bit4= if the drive is a regular disk file: truncate it to
the write start address
bit5= do not print toc of aquired drive
bit6= do not calm down drive after aquiring it
@return <=0 error , 1 success, 2 revoked by -reassure
*/
int Xorriso_option_dev(struct XorrisO *xorriso, char *in_adr, int flag)
{
int ret;
char *adr;
adr= in_adr;
if(strcmp(in_adr, "-")==0)
adr= "stdio:/dev/fd/1";
if(strncmp(adr, "stdio:", 6)==0) {
if(strlen(adr)==6 || strcmp(adr, "stdio:/")==0 ||
strcmp(adr, "stdio:.")==0 || strcmp(adr, "stdio:..")==0 ||
strcmp(adr, "stdio:-")==0) {
sprintf(xorriso->info_text,
"No suitable path given by device address '%s'", adr);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
return(0);
}
}
if(Xorriso_change_is_pending(xorriso, 0) && (flag&1)) {
sprintf(xorriso->info_text,
"%s: Image changes pending. -commit or -rollback first",
(flag&2) ? "-dev" : "-indev");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
return(0);
}
if((flag&1) && (xorriso->in_drive_handle != NULL || adr[0]) && !(flag&4)) {
ret= Xorriso_reassure(xorriso, (flag&2) ? "-dev" : "-indev",
"eventually discard the current image", 0);
if(ret<=0)
return(2);
}
if(adr[0]==0) {
if((flag&1) && xorriso->in_drive_handle != NULL) {
if(xorriso->in_drive_handle == xorriso->out_drive_handle)
sprintf(xorriso->info_text,"Giving up -dev ");
else
sprintf(xorriso->info_text,"Giving up -indev ");
Text_shellsafe(xorriso->indev, xorriso->info_text, 1);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
}
if((flag&2) && xorriso->out_drive_handle != NULL &&
xorriso->in_drive_handle != xorriso->out_drive_handle) {
sprintf(xorriso->info_text,"Giving up -outdev ");
Text_shellsafe(xorriso->outdev, xorriso->info_text, 1);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
}
ret= Xorriso_give_up_drive(xorriso, (flag&3)|((flag&32)>>2));
} else
ret= Xorriso_aquire_drive(xorriso, adr, NULL,
(flag & (3 | 32 | 64)) | (((flag & (8 | 16)) >> 1)));
if(ret<=0)
return(ret);
if(xorriso->in_drive_handle == NULL)
xorriso->image_start_mode= 0; /* session setting is invalid by now */
return(1);
}
/* Option -devices , -device_links */
/* @param flag bit0= perform -device_links rather than -devices
@return <=0 error , 1 success, 2 revoked by -reassure
*/
int Xorriso_option_devices(struct XorrisO *xorriso, int flag)
{
int ret;
if(Xorriso_change_is_pending(xorriso, 0)) {
sprintf(xorriso->info_text,
"-devices: Image changes pending. -commit or -rollback first");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
return(0);
}
ret= Xorriso_reassure(xorriso, "-devices",
"eventually discard the current image", 0);
if(ret<=0)
return(2);
xorriso->info_text[0]= 0;
if(xorriso->in_drive_handle!=NULL || xorriso->out_drive_handle!=NULL) {
if(xorriso->in_drive_handle == xorriso->out_drive_handle) {
sprintf(xorriso->info_text, "Gave up -dev ");
Text_shellsafe(xorriso->indev, xorriso->info_text, 1);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
}else {
if(xorriso->in_drive_handle!=NULL) {
sprintf(xorriso->info_text, "Gave up -indev ");
Text_shellsafe(xorriso->indev, xorriso->info_text, 1);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
}
if(xorriso->out_drive_handle!=NULL) {
sprintf(xorriso->info_text, "Gave up -outdev ");
Text_shellsafe(xorriso->outdev, xorriso->info_text, 1);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
}
}
Xorriso_give_up_drive(xorriso, 3);
}
ret= Xorriso_show_devices(xorriso, flag & 1);
return(ret);
}
/* Option -dialog "on"|"single_line"|"off" */
int Xorriso_option_dialog(struct XorrisO *xorriso, char *mode, int flag)
{
if(strcmp(mode, "on") == 0 || strcmp(mode, "multi_line") == 0)
xorriso->dialog= 2;
else if(strcmp(mode, "single_line") == 0)
xorriso->dialog= 1;
else if(strcmp(mode, "off") == 0)
xorriso->dialog= 0;
else {
sprintf(xorriso->info_text, "-dialog: unknown mode '%s'", mode);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
return(0);
}
return(1);
}
/* Option -disk_dev_ino "on"|"ino_only"|"off" */
int Xorriso_option_disk_dev_ino(struct XorrisO *xorriso, char *mode, int flag)
{
if(strcmp(mode, "on") == 0)
xorriso->do_aaip= (xorriso->do_aaip & ~128) | 16 | 32 | 64;
else if(strcmp(mode, "ino_only") == 0)
xorriso->do_aaip|= 16 | 32 | 64 | 128;
else if(strcmp(mode, "off") == 0)
xorriso->do_aaip &= ~(16 | 32 | 64 | 128);
else {
sprintf(xorriso->info_text, "-disk_dev_ino: unknown mode '%s'", mode);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
return(0);
}
return(1);
}
/* Option -disk_pattern "on"|"ls"|"off" */
int Xorriso_option_disk_pattern(struct XorrisO *xorriso, char *mode, int flag)
{
if(strcmp(mode, "off")==0)
xorriso->do_disk_pattern= 0;
else if(strcmp(mode, "on")==0)
xorriso->do_disk_pattern= 1;
else if(strcmp(mode, "ls")==0)
xorriso->do_disk_pattern= 2;
else {
sprintf(xorriso->info_text, "-disk_pattern: unknown mode '%s'", mode);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
return(0);
}
return(1);
}
/* Option -displacement [-]offset */
int Xorriso_option_displacement(struct XorrisO *xorriso, char *value, int flag)
{
double num;
int displacement_sign= 1, l;
char *cpt;
cpt= value;
if(value[0] == '-') {
displacement_sign= -1;
cpt++;
} else if(value[0] == '+')
cpt++;
num= Scanf_io_size(cpt, 0);
l= strlen(cpt);
if(cpt[l - 1] < '0' || cpt[l - 1] > '9')
num/= 2048.0;
if(num < 0.0 || num > 4294967295.0) {
sprintf(xorriso->info_text,
"-displacement: too large or too small: '%s'", value);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
return(0);
}
if(num == 0)
displacement_sign= 0;
xorriso->displacement= num;
xorriso->displacement_sign= displacement_sign;
return(1);
}
/* Option -drive_class */
int Xorriso_option_drive_class(struct XorrisO *xorriso,
char *d_class, char *pattern, int flag)
{
int ret= 1;
if(strcmp(d_class, "banned") == 0) {
ret= Xorriso_lst_new(&(xorriso->drive_blacklist), pattern,
xorriso->drive_blacklist, 1);
} else if(strcmp(d_class, "caution") == 0) {
ret= Xorriso_lst_new(&(xorriso->drive_greylist), pattern,
xorriso->drive_greylist, 1);
} else if (strcmp(d_class, "harmless") == 0) {
ret= Xorriso_lst_new(&(xorriso->drive_whitelist), pattern,
xorriso->drive_whitelist, 1);
} else if (strcmp(d_class, "clear_list") == 0) {
if(strcmp(pattern, "banned") == 0)
Xorriso_lst_destroy_all(&(xorriso->drive_blacklist), 0);
else if(strcmp(pattern, "caution") == 0)
Xorriso_lst_destroy_all(&(xorriso->drive_greylist), 0);
else if(strcmp(pattern, "harmless") == 0)
Xorriso_lst_destroy_all(&(xorriso->drive_whitelist), 0);
else if(strcmp(pattern, "all") == 0) {
Xorriso_lst_destroy_all(&(xorriso->drive_blacklist), 0);
Xorriso_lst_destroy_all(&(xorriso->drive_greylist), 0);
Xorriso_lst_destroy_all(&(xorriso->drive_whitelist), 0);
} else {
sprintf(xorriso->info_text, "-drive_class clear : unknown class '%s'",
pattern);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
return(0);
}
ret= 1;
} else {
sprintf(xorriso->info_text, "-drive_class: unknown class '%s'", d_class);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
return(0);
}
return(ret);
}
/* Option -dummy "on"|"off" */
int Xorriso_option_dummy(struct XorrisO *xorriso, char *mode, int flag)
{
xorriso->do_dummy= !!strcmp(mode, "off");
return(1);
}
/* Option -dvd_obs "default"|"32k"|"64k" */
int Xorriso_option_dvd_obs(struct XorrisO *xorriso, char *obs, int flag)
{
double num;
if(strcmp(obs, "default") == 0)
num= 0;
else
num = Scanf_io_size(obs,0);
if(num != 0 && num != 32768 && num != 65536) {
sprintf(xorriso->info_text,
"-dvd_obs : Bad size. Acceptable are 0, 32k, 64k");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
return(0);
} else
xorriso->dvd_obs= num;
return(1);
}
/* Option -early_stdio_test */
int Xorriso_option_early_stdio_test(struct XorrisO *xorriso, char *mode,
int flag)
{
if(strcmp(mode, "on") == 0)
xorriso->early_stdio_test= 2 | 4;
else if(strcmp(mode, "off") == 0)
xorriso->early_stdio_test= 0;
else if(strcmp(mode, "appendable_wo") == 0)
xorriso->early_stdio_test= 2 | 4 | 8;
else {
sprintf(xorriso->info_text, "-early_stdio_test: unknown mode '%s'", mode);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0);
return(0);
}
return(1);
}
/* Option -eject */
/* @param flag bit0=do not report toc of eventually remaining drives
*/
int Xorriso_option_eject(struct XorrisO *xorriso, char *which, int flag)
{
int gu_flag= 4, ret;
if(strncmp(which,"in",2)==0)
gu_flag|= 1;
else if(strncmp(which,"out",3)==0)
gu_flag|= 2;
else
gu_flag|= 3;
if((gu_flag&1) && Xorriso_change_is_pending(xorriso, 0)) {
sprintf(xorriso->info_text,
"-eject: Image changes pending. -commit or -rollback first");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
return(0);
}
if(flag&1)
gu_flag|= 8;
ret= Xorriso_give_up_drive(xorriso, gu_flag);
return(ret);
}
/* Options -end , and -rollback_end */
/* @param flag bit0= discard pending changes
bit1= do not -reassure
@return <=0 error , 1 success, 2 revoked by -reassure
*/
int Xorriso_option_end(struct XorrisO *xorriso, int flag)
{
int ret;
char *cmd, *which_will;
if(flag&1)
cmd= "-rollback_end";
else
cmd= "-end";
if(Xorriso_change_is_pending(xorriso, 0)) {
if((flag & 1) || !Xorriso_change_is_pending(xorriso, 1))
which_will= "end the program discarding image changes";
else
which_will= "commit image changes and then end the program";
} else {
which_will= "end the program";
}
if(!(flag&2)) {
ret= Xorriso_reassure(xorriso, cmd, which_will, 0);
if(ret<=0)
return(2);
}
if(Xorriso_change_is_pending(xorriso, 0)) {
if((flag & 1) || !Xorriso_change_is_pending(xorriso, 1)) {
xorriso->volset_change_pending= 0;
} else {
ret= Xorriso_option_commit(xorriso, 1);
xorriso->volset_change_pending= 0; /* no further tries to commit */
if(ret<=0)
return(ret);
}
}
ret= Xorriso_give_up_drive(xorriso, 3);
if(ret<=0)
return(ret);
return(1);
}
/* Option -errfile_log marked|plain path|-|"" */
int Xorriso_option_errfile_log(struct XorrisO *xorriso,
char *mode, char *path, int flag)
{
int ret, mode_word;
FILE *fp= NULL;
if(path[0]==0 || path[0]=='-') {
/* ok */;
} else {
fp= fopen(path, "a");
if(fp==0) {
sprintf(xorriso->info_text, "-errfile_log: Cannot open file ");
Text_shellsafe(path, xorriso->info_text, 1);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
return(0);
}
}
mode_word= xorriso->errfile_mode;
if(strcmp(mode, "marked")==0)
mode_word|= 1;
else if(strcmp(mode, "plain")==0)
mode_word&= ~1;
else {
sprintf(xorriso->info_text, "-errfile_log: Unknown mode ");
Text_shellsafe(mode, xorriso->info_text, 1);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
if(fp != NULL)
fclose(fp);
return(0);
}
Xorriso_process_errfile(xorriso, 0, "log end", 0, 1);
if(xorriso->errfile_fp!=NULL)
fclose(xorriso->errfile_fp);
xorriso->errfile_fp= fp;
xorriso->errfile_mode= mode_word;
ret= Sfile_str(xorriso->errfile_log, path, 0);
if(ret>0)
ret= Xorriso_process_errfile(xorriso, 0, "log start", 0, 1);
if(ret<=0)
return(ret);
return(1);
}
/* Option -error_behavior */
int Xorriso_option_error_behavior(struct XorrisO *xorriso,
char *occasion, char *behavior, int flag)
{
if(strcmp(occasion, "image_loading")==0) {
if(strcmp(behavior, "best_effort")==0)
xorriso->img_read_error_mode= 0;
else if(strcmp(behavior, "failure")==0 || strcmp(behavior, "FAILURE")==0)
xorriso->img_read_error_mode= 1;
else if(strcmp(behavior, "fatal")==0 || strcmp(behavior, "FATAL")==0)
xorriso->img_read_error_mode= 2;
else {
unknown_behavior:;
sprintf(xorriso->info_text,
"-error_behavior: with '%s': unknown behavior '%s'",
occasion, behavior);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
return(0);
}
} else if(strcmp(occasion, "file_extraction")==0) {
if(strcmp(behavior, "best_effort")==0)
xorriso->extract_error_mode= 0;
else if(strcmp(behavior, "keep")==0)
xorriso->extract_error_mode= 1;
else if(strcmp(behavior, "delete")==0)
xorriso->extract_error_mode= 2;
else
goto unknown_behavior;
} else {
sprintf(xorriso->info_text, "-error_behavior: unknown occasion '%s'",
occasion);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
return(0);
}
return(1);
}
/* Option -external_filter */
int Xorriso_option_external_filter(struct XorrisO *xorriso,
int argc, char **argv, int *idx, int flag)
{
int ret, start_idx, end_idx;
start_idx= *idx;
end_idx= Xorriso_end_idx(xorriso, argc, argv, start_idx, 1);
(*idx)= end_idx;
if(end_idx - start_idx < 3) {
sprintf(xorriso->info_text,
"-external_filter : Not enough parameters given. Needed: name options path %s",
xorriso->list_delimiter);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
return(0);
}
ret= Xorriso_external_filter(xorriso, argv[start_idx],
argv[start_idx + 1], argv[start_idx + 2],
end_idx - start_idx - 3, argv + start_idx + 3, 0);
return(ret);
}
/* Options -extract , -extract_single */
/* @param flag bit0=do not report the restored item
bit1=do not reset pacifier, no final pacifier message
bit2= do not make lba-sorted node array for hardlink detection
bit5= -extract_single: eventually do not insert directory tree
*/
int Xorriso_option_extract(struct XorrisO *xorriso, char *iso_path,
char *disk_path, int flag)
{
int ret, problem_count;
char *eff_origin= NULL, *eff_dest= NULL, *ipth, *eopt[1], *edpt[1];
Xorriso_alloc_meM(eff_origin, char, SfileadrL);
Xorriso_alloc_meM(eff_dest, char, SfileadrL);
if(xorriso->allow_restore <= 0) {
sprintf(xorriso->info_text,
"-extract: image-to-disk copies are not enabled by option -osirrox");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
ret= 0; goto ex;
}
if(!(flag&2))
Xorriso_pacifier_reset(xorriso, 0);
ipth= iso_path;
if(ipth[0]==0)
ipth= disk_path;
if(disk_path[0]==0) {
sprintf(xorriso->info_text, "-extract: Empty disk_path given");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 1);
ret= 0; goto ex;
}
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdx, disk_path, eff_dest,
2|4);
if(ret<=0)
goto ex;
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, ipth, eff_origin, 2|8);
if(ret<=0)
goto ex;
eopt[0]= eff_origin;
edpt[0]= eff_dest;
ret= Xorriso_restore_sorted(xorriso, 1, eopt, edpt, &problem_count,
(flag & 32 ? 33 : 0));
if(!(flag&2))
Xorriso_pacifier_callback(xorriso, "files restored",xorriso->pacifier_count,
xorriso->pacifier_total, "", 1 | 4 | 8 | 32);
if(ret <= 0 || problem_count > 0)
goto ex;
if(!(flag&1)) {
sprintf(xorriso->info_text, "Extracted from ISO image: %s '%s'='%s'\n",
(ret>1 ? "directory" : "file"), eff_origin, eff_dest);
Xorriso_info(xorriso,0);
}
ret= 1;
ex:;
if(!(flag & (4 | 32)))
Xorriso_destroy_node_array(xorriso, 0);
Xorriso_free_meM(eff_origin);
Xorriso_free_meM(eff_dest);
return(ret);
}
/* Option -extract_cut */
int Xorriso_option_extract_cut(struct XorrisO *xorriso, char *iso_rr_path,
char *start, char *count, char *disk_path, int flag)
{
int ret;
double num;
off_t startbyte, bytecount;
num= Scanf_io_size(start, 0);
if(num<0 || num > 1.0e18) { /* 10^18 = 10^3 ^ 6 < 2^10 ^ 6 = 2^60 */
sprintf(xorriso->info_text,
"-extract_cut: startbyte address negative or much too large (%s)",
start);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
return(0);
}
startbyte= num;
num= Scanf_io_size(count, 0);
if(num<=0 || num > 1.0e18) {
sprintf(xorriso->info_text,
"-extract_cut: bytecount zero, negative or much too large (%s)",
count);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
return(0);
}
bytecount= num;
sprintf(xorriso->info_text,
"-extract_cut from %s , byte %.f to %.f, and store as %s",
iso_rr_path, (double) startbyte, (double) (startbyte+bytecount),
disk_path);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
ret= Xorriso_extract_cut(xorriso, iso_rr_path, disk_path,
startbyte, bytecount, 0);
return(ret);
}
/* Option -file_size_limit */
int Xorriso_option_file_size_limit(struct XorrisO *xorriso,
int argc, char **argv, int *idx, int flag)
{
int ret, i, end_idx;
off_t new_limit= 0;
end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, 1);
if(*idx >= end_idx)
{ret= 2; goto ex;}
if(*idx + 1 == end_idx && strcmp(argv[*idx], "off") == 0) {
xorriso->file_size_limit= 0;
ret= 1; goto ex;
}
for(i= *idx; i < end_idx; i++)
new_limit+= Scanf_io_size(argv[i], 0);
if(new_limit <= 0) {
sprintf(xorriso->info_text, "-file_size_limit: values sum up to %.f",
(double) new_limit);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 1);
ret= 0; goto ex;
}
xorriso->file_size_limit= new_limit;
ret= 1;
ex:;
(*idx)= end_idx;
if(ret > 0) {
if(xorriso->file_size_limit > 0)
sprintf(xorriso->info_text, "-file_size_limit now at %.f\n",
(double) xorriso->file_size_limit);
else
sprintf(xorriso->info_text, "-file_size_limit now off\n");
Xorriso_info(xorriso,0);
}
return(ret);
}
static int Xorriso_determine_name_space(struct XorrisO *xorriso,
char *space_name, int flag)
{
if(strcmp(space_name, "rockridge") == 0)
return(1);
else if(strcmp(space_name, "joliet") == 0)
return(2);
else if(strcmp(space_name, "ecma119") == 0 ||
strcmp(space_name, "iso9660") == 0)
return(3);
else if(strcmp(space_name, "hfsplus") == 0)
return(4);
sprintf(xorriso->info_text, "-find: Unknown output namespace identifier");
return(0);
}
/* Option -find alias -findi, and -findx */
/* @param flag bit0= -findx rather than -findi
bit1= do not reset pacifier, no final pacifier message
do not reset find_compare_result
bit2= do not count deleted files with rm and rm_r
bit3= use Xorriso_findi_sorted() rather than Xorriso_findi()
(this can also be ordered by test -sort_lba)
bit4= return number of matches plus 1
*/
int Xorriso_option_find(struct XorrisO *xorriso, int argc, char **argv,
int *idx, int flag)
{
int ret, i, end_idx, type= 0, action, deleter= 0, start_lba, count;
int list_extattr_head= 0, bsl_mem, disk_path, name_space;
struct FindjoB *job, *first_job= NULL, *new_job;
char *start_path, *path= NULL, *cpt, *other_path_start= NULL, *cd_pt;
char *access_acl_text= NULL, *default_acl_text= NULL, *list_extattr_mode;
char *arg1_pt;
struct stat dir_stbuf;
uid_t user= 0;
gid_t group= 0;
time_t date= 0;
mode_t mode_or= 0, mode_and= ~1;
double mem_lut= 0.0;
end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, 1);
Xorriso_alloc_meM(path, char, SfileadrL);
Xorriso_alloc_meM(other_path_start, char, SfileadrL);
start_path= ".";
list_extattr_mode= "e";
if(end_idx > *idx && start_path[0]!=0)
start_path= argv[*idx];
ret= Findjob_new(&first_job, start_path, 0);
if(ret<=0) {
Xorriso_no_findjob(xorriso, "-find[ix]", 0);
{ret= -1; goto ex;}
}
job= first_job;
if(!(flag&2))
xorriso->find_compare_result= 1;
for(i= *idx+1; i<end_idx; i++) {
if(strcmp(argv[i], "-name")==0) {
if(i+1>=end_idx) {
not_enough_arguments:;
sprintf(xorriso->info_text,
"-find[ix]: not enough parameters with test ");
Text_shellsafe(argv[i], xorriso->info_text, 1);
goto sorry_ex;
}
i++;
ret= Findjob_set_name_expr(job, argv[i], 0);
if(ret<=0) {
sprintf(xorriso->info_text, "-find[ix]: cannot set -name expression ");
Text_shellsafe(argv[i], xorriso->info_text, 1);
goto sorry_ex;
}
} else if(strcmp(argv[i], "-wholename")==0) {
if(i+1>=end_idx)
goto not_enough_arguments;
i++;
ret= Findjob_set_name_expr(job, argv[i], 1);
if(ret<=0) {
sprintf(xorriso->info_text,
"-find[ix]: cannot set -wholename expression ");
Text_shellsafe(argv[i], xorriso->info_text, 1);
goto sorry_ex;
}
} else if(strcmp(argv[i], "-type")==0) {
if(i+1>=end_idx)
goto not_enough_arguments;
i++;
ret= Findjob_set_file_type(job, argv[i][0], 0);
if(ret<=0) {
sprintf(xorriso->info_text, "-find[ix]: unknown -type '%c'",argv[i][0]);
goto sorry_ex;
}
} else if(strcmp(argv[i], "-damaged")==0) {
Findjob_set_damage_filter(job, 1, 0);
} else if(strcmp(argv[i], "-undamaged")==0) {
Findjob_set_damage_filter(job, -1, 0);
} else if(strcmp(argv[i], "-lba_range")==0) {
if(i+2>=end_idx)
goto not_enough_arguments;
i+= 2;
sscanf(argv[i-1], "%d", &start_lba);
sscanf(argv[i], "%d", &count);
Findjob_set_lba_range(job, start_lba, count, 0);
} else if(strcmp(argv[i], "-pending_data")==0) {
Findjob_set_commit_filter_2(job, 0);
} else if(strcmp(argv[i], "-has_acl")==0) {
Findjob_set_acl_filter(job, 1, 0);
} else if(strcmp(argv[i], "-has_no_acl")==0) {
Findjob_set_acl_filter(job, -1, 0);
} else if(strcmp(argv[i], "-has_xattr")==0) {
Findjob_set_xattr_filter(job, 1, 0);
} else if(strcmp(argv[i], "-has_any_xattr")==0) {
Findjob_set_xattr_filter(job, 1, 1);
} else if(strcmp(argv[i], "-has_no_xattr")==0) {
Findjob_set_xattr_filter(job, -1, 0);
} else if(strcmp(argv[i], "-has_aaip")==0) {
Findjob_set_aaip_filter(job, 1, 0);
} else if(strcmp(argv[i], "-has_no_aaip")==0) {
Findjob_set_aaip_filter(job, -1, 0);
} else if(strcmp(argv[i], "-has_filter")==0) {
Findjob_set_filter_filter(job, 1, 0);
} else if(strcmp(argv[i], "-has_no_filter")==0) {
Findjob_set_filter_filter(job, -1, 0);
} else if(strcmp(argv[i], "-has_md5")==0) {
Findjob_set_prop_filter(job, 15, 1, 0);
} else if(strcmp(argv[i], "-disk_name")==0 ||
strcmp(argv[i], "-disk_path")==0) {
disk_path= (strcmp(argv[i], "-disk_path") == 0);
if(i+1>=end_idx)
goto not_enough_arguments;
i++;
arg1_pt= argv[i];
if(disk_path) {
ret= Xorriso_make_abs_adr(xorriso, xorriso->wdx, argv[i], path,
1 | 2 | 4 | 8);
if(ret<=0)
goto ex;
arg1_pt= path;
}
ret= Findjob_set_name_expr(job, arg1_pt, 2 + disk_path);
if(ret<=0) {
sprintf(xorriso->info_text,
"-find[ix]: cannot set %s ",
disk_path ? "-disk_path address" : "-disk_name expression");
Text_shellsafe(argv[i], xorriso->info_text, 1);
goto sorry_ex;
}
} else if(strcmp(argv[i], "-hidden")==0) {
if(i + 1 >= end_idx)
goto not_enough_arguments;
i+= 1;
type= Xorriso__hide_mode(argv[i], 0);
if(type < 0) {
sprintf(xorriso->info_text, "-findi: -hidden : unknown hide state ");
Text_shellsafe(argv[i], xorriso->info_text, 1);
goto sorry_ex;
} else {
ret= Findjob_set_test_hidden(job, type, 0);
if(ret <= 0) {
sprintf(xorriso->info_text, "-findi: cannot setup -hidden test");
goto sorry_ex;
}
}
} else if(strcmp(argv[i], "-has_hfs_crtp")==0) {
if(i + 2 >= end_idx)
goto not_enough_arguments;
i+= 2;
ret= Xorriso_hfsplus_file_creator_type(xorriso, "", NULL,
argv[i - 1], argv[i], 3);
if(ret <= 0)
{ret= 0; goto ex;}
ret= Findjob_set_crtp_filter(job, argv[i - 1], argv[i], 0);
if(ret <= 0) {
sprintf(xorriso->info_text, "-findi: cannot setup -has_hfs_crtp test");
goto sorry_ex;
}
} else if(strcmp(argv[i], "-has_hfs_bless")==0) {
if(i + 1 >= end_idx)
goto not_enough_arguments;
i+= 1;
ret= Findjob_set_bless_filter(xorriso, job, argv[i], 0);
if(ret <= 0) {
sprintf(xorriso->info_text, "-findi: cannot setup -has_hfs_bless test");
goto sorry_ex;
}
} else if(strcmp(argv[i], "-bad_outname")==0) {
if(i + 1 >= end_idx)
goto not_enough_arguments;
i+= 1;
name_space= Xorriso_determine_name_space(xorriso, argv[i], 0);
if(name_space < 0) {
ret= 0; goto sorry_ex;
}
ret= Findjob_set_num_filter(job, 21, name_space, 0, 0);
if(ret <= 0) {
sprintf(xorriso->info_text, "-findi: cannot setup -bad_outname test");
goto sorry_ex;
}
} else if(strcmp(argv[i], "-true") == 0) {
ret= Findjob_set_false(job, -1, 0);
} else if(strcmp(argv[i], "-false") == 0) {
ret= Findjob_set_false(job, 1, 0);
} else if(strcmp(argv[i], "-decision") == 0) {
if(i+1>=end_idx)
goto not_enough_arguments;
i++;
ret= Findjob_set_decision(job, argv[i], 0);
} else if(strcmp(argv[i], "-prune") == 0) {
ret= Findjob_set_prune(job, 0);
} else if(strcmp(argv[i], "-sub") == 0 || strcmp(argv[i], "(") == 0) {
ret= Findjob_open_bracket(job, 0);
} else if(strcmp(argv[i], "-subend") == 0 || strcmp(argv[i], ")") == 0) {
ret= Findjob_close_bracket(job, 0);
} else if(strcmp(argv[i], "-not") == 0 || strcmp(argv[i], "!") == 0) {
ret= Findjob_not(job, 0);
} else if(strcmp(argv[i], "-and") == 0 || strcmp(argv[i], "-a") == 0) {
ret= Findjob_and(job, 0);
} else if(strcmp(argv[i], "-or") == 0 || strcmp(argv[i], "-o") == 0) {
ret= Findjob_or(job, 0);
} else if(strcmp(argv[i], "-if") == 0) {
ret= Findjob_if(job, 0);
} else if(strcmp(argv[i], "-then") == 0) {
ret= Findjob_then(job, 0);
} else if(strcmp(argv[i], "-else") == 0) {
ret= Findjob_else(job, 0);
} else if(strcmp(argv[i], "-elseif") == 0) {
ret= Findjob_elseif(job, 0);
} else if(strcmp(argv[i], "-endif") == 0) {
ret= Findjob_endif(job, 0);
} else if(strcmp(argv[i], "-sort_lba") == 0) {
flag|= 8;
/* If an operator is open: insert a -true test, else do nothing */
ret= Findjob_set_false(job, -1, 1);
if(ret == 2)
ret= 1;
} else if(strcmp(argv[i], "-exec")==0) {
if(i+1>=end_idx) {
not_enough_exec_arguments:;
sprintf(xorriso->info_text,
"-find[ix]: not enough parameters with -exec ");
Text_shellsafe(argv[i], xorriso->info_text, 1);
goto sorry_ex;
}
i++;
cpt= argv[i];
if(*cpt=='-')
cpt++;
if(strcmp(cpt, "echo")==0) {
Findjob_set_action_target(job, 0, NULL, 0);
} else if(strcmp(cpt, "rm")==0) {
Findjob_set_action_target(job, 1, NULL, 0);
deleter= 1;
} else if(strcmp(cpt, "rm_r")==0) {
Findjob_set_action_target(job, 2, NULL, 0);