New option -compare

This commit is contained in:
Thomas Schmitt 2008-02-26 21:45:28 +00:00
parent dd4dd5e1e8
commit 3f039e4b08
5 changed files with 272 additions and 63 deletions

View File

@ -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

View File

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

View File

@ -1 +1 @@
#define Xorriso_timestamP "2008.02.25.204402"
#define Xorriso_timestamP "2008.02.26.213437"

View File

@ -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<count) {
ret= iso_stream_read(stream_pt, (void *) (buf+rcnt), (size_t) (count-rcnt));
if(ret==0) /* EOF */
break;
if(ret<0) { /* error */
Xorriso_process_msg_queues(xorriso,0);
Xorriso_report_iso_error(xorriso, "", ret, "Error on read",
0, "FAILURE",1);
return(-1);
}
rcnt+= ret;
}
return(rcnt);
}
int Xorriso_iso_file_close(struct XorrisO *xorriso, void **stream, int flag)
{
int ret;
if(*stream==NULL)
return(0);
ret= iso_stream_close(*stream);
if(ret==1)
*stream= NULL;
Xorriso_process_msg_queues(xorriso,0);
return(ret);
}

View File

@ -166,5 +166,14 @@ int Xorriso_get_profile(struct XorrisO *xorriso, int *profile_number,
int Xorriso_set_publisher(struct XorrisO *xorriso, char *name, int flag);
int Xorriso_iso_file_open(struct XorrisO *xorriso, char *pathname,
void **stream, int flag);
int Xorriso_iso_file_read(struct XorrisO *xorriso, void *stream, char *buf,
int count, int flag);
int Xorriso_iso_file_close(struct XorrisO *xorriso, void **stream, int flag);
#endif /* Xorrisoburn_includeD */