
/* Command line oriented batch and dialog tool which creates, loads,
   manipulates and burns ISO 9660 filesystem images.

   Copyright 2007-2010 Thomas Schmitt, <scdbackup@gmx.net>

   Provided under GPL version 2 or later.

   This file contains inner declarations of xorriso.
   The public interface is in xorriso.h
*/


/* For now, #ifdef Xorriso_is_xorriso_selF  has no meaning.
   But it is already now to be set only by the xorriso.c module.
*/

#ifndef Xorriso_private_includeD
#define Xorriso_private_includeD yes

/** The source code release timestamp */
#include "xorriso_timestamp.h"
#ifndef Xorriso_timestamP
#define Xorriso_timestamP "-none-given-"
#endif

/** The binary build timestamp is to be set externally by the compiler
    or by a macro definition in xorriso_buildstamp.h.
*/
#include "xorriso_buildstamp.h"
#ifndef Xorriso_build_timestamP
#define Xorriso_build_timestamP "-none-given-"
#endif

#include <regex.h>


#define Smem_malloC malloc
#define Smem_freE free
#define SfileadrL 4096

struct LinkiteM;          /* Trace of hops during symbolic link resolution */
struct ExclusionS;        /* List of -not_* conditions */
struct PermiteM;          /* Stack of temporarily altered access permissions */
struct SpotlisT;          /* List of intervals with different read qualities */
struct CheckmediajoB;     /* Parameters for Xorriso_check_media() */
struct SectorbitmaP;      /* Distiniction between valid and invalid sectors */


/* maximum number of history lines to be reported with -status:long_history */
#define Xorriso_status_history_maX 100

/* <<< ??? */
/* try to catch signals and ignore them during abort handling */
#define Xorriso_abort_handler_defaulT (1|(2<<4))


/** The list of startup file names */
#define Xorriso_rc_nuM 4


/* Default setting for the size limit of single data files:
   100 extents with 4 GB - 2 kB each = 400 GB - 200 kB
*/
#define Xorriso_default_file_size_limiT \
        (((off_t) 400) * ((off_t) 1024*1024*1024) - (off_t) 204800)


struct XorrisO { /* the global context of xorriso */

 int libs_are_started;

 /* source */
 char progname[SfileadrL];
 char initial_wdx[SfileadrL];
 int no_rc;

 /* Command line argument emulations:
      0=xorriso mode
      1=mkisofs mode
      2=cdrecord mode
 */
 int argument_emulation;

 /** List of startupfiles */
 char rc_filenames[Xorriso_rc_nuM][SfileadrL];
 int rc_filename_count;

 char wdi[SfileadrL];
 char wdx[SfileadrL];
 int did_something_useful;

 int add_plainly;
 off_t split_size;

 char list_delimiter[81];

 /* >>> put libisofs aspects here <<< */

 int ino_behavior; /* bit0= at image load time:
                            Do not load PX inode numbers but generate new
                            unique ones for all loaded IsoNode.
                      bit1= at image generation time:
                            Do not consolidate suitable nodes to hardlinks.
                      bit2= at restore-to-disk time:
                            Do not consolidate suitable nodes to hardlinks.
                      bit3= with update:
                            Do not try to detect hardlink splits and joinings.
                      bit4= with extract:
                            Do not create or use hln arrays if sort_lba_on
                    */

 int do_joliet;

 int do_aaip; /* bit0= ACL in
                 bit1= ACL out
                 bit2= EA in
                 bit3= EA out
                 bit4= record dev,inode per node, isofs_st_out in root
                 bit5= check dev,inode,isofs_st_in
                 bit6= omit content check if bit5 check is conclusive
                 bit7= omit dev check with bit5
                 bit8= store output charset in xattr "isofs.cs"
                 bit9= allow to set input charset from xattr "isofs.cs"
              */

 int do_md5;  /* bit0= read MD5 array
                 bit1= write session MD5
                 bit2= write MD5 for each data file
                 bit3= make file content stability check by double reading
                 bit4= use recorded MD5 as proxy of ISO file
               */

 char scdbackup_tag_name[81];
 char scdbackup_tag_time[19];
 char scdbackup_tag_written[512];
 char scdbackup_tag_listname[SfileadrL];

 int relax_compliance;        /* opaque bitfield to be set by xorrisoburn */
 int do_follow_pattern;
 int do_follow_param;
 int do_follow_links;
 int follow_link_limit;
 int do_follow_mount;
 int do_global_uid;
 uid_t global_uid;
 int do_global_gid;
 gid_t global_gid;
 int do_global_mode;
 mode_t global_dir_mode;
 mode_t global_file_mode;

 struct Xorriso_lsT *filters;
 int filter_list_closed;

 int zlib_level;
 int zlib_level_default;
 int zisofs_block_size;
 int zisofs_block_size_default;
 int zisofs_by_magic;

 int do_overwrite; /* 0=off, 1=on, 2=nondir */
 int do_reassure;  /* 0=off, 1=on, 2=tree */

 char volid[33];
 int volid_default;
 char loaded_volid[33];
 char assert_volid[SfileadrL];
 char assert_volid_sev[80];

 char publisher[129];
 char application_id[129];
 char system_id[33];
 char volset_id[129];

 char session_logfile[SfileadrL];
 int session_lba;
 int session_blocks;

 /* >>> put libburn/isoburn aspects here */

 struct Xorriso_lsT *drive_blacklist;
 struct Xorriso_lsT *drive_greylist;
 struct Xorriso_lsT *drive_whitelist;

 int toc_emulation_flag; /* bit0= bit3 for isoburn_drive_aquire()
                                  scan -ROM profiles for ISO sessions
                            bit1= bit4 for isoburn_drive_aquire()
                                  do not emulate TOC on overwriteable media
                            bit2= bit7 for isoburn_drive_aquire()
                                  pretend any media to be -ROM
                         */

