diff --git a/xorriso/xorriso.1 b/xorriso/xorriso.1 index ab53f4f1..db7a3d9b 100644 --- a/xorriso/xorriso.1 +++ b/xorriso/xorriso.1 @@ -1249,6 +1249,17 @@ This is subject to the settings of -follow. -findx accepts the -exec actions as does -find. But it will always perform action "echo". .TP +\fB\-compare\fR disk_path iso_rr_path +Compare attributes and eventual data file content of a fileobject in the +local filesystem with a file object in the ISO image. That iso_rr_path may +well point to a image file object which is not yet committed, i.e. of which +the data content still resides in the local filesystem. Such data content is +prone to externally caused changes. +.br +Differing attributes are reported in detail, differing content is summarized. +Both to the result channel. In case of no differences no result lines are +emitted. +.TP .B Command compatibility emulations: .PP Writing of ISO 9660 on CD is traditionally done by program mkisofs diff --git a/xorriso/xorriso.c b/xorriso/xorriso.c index bf3bdb69..573c00c7 100644 --- a/xorriso/xorriso.c +++ b/xorriso/xorriso.c @@ -1474,6 +1474,45 @@ char *Ftimetxt(time_t t, char timetext[40], int flag) } +/* @param flag bit0= single letters */ +char *Ftypetxt(mode_t st_mode, int flag) +{ + if(flag&1) + goto single_letters; + if(S_ISDIR(st_mode)) + return("directory"); + else if(S_ISREG(st_mode)) + return("regular_file"); + else if(S_ISLNK(st_mode)) + return("symbolic_link"); + else if(S_ISBLK(st_mode)) + return("block_device"); + else if(S_ISCHR(st_mode)) + return("char_device"); + else if(S_ISFIFO(st_mode)) + return("name_pipe"); + else if(S_ISSOCK(st_mode)) + return("unix_socket"); + return("unknown"); +single_letters:; + if(S_ISDIR(st_mode)) + return("d"); + else if(S_ISREG(st_mode)) + return("-"); + else if(S_ISLNK(st_mode)) + return("l"); + else if(S_ISBLK(st_mode)) + return("b"); + else if(S_ISCHR(st_mode)) + return("c"); + else if(S_ISFIFO(st_mode)) + return("p"); + else if(S_ISSOCK(st_mode)) + return("s"); + return("?"); +} + + /* ------------------------------------------------------------------------ */ @@ -4150,53 +4189,44 @@ much_too_long:; /* @param flag bit0= compare atime bit1= compare ctime + bit30= omit adr_common_tail in report messages bit31= do not issue result messages @return 1=files match properly , 0=difference detected , -1=error */ -int Xorriso_compare_2_files(struct XorrisO *xorriso, char *adr1, char *adr2, - char *adr_common_tail, int flag) +int Xorriso_compare_2_files(struct XorrisO *xorriso, char *disk_adr, + char *iso_adr, char *adr_common_tail, int flag) { struct stat s1, s2; - int ret, differs= 0, r1, r2, fd1= -1, fd2= -1, i, done; + int ret, differs= 0, r1, r2, fd1= -1, i, done, wanted; + void *stream2= NULL; char *respt; - char buf1[SfileadrL], buf2[SfileadrL], a[5*SfileadrL], sfe[5*SfileadrL]; + char buf1[32*1024], buf2[32*1024], a[5*SfileadrL], sfe[5*SfileadrL]; + char ttx1[40], ttx2[40]; off_t r1count= 0, r2count= 0, diffcount= 0, first_diff= -1; respt= xorriso->result_line; - ret= lstat(adr1, &s1); + ret= lstat(disk_adr, &s1); if(ret==-1) { sprintf(respt , "? %s : cannot lstat() : %s", - Text_shellsafe(adr1, sfe, 0), strerror(errno)); + Text_shellsafe(disk_adr, sfe, 0), strerror(errno)); if(!(flag&(1<<31))) Xorriso_result(xorriso,0); return(0); } - if(S_ISDIR(s1.st_mode)) - strcpy(a, "d"); - else if(S_ISREG(s1.st_mode)) - strcpy(a, "-"); - else if(S_ISLNK(s1.st_mode)) - strcpy(a, "l"); - else if(S_ISBLK(s1.st_mode)) - strcpy(a, "b"); - else if(S_ISCHR(s1.st_mode)) - strcpy(a, "c"); - else if(S_ISFIFO(s1.st_mode)) - strcpy(a, "p"); - else if(S_ISSOCK(s1.st_mode)) - strcpy(a, "s"); - else - strcpy(a, "?"); + strcpy(a, Ftypetxt(s1.st_mode, 1)); strcat(a, " "); if(adr_common_tail[0]) sprintf(a, Text_shellsafe(adr_common_tail, sfe, 0)); else strcat(a, "'.'"); + strcat(a, " :"); + if(flag&(1<<30)) + a[0]= 0; - ret= Xorriso_iso_lstat(xorriso, adr2, &s2, 0); + ret= Xorriso_iso_lstat(xorriso, iso_adr, &s2, 0); if(ret==-1) { - sprintf(respt, "? %s : cannot lstat() : %s\n", - Text_shellsafe(adr2, sfe, 0), strerror(errno)); + sprintf(respt, "? %s (ISO) : cannot find this file in ISO image\n", + Text_shellsafe(iso_adr, sfe, 0)); if(!(flag&(1<<31))) Xorriso_result(xorriso,0); return(0); @@ -4204,20 +4234,28 @@ int Xorriso_compare_2_files(struct XorrisO *xorriso, char *adr1, char *adr2, /* Attributes */ if(s1.st_mode != s2.st_mode) { - sprintf(respt, "%s : st_mode : %7.7o <> %7.7o\n", - a, s1.st_mode, s2.st_mode); - if(!(flag&(1<<31))) - Xorriso_result(xorriso,0); + if((s1.st_mode&~S_IFMT)!=(s2.st_mode&~S_IFMT)) { + sprintf(respt, "%s st_mode : %7.7o <> %7.7o\n", + a, s1.st_mode, s2.st_mode); + if(!(flag&(1<<31))) + Xorriso_result(xorriso,0); + } + if((s1.st_mode&S_IFMT)!=(s2.st_mode&S_IFMT)) { + sprintf(respt, "%s type : %s <> %s\n", + a, Ftypetxt(s1.st_mode, 0), Ftypetxt(s2.st_mode, 0)); + if(!(flag&(1<<31))) + Xorriso_result(xorriso,0); + } differs= 1; } if(s1.st_uid != s2.st_uid) { - sprintf(respt, "%s : st_uid : %d <> %d\n", a, s1.st_uid, s2.st_uid); + sprintf(respt, "%s st_uid : %d <> %d\n", a, s1.st_uid, s2.st_uid); if(!(flag&(1<<31))) Xorriso_result(xorriso,0); differs= 1; } if(s1.st_gid != s2.st_gid) { - sprintf(respt, "%s : st_gid : %d <> %d\n", a, s1.st_gid, s2.st_gid); + sprintf(respt, "%s st_gid : %d <> %d\n", a, s1.st_gid, s2.st_gid); if(!(flag&(1<<31))) Xorriso_result(xorriso,0); differs= 1; @@ -4225,7 +4263,7 @@ int Xorriso_compare_2_files(struct XorrisO *xorriso, char *adr1, char *adr2, if((S_ISCHR(s1.st_mode) && S_ISCHR(s2.st_mode)) || (S_ISBLK(s1.st_mode) && S_ISBLK(s2.st_mode))) { if(s1.st_rdev != s2.st_rdev) { - sprintf(respt, "%s : %s st_rdev : %lu <> %lu\n", a, + sprintf(respt, "%s %s st_rdev : %lu <> %lu\n", a, (S_ISCHR(s1.st_mode) ? "S_IFCHR" : "S_IFBLK"), (unsigned long) s1.st_rdev, (unsigned long) s1.st_rdev); if(!(flag&(1<<31))) @@ -4234,23 +4272,28 @@ int Xorriso_compare_2_files(struct XorrisO *xorriso, char *adr1, char *adr2, } } if(S_ISREG(s2.st_mode) && s1.st_size != s2.st_size) { - sprintf(respt, "%s : st_size : %.f <> %.f\n", - a, (double) s1.st_size, (double) s2.st_size); + sprintf(respt, "%s st_size : %.f <> %.f diff= %.f\n", + a, (double) s1.st_size, (double) s2.st_size, + ((double) s1.st_size) - (double) s2.st_size); if(!(flag&(1<<31))) Xorriso_result(xorriso,0); differs= 1; } if(s1.st_mtime != s2.st_mtime) { - sprintf(respt, "%s : st_mtime : %u <> %u\n", - a, (unsigned int) s1.st_mtime, (unsigned int) s2.st_mtime); + sprintf(respt, "%s st_mtime : %s <> %s diff= %.f s\n", + a, Ftimetxt(s1.st_mtime, ttx1, 0), + Ftimetxt(s2.st_mtime, ttx2, 0), + ((double) s1.st_mtime) - (double) s2.st_mtime); if(!(flag&(1<<31))) Xorriso_result(xorriso,0); differs= 1; } if(flag&1) { if(s1.st_atime != s2.st_atime) { - sprintf(respt, "%s : st_atime : %u <> %u\n", - a, (unsigned int) s1.st_atime, (unsigned int) s2.st_atime); + sprintf(respt, "%s st_atime : %s <> %s diff= %.f s\n", + a, Ftimetxt(s1.st_atime, ttx1, 0), + Ftimetxt(s2.st_atime, ttx2, 0), + ((double) s1.st_atime) - (double) s2.st_atime); if(!(flag&(1<<31))) Xorriso_result(xorriso,0); differs= 1; @@ -4258,27 +4301,28 @@ int Xorriso_compare_2_files(struct XorrisO *xorriso, char *adr1, char *adr2, } if(flag&2) { if(s1.st_ctime != s2.st_ctime) { - sprintf(respt, "%s : st_ctime : %u <> %u\n", - a, (unsigned int) s1.st_ctime, (unsigned int) s2.st_ctime); + sprintf(respt, "%s st_ctime : %s <> %s diff= %.f s\n", + a, Ftimetxt(s1.st_ctime, ttx1, 0), + Ftimetxt(s2.st_ctime, ttx2, 0), + ((double) s1.st_ctime) - (double) s2.st_ctime); if(!(flag&(1<<31))) Xorriso_result(xorriso,0); differs= 1; } } - if(S_ISREG(s1.st_mode)) { - fd1= open(adr1, O_RDONLY); + if(S_ISREG(s1.st_mode) && S_ISREG(s2.st_mode)) { + fd1= open(disk_adr, O_RDONLY); if(fd1==-1) { - sprintf(respt, "- %s : cannot open() : %s\n", adr1, strerror(errno)); + sprintf(respt, "- %s (DISK) : cannot open() : %s\n", + disk_adr, strerror(errno)); if(!(flag&(1<<31))) Xorriso_result(xorriso,0); return(0); } -/* >>> */ - - fd2= open(adr2, O_RDONLY); - if(fd2==-1) { - sprintf(respt, "- %s : cannot open() : %s\n", adr2, strerror(errno)); + ret= Xorriso_iso_file_open(xorriso, iso_adr, &stream2, 0); + if(ret<=0) { + sprintf(respt, "- %s (ISO) : cannot open() file in ISO image\n",iso_adr); if(!(flag&(1<<31))) Xorriso_result(xorriso,0); close(fd1); @@ -4288,16 +4332,35 @@ int Xorriso_compare_2_files(struct XorrisO *xorriso, char *adr1, char *adr2, /* Content */ done= 0; while(!done) { + + /* fd1 is a regular file and should deliver full buffers */ r1= read(fd1, buf1, sizeof(buf1)); - r2= read(fd2, buf2, sizeof(buf2)); + + wanted= sizeof(buf2); + +/* +#define Libisofs_data_read_as_posiX yes +*/ +#ifndef Libisofs_data_read_as_posiX + /* This functions guarantees to deliver full buffers but fails on + oversized read requests. */ + if(r2count+wanted>s2.st_size) + wanted= s2.st_size-r2count; +#endif + + if(wanted>0) + r2= Xorriso_iso_file_read(xorriso, stream2, buf2, wanted, 0); + else + r2= 0; + if((r1==EOF && r2==EOF) || (r1==0 && r2==0)) break; if(r1==EOF || r1==0) { if(r1==EOF) r1= 0; if(s1.st_size > r1count + r1) { - sprintf(respt, "- %s : early EOF after %.f bytes\n", - adr1, (double) r1count); + sprintf(respt, "- %s (DISK) : early EOF after %.f bytes\n", + disk_adr, (double) r1count); if(!(flag&(1<<31))) Xorriso_result(xorriso,0); } @@ -4308,8 +4371,8 @@ int Xorriso_compare_2_files(struct XorrisO *xorriso, char *adr1, char *adr2, if(r2==EOF) r2= 0; if(s2.st_size > r2count + r2) { - sprintf(respt, "- %s : early EOF after %.f bytes\n", - adr2, (double) r2count); + sprintf(respt, "- %s (ISO) : early EOF after %.f bytes\n", + iso_adr, (double) r2count); if(!(flag&(1<<31))) Xorriso_result(xorriso,0); } @@ -4318,8 +4381,8 @@ int Xorriso_compare_2_files(struct XorrisO *xorriso, char *adr1, char *adr2, } if(r2>r1) { if(s1.st_size > r1count + r1) { - sprintf(respt, "- %s : early EOF after %.f bytes\n", - adr1, (double) r1count); + sprintf(respt, "- %s (DISK) : early EOF after %.f bytes\n", + disk_adr, (double) r1count); if(!(flag&(1<<31))) Xorriso_result(xorriso,0); } @@ -4340,7 +4403,7 @@ int Xorriso_compare_2_files(struct XorrisO *xorriso, char *adr1, char *adr2, if(diffcount>0 || r1count!=r2count) { if(first_diff<0) first_diff= (r1count>r2count ? r2count : r1count); - sprintf(respt, "%s : %s : differs by at least %.f bytes. First at %.f\n", + sprintf(respt, "%s %s : differs by at least %.f bytes. First at %.f\n", a, (s1.st_mtime==s2.st_mtime ? "CONTENT": "content"), (double) (diffcount + abs(r1count-r2count)), (double) first_diff); if(!(flag&(1<<31))) @@ -4350,8 +4413,7 @@ int Xorriso_compare_2_files(struct XorrisO *xorriso, char *adr1, char *adr2, } if(fd1!=-1) close(fd1); - if(fd2!=-1) - close(fd2); + Xorriso_iso_file_close(xorriso, &stream2, 0); return(!differs); } @@ -5720,6 +5782,7 @@ int Xorriso_format_ls_l(struct XorrisO *xorriso, struct stat *stbuf, int flag) #ifndef NIX Ftimetxt(stbuf->st_mtime, rpt+strlen(rpt), 0); + strcat(rpt, " "); #else mtime= stbuf->st_mtime; tmpt= localtime_r(&mtime, &tms); @@ -7559,6 +7622,36 @@ int Xorriso_option_commit_eject(struct XorrisO *xorriso, char *which, int flag) } +/* Option -compare + @param flag bit0= issue summary message +*/ +int Xorriso_option_compare(struct XorrisO *xorriso, char *disk_path, + char *iso_path, int flag) +{ + int ret; + char *ipth; + + ipth= iso_path; + if(ipth[0]==0) + ipth= disk_path; + + ret= Xorriso_compare_2_files(xorriso, disk_path, ipth, "", 2|(1<<30)); + if(ret>0) { + sprintf(xorriso->result_line, + "Ok. Both files match as far as expectable.\n"); + } else if(ret==0) { + sprintf(xorriso->result_line, "Not ok. Differences detected.\n"); + } else { + sprintf(xorriso->result_line, "Not ok. Comparison failed due to error.\n"); + } + if(flag&1) + Xorriso_result(xorriso,0); + if(ret<0) + return(ret); + return(1); +} + + /* Option -cpr alias -cpri */ int Xorriso_option_cpri(struct XorrisO *xorriso, int argc, char **argv, int *idx, int flag) @@ -8371,6 +8464,9 @@ int Xorriso_option_help(struct XorrisO *xorriso, int flag) " -findx disk_path [-name pattern] like -find but in local filesystem.", " Any -exec option is ignored. Action is always echo.", "", +" -compare disk_path iso_rr_path compare attributes and in case of regular", +" data files the content of filesystem object and ISO object.", +"", "Compatibility emulation (argument list may be ended by --):", " -as mkisofs [-help|-o|-R|-J|-V|-P|-f|-graft-points|-path-list|pathspecs]", " Perform some mkisofs gestures, understand pathspecs as mkisofs", @@ -9745,6 +9841,10 @@ next_command:; (*idx)++; ret= Xorriso_option_commit_eject(xorriso, arg1, 0); + } else if(strcmp(cmd,"compare")==0) { + (*idx)+= 2; + ret= Xorriso_option_compare(xorriso, arg1, arg2, 1); + } else if(strcmp(cmd,"cpr")==0 || strcmp(cmd,"cpri")==0) { ret= Xorriso_option_cpri(xorriso, argc, argv, idx, 0); diff --git a/xorriso/xorriso_timestamp.h b/xorriso/xorriso_timestamp.h index f89ed6f3..684f9ff2 100644 --- a/xorriso/xorriso_timestamp.h +++ b/xorriso/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2008.02.25.204402" +#define Xorriso_timestamP "2008.02.26.213437" diff --git a/xorriso/xorrisoburn.c b/xorriso/xorrisoburn.c index ccded134..248e0379 100644 --- a/xorriso/xorrisoburn.c +++ b/xorriso/xorrisoburn.c @@ -2858,7 +2858,9 @@ ex:; } -/* @param flag bit0= *node is already valid */ +/* @param flag bit0= *node is already valid + bit1= add extra block for size estimation +*/ int Xorriso_fake_stbuf(struct XorrisO *xorriso, char *path, struct stat *stbuf, IsoNode **node, int flag) { @@ -2909,7 +2911,7 @@ int Xorriso_fake_stbuf(struct XorrisO *xorriso, char *path, struct stat *stbuf, /* >>> stbuf->st_rdev */ if(LIBISO_ISREG(*node)) - stbuf->st_size= iso_file_get_size((IsoFile *) *node)+2048; + stbuf->st_size= iso_file_get_size((IsoFile *) *node)+ (2048 * !!(flag&2)); else stbuf->st_size= 0; @@ -3054,7 +3056,7 @@ int Xorriso_ls_filev(struct XorrisO *xorriso, char *wd, ret= Xorriso_make_abs_adr(xorriso, wd, filev[i], path, 1|2|4); if(ret<=0) continue; - ret= Xorriso_fake_stbuf(xorriso, path, &stbuf, &node, 0); + ret= Xorriso_fake_stbuf(xorriso, path, &stbuf, &node, (flag&4)>>1); if(ret<=0) continue; if(LIBISO_ISDIR(node) && !(flag&(4|8))) { @@ -4254,5 +4256,92 @@ int Xorriso_get_profile(struct XorrisO *xorriso, int *profile_number, if(*profile_number==0x08 || *profile_number==0x09 || *profile_number==0x0a) return(2); return(0); - } + + +int Xorriso_iso_file_open(struct XorrisO *xorriso, char *pathname, + void **stream, int flag) +{ + int ret; + char eff_path[SfileadrL]; + IsoNode *node= NULL; + IsoFile *filenode= NULL; + IsoStream *iso_stream= NULL; + + *stream= NULL; + ret= Xorriso_get_node_by_path(xorriso, pathname, eff_path, &node, 0); + if(ret<=0) + return(ret); + if(!LIBISO_ISREG(node)) { + sprintf(xorriso->info_text, + "Given path does not lead to a regular data file in the image"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + filenode= (IsoFile *) node; + iso_stream= iso_file_get_stream(filenode); + if(iso_stream==NULL) { + Xorriso_process_msg_queues(xorriso,0); + sprintf(xorriso->info_text, + "Could not obtain source stream of file in the image for reading"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + ret= iso_stream_open(iso_stream); + if(ret<0) { + sprintf(xorriso->info_text, + "Could not open data file in the image for reading"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + return(0); + } + if(!iso_stream_is_repeatable(iso_stream)) { + sprintf(xorriso->info_text, + "The data production of the file in the image is one-time only"); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + iso_stream_close(iso_stream); + return(0); + } + Xorriso_process_msg_queues(xorriso,0); + *stream= iso_stream; + return(1); +} + + +int Xorriso_iso_file_read(struct XorrisO *xorriso, void *stream, char *buf, + int count, int flag) +{ + int ret, rcnt= 0; + IsoStream *stream_pt; + + stream_pt= (IsoStream *) stream; + + while(rcnt