 int image_start_mode;  /* From what address to load the ISO image
                           bit0-15= addressing mode
                            0= automatic lba as deduced from media
                            1= value is session number
                            2= value is track number
                            3= value is lba
                           bit16= with mode 3 : value is possibly 16 too high.
                                  Let isoburn_set_msc1() adjust it.
                           bit30= interference with normal msc1 processing
                                  is enabled. Without this bit,
                                  isoburn_set_msc1() will not be called.
                           bit31= image loading has happened,
                                  setting is kept for rollback only.
                                  Always apply as 0=auto.
                        */
 char image_start_value[81]; /* value according image_start_mode */

 int drives_exclusive;   /* burn_preset_device_open() param exclusive */

 int do_calm_drive;      /* bit0= calm down drive after aquiring it */

 char indev[SfileadrL];
 void *in_drive_handle;  /* interpreted only by xorrisoburn.c */
 void *in_volset_handle; /* interpreted only by xorrisoburn.c */
 char *in_charset;       /* The charset to interpret the filename bytes */
 int indev_is_exclusive;

 time_t isofs_st_out;    /* A time point at least 1 second before image
                            composition began. To be stored with image as
                            xattr "isofs.st". */
 time_t isofs_st_in;     /* That time point as read from "isofs.st" of the
                            loaded image. */

 int volset_change_pending; /* whether -commit would make sense */
 int no_volset_present;     /* set to 1 on first failure */

 struct CheckmediajoB *check_media_default;
 int check_media_bad_limit;      /* values defined as Xorriso_read_quality_* */
 struct SectorbitmaP *in_sector_map; /* eventual sector validity bitmap */


 char outdev[SfileadrL];
 void *out_drive_handle; /* interpreted only by xorrisoburn.c */
 char *out_charset;      /* The charset to produce the filename bytes for */
 int dev_fd_1; /* The fd which substitutes for /dev/fd/1 and is
                     connected to externaly perveived stdout.
                  */
 int outdev_is_exclusive;

 int grow_blindly_msc2; /* if >= 0 this causes growing from drive to drive.
                           The value is used as block address offset for
                           image generation. Like in: mkisofs -C msc1,msc2
                         */

 int ban_stdio_write;
 int do_dummy;
 int do_close;
 int speed;     /* in libburn units : 1000 bytes/second , 0 = Max, -1 = Min */
 int fs;        /* fifo size in 2048 byte chunks : at most 1 GB */
 int padding;   /* number of bytes to add after ISO 9660 image */

 int alignment; /* if > 0 : image size alignment in 2048 byt blocks */
                /* <<< not sure whether to keep this after libisofs will have
                       learned to pad up MBR images to full MB */

 int do_stream_recording; /* 0=no, 1=yes, 2=for data, not for dir
                             >=16 means yes with number as start LBA  */

 int dvd_obs;                 /* DVD write chunk size: 0, 32k or 64k */
 int stdio_sync;              /* stdio fsync interval: -1, 0, >=32 */

 int keep_boot_image;
 int patch_isolinux_image;
 char boot_image_bin_path[SfileadrL];
 int boot_image_emul; /* 0=no emulation
                        (1=emulation as hard disk)
                        (2=emulation as floppy)
                      */
 char boot_image_cat_path[SfileadrL];
 off_t boot_image_load_size;
 int boot_image_isohybrid; /* 0=off , 1=auto , 2=on , 3=force */

 /* LBA of boot image after image loading */
 int loaded_boot_bin_lba;
 /* Path of the catalog node after image loading */
 char loaded_boot_cat_path[SfileadrL];

 /* XORRISO options */
 int allow_graft_points;

 int allow_restore; /* -1=permanently disallowed
                        0=disallowed, 1=allowed, 2=device files allowed */
 int do_concat_split;  /* 1= restore complete split file directories as
                             regular files
                        */
 int do_auto_chmod;    /* 1= eventually temporarily open access permissions
                             of self-owned directories during restore
                        */
 int do_restore_sort_lba; /* 1= restore via node_array rather than via
                                tree traversal. Better read performance,
                                no directory mtime restore, needs do_auto_chmod
                           */
 int mount_opts_flag; /* bit0= "shared" = not "exclusive"
                               Try to emit non-exclusive mount command.
                               Do not give up drives.
                               Linux: use loop device even on block devices
                               in order to circumvent the ban to mount a
                               device twice (with different sbsector=)
                               FreeBSD: ?
                       */

 int dialog;  /* 0=off , 1=single-line , 2=multi-line */

 int bsl_interpretation;
                     /* whether to run input through Sfile_bsl_interpreter():
                        bit0-1= dialog and quoted file reading
                          0= no interpretation, leave unchanged
                          1= only inside double quotes
                          2= outside single quotes
                          3= everywhere
                        bit2-3= reserved as future expansion of bit0-1
                        bit4= interpretation within program start arguments
                        bit5= perform backslash encoding with results
                        bit6= perform backslash encoding with info texts
                     */

 /* Pattern matching facility. It still carries legacy from scdbackup/askme.c
    but is fully functional for xorriso.
 */
 int search_mode;
 /* 0= start text
    1= fgrep , 
    2= regular expression
    3= (eventually structured) shell parser expression
    4= shell parser expression for leaf name
 */

 int structured_search;
 /* 0= flat text search
    1= '/' is a significant separator that cannot be matched by wildcards
    ( 2= like 1 : but report only occurence in tree, no payload, no location )
    ( 3= like 2 : but report first content level of matching directories )
    4= actually not structured but unique find mode (with search_mode 4)
 */

 int do_iso_rr_pattern; /* 0=off, 1=on, 2=ls */
 int do_disk_pattern;   /* 0=off, 1=on, 2=ls */

 int temp_mem_limit;

 off_t file_size_limit;

 struct ExclusionS *disk_exclusions;
 int disk_excl_mode; /* bit0= on (else off)
                        bit1= parameter too (else rekursion only)
                        bit2= whole subtree banned (else only exact path)
                        bit3= when comparing ignore excluded files rather
                              than to treat them as truely missing on disk
                     */

 int use_stdin; /* use raw stdin even if readline support is compiled */
 int result_page_length;
 int result_page_width;
 char mark_text[SfileadrL]; /* ( stdout+stderr, M: ) */
 int packet_output;
 char logfile[4][SfileadrL];
 FILE *logfile_fp[4];
 FILE *pktlog_fp;
 struct Xorriso_lsT *result_msglists[Xorriso_max_outlist_stacK];
 struct Xorriso_lsT *info_msglists[Xorriso_max_outlist_stacK];
 int msglist_flags[Xorriso_max_outlist_stacK]; /* bit0= result is redirected
                                                  bit1= info is redirected
                                               */
 int msglist_stackfill;

 int status_history_max; /* for -status long_history */
 
 /* 0= no logging of SCSI commands, 1= to stderr */
 int scsi_log;

 char report_about_text[20];
 int report_about_severity;
 int library_msg_direct_print;
 char abort_on_text[20];
 int abort_on_severity; /* A severity rank number as threshold */
 int problem_status; /* Severity rank number. 0= no abort condition present */
 char problem_status_text[20];

 char errfile_log[SfileadrL]; /* for -errfile_log */
 int errfile_mode; /* bit0= marked */
 FILE *errfile_fp;

 int img_read_error_mode; /* 0=best_effort , 1=failure , 2=fatal */
 int extract_error_mode; /* 0=best_effort , 1=keep , 2=delete */

 char return_with_text[20];
 int return_with_severity;
 int return_with_value;
 int eternal_problem_status;
 char eternal_problem_status_text[20];

 /* temporary search facilities */
 regex_t *re;
 regmatch_t match[1]; 
 char **re_constants;
 int re_count;
 int re_fill;
 char reg_expr[2*SfileadrL];

 /* run state */
 int run_state; /* 0=preparing , 1=writing image */
 int is_dialog;
 int bar_is_fresh;
 char pending_option[SfileadrL]; /* eventual option entered at page prompt */
 int request_to_abort; /* abort a single operation like -ls, not the program */
 int request_not_to_ask; /* suppress reassure and pager */
 double idle_time;
 int re_failed_at; /* mismatch position with structured_search */
 int prepended_wd;
 double insert_count;
 double insert_bytes;
 double error_count; /* double will not roll over */

 /* pacifiers */
 int pacifier_style; /* 0= xorriso, 1=mkisofs 2=cdrecord */
 double pacifier_interval;
 double start_time;
 double last_update_time;
 /* optional global counters for brain reduced callback functions */
 off_t pacifier_count;
 off_t pacifier_total;
 off_t pacifier_byte_count; /* auxiliary counter for data bytes */

 void *pacifier_fifo;

 int find_compare_result; /* 1=everything matches , 0=mismatch , -1=error */ 
 int find_check_md5_result; /* bit0= seen mismatch
                               bit1= seen error
                               bit2= seen data file without MD5
                               bit3= seen match
                             */

 /* Tree node collection and LBA sorting facility */
 int node_counter;
 int node_array_size;
 void **node_array;
 struct Xorriso_lsT *node_disk_prefixes;
 struct Xorriso_lsT *node_img_prefixes;

 /* Hardlink matching at restore time memorizes hardlink target paths.
    Array of nodes sorted by LBA. */
 int hln_count;
 void **hln_array;
 void **hln_targets;
 int hln_change_pending; /* whether a change was made since hln creation */

 /* >>> this should count all temp_mem and thus change its name */
 off_t node_targets_availmem;

 /* Hardlink matching at update time:
    Array of all nodes in the tree, sorted by disk dev,ino.
    Bitmap of nodes which possibly got new hardlink siblings.
    List of involved disk-iso path pairs. */
 int di_count;
 void **di_array;
 char *di_do_widen;
 struct Xorriso_lsT *di_disk_paths;
 struct Xorriso_lsT *di_iso_paths;

 struct PermiteM *perm_stack; /* Temporarily altered dir access permissions */

 /* result (stdout, R: ) */
 char result_line[10*SfileadrL];
 int result_line_counter;
 int result_page_counter;
 int result_open_line_len;


 /* info (stderr, I:) */
 char info_text[10*SfileadrL];

};


int Xorriso_prepare_regex(struct XorrisO *xorriso, char *adr, int flag);

int Xorriso_result(struct XorrisO *xorriso, int flag);

int Xorriso_info(struct XorrisO *xorriso, int flag);

int Xorriso_request_confirmation(struct XorrisO *xorriso, int flag);

/* @return 0=match , else no match
*/
int Xorriso_regexec(struct XorrisO *xorriso, char *to_match, int *failed_at,
                    int flag);

int Xorriso_prepare_expansion_pattern(struct XorrisO *xorriso, char *pattern,
                                      int flag);

int Xorriso__mode_to_perms(mode_t st_mode, char perms[11], int flag);

int Xorriso_much_too_long(struct XorrisO *xorriso, int len, int flag);

int Xorriso_check_temp_mem_limit(struct XorrisO *xorriso, off_t mem, int flag);

int Xorriso_eval_nonmatch(struct XorrisO *xorriso, char *pattern,
                          int *nonconst_mismatches, off_t *mem, int flag);

/* @param flag bit0= a match count !=1 is a SORRY event
*/
int Xorriso_check_matchcount(struct XorrisO *xorriso,
                int count, int nonconst_mismatches, int num_patterns,
                char **patterns, int flag);

int Xorriso_no_pattern_memory(struct XorrisO *xorriso, off_t mem, int flag);

int Xorriso_alloc_pattern_mem(struct XorrisO *xorriso, off_t mem,
                              int count, char ***filev, int flag);

/* @param flag bit0= count results rather than storing them
   @return <=0 error , 1 is root (end processing) ,
                       2 is not root (go on processing)
*/
int Xorriso_check_for_root_pattern(struct XorrisO *xorriso,
              int *filec, char **filev, int count_limit, off_t *mem, int flag);

/* @param flag bit0= prepend wd only if name does not begin by '/'
               bit2= prepend wd (automatically done if wd[0]!=0)
*/
int Xorriso_make_abs_adr(struct XorrisO *xorriso, char *wd, char *name,
                             char adr[], int flag);

/* @param flag bit0= count result rather than storing it
               bit1= unexpected change of number is a FATAL event
*/
int Xorriso_register_matched_adr(struct XorrisO *xorriso,
                               char *adr, int count_limit,
                               int *filec, char **filev, off_t *mem, int flag);

int Xorriso_format_ls_l(struct XorrisO *xorriso, struct stat *stbuf, int flag);

/* @param flag bit0= simple readlink(): no normalization, no multi-hop
*/
int Xorriso_resolve_link(struct XorrisO *xorriso,
                     char *link_path, char result_path[SfileadrL], int flag);

/* @param flag bit0= for Xorriso_msgs_submit: use pager
*/
int Xorriso_hop_link(struct XorrisO *xorriso, char *link_path,
                   struct LinkiteM **link_stack, struct stat *stbuf, int flag);

/* reg_expr should be twice as large as bourne_expr ( + 2 to be exact) */
/* return: 2= bourne_expr is surely a constant */
int Xorriso__bourne_to_reg(char bourne_expr[], char reg_expr[], int flag);

int Xorriso_no_malloc_memory(struct XorrisO *xorriso, char **to_free,
                             int flag);

int Xorriso_pacifier_reset(struct XorrisO *xorriso, int flag);

/* This call is to be issued by long running workers in short intervals.
   It will check whether enough time has elapsed since the last pacifier
   message and eventually issue an update message.
   @param what_done  A sparse description of the action, preferrably in past 
                     tense. E.g. "done" , "files added".
   @param count The number of objects processed so far.
                Is ignored if <=0.
   @param todo  The number of objects to be done in total.
                Is ignored if <=0.
   @param current_object A string telling the object currently processed.
                         Ignored if "".
   @param flag  bit0= report unconditionally, no time check
*/
int Xorriso_pacifier_callback(struct XorrisO *xorriso, char *what_done,
                              off_t count, off_t todo, char *current_object,
                              int flag);

int Xorriso_pfx_disk_path(struct XorrisO *xorriso, char *iso_path,
                          char *iso_prefix, char *disk_prefix,
                          char disk_path[SfileadrL], int flag);

/* @param boss_iter Opaque handle to be forwarded to actions in ISO image
                    Set to NULL if calling this function from outside ISO world
   @param flag bit0= update rather than compare
*/
int Xorriso_find_compare(struct XorrisO *xorriso, void *boss_iter,
                         char *iso_path, char *iso_prefix, char *disk_prefix, 
                         int flag);

/* @param boss_iter Opaque handle to be forwarded to actions in ISO image
                    Set to NULL if calling this function from outside ISO world
*/
int Xorriso_update_interpreter(struct XorrisO *xorriso, void *boss_iter,
                               int compare_result, char *disk_path,
                               char *iso_rr_path, int flag);

int Xorriso_path_is_excluded(struct XorrisO *xorriso, char *path, int flag);

/* @param flag bit0= long format
               bit1= do not print count of nodes
               bit2= du format
               bit3= print directories as themselves (ls -d)
*/
int Xorriso_lsx_filev(struct XorrisO *xorriso, char *wd,
                      int filec, char **filev, off_t boss_mem, int flag);

/*
   @param flag >>> bit0= remove whole sub tree: rm -r
               bit1= remove empty directory: rmdir
               bit2= recursion: do not reassure in mode 2 "tree"
               bit3= this is for overwriting and not for plain removal
               bit4= count deleted files in xorriso->pacifier_count
               bit5= with bit0 only remove directory content, not the directory
   @return   <=0 = error
               1 = removed leaf file object
               2 = removed directory or tree
               3 = did not remove on user revocation
*/
int Xorriso_rmx(struct XorrisO *xorriso, off_t boss_mem, char *path, int flag);


/* @param flag bit7= return 4 if restore fails from denied permission
                     do not issue error message
   @return <=0 failure , 1 success ,
           4 with bit7: permission to create file was denied
*/ 
int Xorriso_make_tmp_path(struct XorrisO *xorriso, char *orig_path,
                          char *tmp_path, int *fd, int flag);

/* @param flag bit0= path is a directory
               bit2= recursion: do not reassure in mode 2 "tree"
               bit3= this is for overwriting and not for plain removal
*/
int Xorriso_reassure_restore(struct XorrisO *xorriso, char *path, int flag);


/* @param flag bit0= change regardless of xorriso->do_auto_chmod
               bit1= desired is only rx
*/
int Xorriso_auto_chmod(struct XorrisO *xorriso, char *disk_path, int flag);

int Xorriso_make_accessible(struct XorrisO *xorriso, char *disk_path,int flag);

/* @param flag bit0= prefer to find a match after *img_prefixes
                     (but deliver img_prefixes if no other can be found)
*/
int Xorriso_make_restore_path(struct XorrisO *xorriso,
         struct Xorriso_lsT **img_prefixes, struct Xorriso_lsT **disk_prefixes,
         char img_path[SfileadrL], char disk_path[SfileadrL], int flag);

int Xorriso_restore_make_hl(struct XorrisO *xorriso,
                            char *old_path, char *new_path, int flag);


int Xorriso_protect_stdout(struct XorrisO *xorriso, int flag);


/* @param flag bit0= mark untested areas as valid
*/
int Xorriso_spotlist_to_sectormap(struct XorrisO *xorriso,
                                  struct SpotlisT *spotlist,
                                  int read_chunk,
                                  struct SectorbitmaP **map,
                                  int flag);

int Xorriso_toc_to_string(struct XorrisO *xorriso, char **toc_text, int flag);


/* @param flag bit0+1= what to aquire after giving up outdev
                       0=none, 1=indev, 2=outdev, 3=both
*/
int Xorriso_reaquire_outdev(struct XorrisO *xorriso, int flag);


/* Opens the -check_media data copy in for reading and writing
*/
int Xorriso_open_job_data_to(struct XorrisO *xorriso,
                             struct CheckmediajoB *job, int flag);

int Xorriso_no_findjob(struct XorrisO *xorriso, char *cmd, int flag);


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);


/* @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 Xorriso_is_in_patternlist(struct XorrisO *xorriso,
                        struct Xorriso_lsT *patternlist, char *path, int flag);

char *Xorriso_get_pattern(struct XorrisO *xorriso,
                         struct Xorriso_lsT *patternlist, int index, int flag);


/* Normalize ACL and sort apart "access" ACL from "default" ACL.
 */
int Xorriso_normalize_acl_text(struct XorrisO *xorriso, char *in_text,
                    char **access_acl_text, char **default_acl_text, int flag);

int Xorriso_path_setfattr(struct XorrisO *xorriso, void *in_node, char *path,
                       char *name, size_t value_length, char *value, int flag);

int Xorriso_status_result(struct XorrisO *xorriso, char *filter, FILE *fp,
                          int flag);

int Xorriso_compare_2_files(struct XorrisO *xorriso, char *disk_adr,
                            char *iso_adr, char *adr_common_tail,
                            int *result, int flag);

int Xorriso_report_md5_outcome(struct XorrisO *xorriso, char *severity, 
                               int flag);

int Xorriso_append_scdbackup_record(struct XorrisO *xorriso, int flag);

int Xorriso_may_burn(struct XorrisO *xorriso, int flag);


int Sfile_str(char target[SfileadrL], char *source, int flag);

double Sfile_microtime(int flag);

int Sfile_add_to_path(char path[SfileadrL], char *addon, int flag);

int Sfile_scale(double value, char *result, int siz, double thresh, int flag);

int Sfile_destroy_argv(int *argc, char ***argv, int flag);

/*
 bit0= do not ignore trailing slash
 bit1= do not ignore empty components (other than the empty root name)
*/
int Sfile_count_components(char *path, int flag);

/*
 @param flag
 bit0= return -1 if file is missing
 bit1= return a hardlink with siblings as type 5
 bit2= evaluate eventual link target rather than the link object itself
 bit3= return a socket or a char device as types 7 or 8 rather than 0
 @return
  0=unknown
  1=regular
  2=directory
  3=symbolic link
  4=named pipe
  5=multiple hardlink (with bit1)
  6=block device
  7=socket (with bit3)
  8=character device (with bit3)
*/
int Sfile_type(char *filename, int flag);

/* @param flag bit0= only encode inside quotes
               bit1= encode < 32 outside quotes except 7, 8, 9, 10, 12, 13
               bit2= encode in any case above 126
               bit3= encode in any case shellsafe:
                     <=42 , 59, 60, 62, 63, 92, 94, 96, >=123
*/
int Sfile_bsl_encoder(char **result, char *text, size_t text_len, int flag);

int Sfile_argv_bsl(int argc, char ***argv, int flag);


struct Xorriso_lsT {
  char *text;
  struct Xorriso_lsT *prev,*next;
};

/** Create a new list item with arbitrary byte content.
    @param lstring  The newly created object or NULL on failure
    @param data     An array of bytes to be copied into the new object
    @param data_len Number of bytes to be copied
    @param link     Xorriso_lsT object to which the new object shall be linked
    @param flag Bitfield for control purposes
                bit0= insert before link rather than after it
                bit1= do not copy data (e.g. because *data is invalid)
                bit2= attach data directly by pointer rather than by copying
    @return <=0 error, 1 ok
*/
int Xorriso_lst_new_binary(struct Xorriso_lsT **lstring, char *data,
                           int data_len, struct Xorriso_lsT *link, int flag);


/** Create a new list item with a 0-terminated text as content.
    @param lstring  The newly created object or NULL on failure
    @param text     A 0-terminated array of bytes
    @param link     Xorriso_lsT object to which the new object shall be linked
    @param flag     see Xorriso_lst_new_binary
    @return <=0 error, 1 ok
*/
int Xorriso_lst_new(struct Xorriso_lsT **lstring, char *text,
                    struct Xorriso_lsT *link, int flag);


/** Create a new list item at the end of a given list.
    @param entry    Contains as input a pointer to a pointer to any existing
                    list item. As output this list item pointer may be
                    changed to the address of the new list item:
                    if ((*entry == 0) || (flag & 1))
    @param data     An array of bytes to be copied into the new object
    @param data_len Number of bytes to be copied
    @param flag     Bitfield for control purposes
                    bit0= Return new object address in *entry
                    bit1= do not copy data (e.g. because *data is invalid)
                    bit2= attach data directly by pointer rather than by copying
    @return <=0 error, 1 ok
*/
int Xorriso_lst_append_binary(struct Xorriso_lsT **entry,
                              char *data, int data_len, int flag);


/** Destroy a single list item and connect its eventual list neighbors.
    @param lstring  pointer to the pointer to be freed and set to NULL
    @param flag     unused yet, submit 0
    @return 0= *lstring was alredy NULL, 1= ok
*/
int Xorriso_lst_destroy(struct Xorriso_lsT **lstring, int flag);


struct Xorriso_lsT *Xorriso_lst_get_next(struct Xorriso_lsT *entry, int flag);

struct Xorriso_lsT *Xorriso_lst_get_prev(struct Xorriso_lsT *entry, int flag);

char *Xorriso_lst_get_text(struct Xorriso_lsT *entry, int flag);

int Xorriso_lst_detach_text(struct Xorriso_lsT *entry, int flag);


char *Text_shellsafe(char *in_text, char *out_text, int flag);

int Sort_argv(int argc, char **argv, int flag);

/* @param flag bit0= single letters */
char *Ftypetxt(mode_t st_mode, int flag);

/* @param flag bit0=with year and seconds
               bit1=timestamp format YYYY.MM.DD.hhmmss
*/
char *Ftimetxt(time_t t, char timetext[40], int flag);

int System_uname(char **sysname, char **release, char **version, 
                 char **machine, int flag);


struct DirseQ;

int Dirseq_new(struct DirseQ **o, char *adr, int flag);

int Dirseq_destroy(struct DirseQ **o, int flag);

int Dirseq_next_adr(struct DirseQ *o, char reply[SfileadrL], int flag);


int Linkitem_reset_stack(struct LinkiteM **o, struct LinkiteM *to, int flag);




#define Xorriso_findjob_on_expR yes

#ifdef Xorriso_findjob_on_expR

/*
   A single Testnode.
*/
struct ExprtesT {

 struct FindjoB *boss;

 int invert;  /* 0=normal  1=invert result */ 

 /*
   0= -false (with invert : -true)
   1= -name char *arg1 (regex_t in *arg2)
   2= -type char *arg1
   3= -damaged
   4= -lba_range int *arg1 int *arg2
   5= -has_acl
   6= -has_xattr
   7= -has_aaip
   8= -has_filter
   9= -wanted_node IsoNode *arg1 (for internal use, arg1 not allocated)
  10= -pending_data
  11= -decision char *arg1 ("yes", "no")
  12= -prune
  13= -wholename char *arg1 (regex_t in *arg2)
  14= -has_any_xattr
  15= -has_md5
 */
 int test_type;

 void *arg1;
 void *arg2;

};


/* 
   A computational node.
   A tree of these nodes forms the expression.
   Sequences of AND/OR operations form branches, brackets spawn new branches,
   NOT inverts node's test resp. subtree result.
*/
struct ExprnodE {

 struct ExprnodE *up;

 char origin[8];

  /* Operators */
 int invert;  /* 0=normal  1=invert own result (subtree or test, but not op) */ 

 int assoc; /*
                0= left : compute own value, combine with left value,
                          compute right value, combine with current value
                1= right: compute own value, compute right value, 
                          combine own and right, combine with left value
             */

 int use_shortcuts; /* 0= evaluate all tests of -and and -or,
                       1= evaluate only until the combined result is known
                     */

 struct ExprnodE *left;
 int left_op; /* 0=OR , 1=AND */
  
 struct ExprnodE *right;
 int right_op; /* see left_op */

 /* Brackets : a pointer to the first node in a subchain */ 
 struct ExprnodE *sub; 

 int is_if_then_else;
 struct ExprnodE *true_branch;
 struct ExprnodE *false_branch;

 /* elementary test : if sub!=NULL , test is ignored */
 struct ExprtesT *test;

 /* Result */
 int own_value;
 int composed_value;

};


struct FindjoB {

 char *start_path;

 struct ExprnodE *test_tree;

 struct ExprnodE *cursor;
 int invert;  /* 0=normal  1=set invert-property for next new test node */
 int use_shortcuts;

 /* 0= echo
    1= rm (also rmdir)
    2= rm_r
>>> 3= mv target
    4= chown user
    5= chgrp group
    6= chmod mode_and mode_or
    7= alter_date type date
    8= lsdl
    9= chown_r user
   10= chgrp_r group
   11= chmod_r mode_and mode_or
   12= alter_date_r type date
   13= find
   14= compare disk_equivalent_of_start_path
   15= in_iso iso_rr_equivalent_of_start_path
   16= not_in_iso iso_rr_equiv
   17= update disk_equiv
   18= add_missing iso_rr_equiv
   19= empty_iso_dir iso_rr_equiv
   20= is_full_in_iso iso_rr_equiv
   21= report_damage
   22= report_lba
   23= internal: memorize path of last matching node in found_path
   24= getfacl
   25= setfacl access_acl default_acl
   26= getfattr
   27= setfattr
   28= set_filter name
   29= show_stream
   30= internal: count by xorriso->node_counter
   31= internal: register in xorriso->node_array
   32= internal: widen_hardlinks disk_equiv: update nodes marked in di_do_widen
   33= get_any_xattr
   34= get_md5
   35= check_md5
   36= make_md5
 */
 int action;
 int prune;

 /* action specific parameters */
 char *target;
 char *text_2;
 uid_t user;
 gid_t group;
 mode_t mode_and, mode_or;
 int type; /* see Xorriso_set_time flag */
 time_t date;
 char *found_path;
 struct FindjoB *subjob;

 /* Errors */
 char errmsg[4096];
 int errn; /*
             >0 = UNIX errno
             -1 = close_bracket: no bracket open 
             -2 = binary operator or closing bracket expected
             -3 = unexpected binary operator or closing bracket
             -4 = unsupported command
             -5 = -then -elseif -else -endif without -if or at wrong place
           */
};


int Exprtest_match(struct XorrisO *xorriso, struct ExprtesT *ftest,
                   void *node_pt, char *name, char *path,
                   struct stat *boss_stbuf, struct stat *stbuf, int flag);


int Exprnode_destroy(struct ExprnodE **fnode, int flag);

int Exprnode_tree_value(struct XorrisO *xorriso, struct ExprnodE *fnode,
                        int left_value, void *node, char *name, char *path,
                        struct stat *boss_stbuf, struct stat *stbuf, int flag);


int Findjob_new(struct FindjoB **o, char *start_path, int flag);

int Findjob_destroy(struct FindjoB **o, int flag);

int Findjob_set_start_path(struct FindjoB *o, char *start_path, int flag);

int Findjob_get_start_path(struct FindjoB *o, char **start_path, int flag);

int Findjob_set_commit_filter_2(struct FindjoB *o, int flag);

int Findjob_set_lba_range(struct FindjoB *o, int start_lba, int count, 
                          int flag);

int Findjob_set_wanted_node(struct FindjoB *o, void *wanted_node, int flag);

int Findjob_set_decision(struct FindjoB *o, char *decision, int flag);

int Findjob_open_bracket(struct FindjoB *job, int flag);

int Findjob_close_bracket(struct FindjoB *job, int flag);

int Findjob_not(struct FindjoB *job, int flag);

int Findjob_and(struct FindjoB *job, int flag);

int Findjob_or(struct FindjoB *job, int flag);

int Findjob_if(struct FindjoB *job, int flag);

int Findjob_then(struct FindjoB *job, int flag);

int Findjob_else(struct FindjoB *job, int flag);

int Findjob_elseif(struct FindjoB *job, int flag);

int Findjob_endif(struct FindjoB *job, int flag);

int Findjob_test_2(struct XorrisO *xorriso, struct FindjoB *o, 
                   void *node, char *name, char *path,
                   struct stat *boss_stbuf, struct stat *stbuf, int flag);

int Findjob_set_action_found_path(struct FindjoB *o, int flag);

/* @param flag bit0= recursive
*/
int Findjob_set_action_target(struct FindjoB *o, int action, char *target,
                              int flag);
int Findjob_get_action(struct FindjoB *o, int flag);

int Findjob_get_action_parms(struct FindjoB *o, char **target, char **text_2,
                             uid_t *user, gid_t *group,
                             mode_t *mode_and, mode_t *mode_or,
                             int *type, time_t *date, struct FindjoB **subjob,
                             int flag);

int Findjob_set_found_path(struct FindjoB *o, char *path, int flag);

int Findjob_get_found_path(struct FindjoB *o, char **path, int flag);

#else /* Xorriso_findjob_on_expR */


struct FindjoB;


int Findjob_new(struct FindjoB **o, char *start_path, int flag);

int Findjob_destroy(struct FindjoB **job, int flag);


/* @return 0=no match , 1=match , <0 = error
*/
int Findjob_test(struct FindjoB *job, char *name, 
                 struct stat *boss_stbuf, struct stat *stbuf,
                 int depth, int flag);

/* @return <0 error, >=0 see xorriso.c struct FindjoB.action
*/
int Findjob_get_action(struct FindjoB *o, int flag);

/* @return <0 error, >=0 see xorriso.c struct FindjoB.action
*/ 
int Findjob_get_action_parms(struct FindjoB *o, char **target, char **text_2,
                             uid_t *user, gid_t *group,
                             mode_t *mode_and, mode_t *mode_or,
                             int *type, time_t *date, struct FindjoB **subjob,
                             int flag);

/* @param flag bit0= recursive
*/
int Findjob_set_action_target(struct FindjoB *o, int action, char *target,
                              int flag);

/* @param flag bit0= recursive
*/
int Findjob_set_action_chgrp(struct FindjoB *o, gid_t group, int flag);

/* @param flag bit0= recursive
*/
int Findjob_set_action_chmod(struct FindjoB *o,
                             mode_t mode_and, mode_t mode_or, int flag);

/* @param flag bit0= recursive
*/
int Findjob_set_action_ad(struct FindjoB *o, int type, time_t date, int flag);

int Findjob_set_start_path(struct FindjoB *o, char *start_path, int flag);

int Findjob_set_action_found_path(struct FindjoB *o, int flag);

int Findjob_get_start_path(struct FindjoB *o, char **start_path, int flag);

int Findjob_set_lba_range(struct FindjoB *o, int start_lba, int count,
                          int flag);

int Findjob_get_lba_damage_filter(struct FindjoB *o, int *start_lba,
                                  int *end_lba, int *damage_filter, int flag);

int Findjob_get_commit_filter(struct FindjoB *o, int *commit_filter, int flag);

int Findjob_get_acl_filter(struct FindjoB *o, int *acl_filter, int flag);

int Findjob_get_xattr_filter(struct FindjoB *o, int *xattr_filter, int flag);

int Findjob_get_aaip_filter(struct FindjoB *o, int *aaip_filter, int flag);

int Findjob_get_filter_filter(struct FindjoB *o, int *value, int flag);

int Findjob_set_wanted_node(struct FindjoB *o, void *wanted_node, int flag);

int Findjob_get_wanted_node(struct FindjoB *o, void **wanted_node, int flag);

int Findjob_set_found_path(struct FindjoB *o, char *path, int flag);

int Findjob_get_found_path(struct FindjoB *o, char **path, int flag);

#endif /* ! Xorriso_findjob_on_expR */


struct SplitparT;

int Splitparts_new(struct SplitparT **o, int count, int flag);

int Splitparts_destroy(struct SplitparT **o, int count, int flag);

int Splitparts_set(struct SplitparT *o, int idx,
                   char *name, int partno, int total_parts,
                   off_t offset, off_t bytes, off_t total_bytes, int flag);

int Splitparts_get(struct SplitparT *o, int idx, char **name, int *partno,
                   int *total_parts, off_t *offset, off_t *bytes,
                   off_t *total_bytes, int flag);

int Splitpart__parse(char *name, int *partno, int *total_parts,
                    off_t *offset, off_t *bytes, off_t *total_bytes, int flag);

int Splitpart__is_part_path(char *path, int flag);

int Splitpart__compose(char *adr, int partno, int total_parts,
                       off_t offset, off_t bytes, off_t total_bytes, int flag);

int Splitparts_sort(struct SplitparT *o, int count, int flag);


int Permstack_push(struct PermiteM **o, char *disk_path, struct stat *stbuf,
                   int flag);

int Permstack_pop(struct PermiteM **o, struct PermiteM *stopper,
                  struct XorrisO *xorriso, int flag);


int Spotlist_new(struct SpotlisT **o, int flag);

int Spotlist_destroy(struct SpotlisT **o, int flag);

int Spotlist_add_item(struct SpotlisT *o, int start_lba, int blocks,
                      int quality, int flag);

int Spotlist_count(struct SpotlisT *o, int flag);

int Spotlist_block_count(struct SpotlisT *o, int flag);

int Spotlist_sector_size(struct SpotlisT *o, int read_chunk, int flag);

int Spotlist_get_item(struct SpotlisT *o, int idx,
                      int *start_lba, int *blocks, int *quality, int flag);

char *Spotlist__quality_name(int quality, char name[80], int bad_limit,
                             int flag);


#define Xorriso_read_quality_gooD         0x7fffffff
#define Xorriso_read_quality_md5_matcH    0x70000000
#define Xorriso_read_quality_sloW         0x60000000
#define Xorriso_read_quality_partiaL      0x50000000
#define Xorriso_read_quality_valiD        0x40000000
#define Xorriso_read_quality_untesteD     0x3fffffff
#define Xorriso_read_quality_invaliD      0x3ffffffe
#define Xorriso_read_quality_tao_enD      0x28000000
#define Xorriso_read_quality_off_tracK    0x20000000
#define Xorriso_read_quality_md5_mismatcH 0x10000000
#define Xorriso_read_quality_unreadablE   0x00000000


struct CheckmediajoB {
 int use_dev;        /* 0= use indev , 1= use outdev , 2= use sector map*/
 
 int min_lba;        /* if >=0 : begin checking at this address */ 
 int max_lba;        /* if >=0 : read up to this address, else use mode */
 
 int min_block_size; /* granularity desired by user
                     */ 
 int mode;           /* 0= track by track
                        1= single sweep over libisoburn media capacity
                        >>> 2= single sweep over libburn media capacity
                     */
 time_t start_time;  
 int time_limit;     /* Number of seconds after which to abort */
 
 int item_limit;     /* Maximum number of media check list items as result */
 
 char abort_file_path[SfileadrL];

 char data_to_path[SfileadrL];
 int data_to_fd;
 off_t data_to_offset; /* usually 0 with image copy, negative with file copy */
 off_t data_to_limit;  /* used with file copy */
 int patch_lba0;
 int patch_lba0_msc1;

 char sector_map_path[SfileadrL];
 struct SectorbitmaP *sector_map;
 int map_with_volid;  /* 0=add quick toc to map file,
                         1=read ISO heads for toc
                      */

 int retry;          /* -1= only try full read_chunk, 1=retry with 2k blocks
                         0= retry with CD, full chunk else
                      */

 int report_mode;    /* 0= print MCL items
                        1= print damaged files
                     */

 char event_severity[20]; /* If not "ALL": trigger event of given severity
                             at the end of a check job if bad blocks were
                             discovered.
                           */

 double slow_threshold_seq; /* Time limit in seconds for the decision whether
                               a read operation is considered slow. This does
                               not apply to thr first read of an interval.
                             */

 int untested_valid; /* 1= mark untested data blocks as valid when calling
                           Xorriso_spotlist_to_sectormap()
                      */
};

int Checkmediajob_new(struct CheckmediajoB **o, int flag);

int Checkmediajob_destroy(struct CheckmediajoB **o, int flag);

int Checkmediajob_copy(struct CheckmediajoB *from, struct CheckmediajoB *to,
                       int flag);

int Sectorbitmap_new(struct SectorbitmaP **o, int sectors, int sector_size,
                     int flag);
int Sectorbitmap_destroy(struct SectorbitmaP **o, int flag);
int Sectorbitmap_from_file(struct SectorbitmaP **o, char *path, char *msg,
                           int *os_errno, int flag);
int Sectorbitmap_to_file(struct SectorbitmaP *o, char *path, char *info,
                         char *msg, int *os_errno, int flag);
int Sectorbitmap_set(struct SectorbitmaP *o, int sector, int flag);
int Sectorbitmap_set_range(struct SectorbitmaP *o,
                           int start_sector, int sectors, int flag);
int Sectorbitmap_is_set(struct SectorbitmaP *o, int sector, int flag);
int Sectorbitmap_bytes_are_set(struct SectorbitmaP *o,
                               off_t start_byte, off_t end_byte, int flag);

int Sectorbitmap_get_layout(struct SectorbitmaP *o,
                           int *sectors, int *sector_size, int flag);

int Sectorbitmap_copy(struct SectorbitmaP *from, struct SectorbitmaP *to,
                      int flag);

/* bit0= append (text!=NULL) */
int Sregex_string(char **handle, char *text, int flag);

/* @param flag bit0= only test expression whether compilable
*/
int Sregex_match(char *pattern, char *text, int flag);

#endif /* Xorriso_private_includeD */

