From 2ac12ad0e9d432a0e71f7bb0b92e0378d645b518 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Thu, 8 Nov 2007 14:43:53 +0000 Subject: [PATCH] Implemented option -alter_date, corrected write problem with mode and ownership --- libisoburn/trunk/test/xorriso.1 | 64 ++- libisoburn/trunk/test/xorriso.c | 506 +++++++++++++++++++++- libisoburn/trunk/test/xorriso_timestamp.h | 2 +- libisoburn/trunk/test/xorrisoburn.c | 41 +- libisoburn/trunk/test/xorrisoburn.h | 3 + 5 files changed, 587 insertions(+), 29 deletions(-) diff --git a/libisoburn/trunk/test/xorriso.1 b/libisoburn/trunk/test/xorriso.1 index 4017ccdb..a6ec6064 100644 --- a/libisoburn/trunk/test/xorriso.1 +++ b/libisoburn/trunk/test/xorriso.1 @@ -43,7 +43,7 @@ Copies files from filesystem into the ISO image. .br Renames or deletes file objects in the ISO image. .br - > Changes file properties in the ISO image. +Changes file properties in the ISO image. .br > Can write result as completely new image to optical media or filesystem objects. .br @@ -312,19 +312,44 @@ See also the note with option -rm. Rename the given file objects in the ISO tree to the last argument in the list. Use the same rules as with shell command mv. .TP -> \fB\-chown\fR uid iso_rr_path [...] +\fB\-chown\fR uid iso_rr_path [...] Equivalent to shell command chown in the ISO image. .TP -> \fB\-chgrp\fR gid iso_rr_path [...] +\fB\-chgrp\fR gid iso_rr_path [...] Equivalent to shell command chgrp in the ISO image. .TP -> \fB\-chmod\fR mode iso_rr_path [...] +\fB\-chmod\fR mode iso_rr_path [...] Equivalent to shell command chmod in the ISO image. .TP -> \fB\-alter_date\fR type timestring iso_rr_path [...] +\fB\-alter_date\fR type timestring iso_rr_path [...] Alter the date entries of a file in the ISO image. type is one of "a", "m", "b" for access time, modification time, both times. +.br +timestring may be in the following formats +(see also section EXAMPLES): +.br +As expected by program date: + MMDDhhmm[[CC]YY][.ss]] +.br +As produced by program date: + [Day] MMM DD hh:mm:ss [TZON] YYYY +.br +Relative times counted from current clock time: + +|-Number["s"|"h"|"d"|"w"|"m"|"y"] +.br +where "s" means seconds, "h" hours, "d" days, "w" weeks, "m" = 30d, y=365.25d. +.br +Absolute seconds counted from Jan 1 1970: + =Number +.br +xorriso's own timestamps: + YYYY.MM.DD[.hh[mm[ss]]] +.br +scdbackup timestamps: + YYMMDD[.hhmm[ss]] +.br +where "A0" is year 2000, "B0" is 2010, etc. .TP \fB\-mkdir\fR iso_rr_path [...] Create empty directories if they do not exist yet. @@ -688,9 +713,32 @@ Use text as this program's name in subsequent messages Use text as this program's name and perform -help. .br .SH EXAMPLES - ->>> to come - +.SS +>>> more to come +.br +.SS +.B Examples of input timestrings +.br +As printed by program date: +.B 'Thu Nov 8 14:51:13 CET 2007' +.br +The same without ignored parts: +.B 'Nov 8 14:51:13 2007' +.br +The same as expected by date: +.B 110814512007.13 +.br +Four weeks in the future: +.B +4w +.br +The current time: +.B +0 +.br +Three hours ago: +.B \-3h +.br +Seconds since Jan 1 1970: +.B =1194531416 .br .SH FILES .SS diff --git a/libisoburn/trunk/test/xorriso.c b/libisoburn/trunk/test/xorriso.c index fb0d1bb4..144f890e 100644 --- a/libisoburn/trunk/test/xorriso.c +++ b/libisoburn/trunk/test/xorriso.c @@ -719,6 +719,58 @@ double Sfile_microtime(int flag) } +int Sfile_decode_datestr(struct tm *reply, char *text, int flag) +/* YYMMDD[.hhmm[ss]] */ +{ + int i,l; + time_t current_time; + struct tm *now; + + current_time= time(0); + now= localtime(¤t_time); + for(i=0;i'9' && text[0]<'A') || text[0]>'Z') + return(0); + l= strlen(text); + for(i=1;i'9') + break; + if(i!=6) + return(0); + if(text[i]==0) + goto decode; + if(text[i]!='.' || (l!=11 && l!=13)) + return(0); + for(i++;i'9') + break; + if(i!=l) + return(0); + +decode:; + reply->tm_hour= 0; + reply->tm_min= 0; + reply->tm_sec= 0; + i= 0; + if(text[0]>='A') + reply->tm_year= 100+(text[i]-'A')*10+text[1]-'0'; + else + reply->tm_year= 10*(text[0]-'0')+text[1]-'0'; + reply->tm_mon= 10*(text[2]-'0')+text[3]-'0'-1; + reply->tm_mday= 10*(text[4]-'0')+text[5]-'0'; + if(l==6) + return(1); + reply->tm_hour= 10*(text[7]-'0')+text[8]-'0'; + reply->tm_min= 10*(text[9]-'0')+text[10]-'0'; + if(l==11) + return(1); + reply->tm_sec= 10*(text[11]-'0')+text[12]-'0'; + return(1); +} + + #endif /* Xorriso_sfile_externaL */ @@ -1122,6 +1174,402 @@ double Scanf_io_size(char *text, int flag) } +int Decode_date_input_format(struct tm *erg, char *text, int flag) +/* MMDDhhmm[[CC]YY][.ss]] */ +{ + int i,l,year; + time_t current_time; + struct tm *now; + + current_time= time(0); + now= localtime(¤t_time); + for(i=0;i'9') + break; + if(i!=8 && i!=10 && i!=12) + return(0); + if(text[i]==0) + goto decode; + if(text[i]!='.' || l!=15) + return(0); + i++; + if(text[i]<'0'||text[i]>'9') + return(0); + i++; + if(text[i]<'0'||text[i]>'9') + return(0); + +decode:; + /* MMDDhhmm[[CC]YY][.ss]] */ + i= 0; + erg->tm_mon= 10*(text[0]-'0')+text[1]-'0'-1; + erg->tm_mday= 10*(text[2]-'0')+text[3]-'0'; + erg->tm_hour= 10*(text[4]-'0')+text[5]-'0'; + erg->tm_min= 10*(text[6]-'0')+text[7]-'0'; + erg->tm_sec= 0; + if(l==8) + return(1); + if(l>10){ + year= 1000*(text[8]-'0')+100*(text[9]-'0')+10*(text[10]-'0')+(text[11]-'0'); + }else{ + year= 1900+10*(text[8]-'0')+(text[9]-'0'); + if(year<1970) + year+= 100; + } + erg->tm_year= year-1900; + if(l<=12) + return(1); + erg->tm_sec= 10*(text[13]-'0')+text[14]-'0'; + return(1); +} + + +int Decode_date_weekday(char *text, int flag) +{ + int i; + static char days[][4]= {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", ""}; + + for(i= 0; days[i][0]!=0; i++) + if(strncmp(text,days[i],3)==0) + return(i); + if((strlen(text)==3 || (strlen(text)==4 && text[3]==',')) && + isalpha(text[0]) && isalpha(text[1]) && isalpha(text[2])) + return(7); + return(-1); +} + + +int Decode_date_month(char *text, int flag) +{ + int i; + static char months[][4]= {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ""}; + + for(i= 0; months[i][0]!=0; i++) + if(strncmp(text,months[i],3)==0) + return(i); + return(-1); +} + + +/* @return -1=not a number, -2=not a day , 1 to 31 day of month */ +int Decode_date_mday(char *text, int flag) +{ + int ret, i; + + for(i= 0; text[i]!=0; i++) + if(!isdigit(text[i])) + return(-1); + if(strlen(text)>2 || text[0]==0) + return(-2); + sscanf(text, "%d", &ret); + if(ret<=0 || ret>31) + return(-2); + return(ret); +} + +int Decode_date_hms(char *text, struct tm *erg, int flag) +{ + int i, hour= -1, minute= -1, second= 0; + + for(i= 0; i<9; i+= 3) { + if(i==6&&text[i]==0) + break; + if(!isdigit(text[i])) + return(-1); + if(!isdigit(text[i+1])) + return(-1); + if(text[i+2]!=':' && !(text[i+2]==0 && i>=3)) + return(-1); + if(i==0) + sscanf(text+i,"%d",&hour); + else if(i==3) + sscanf(text+i,"%d",&minute); + else + sscanf(text+i,"%d",&second); + } + if(hour<0 || hour>23 || minute<0 || minute>59 || second>59) + return(-1); + erg->tm_hour= hour; + erg->tm_min= minute; + erg->tm_sec= second; + return(1); +} + + +/* @return -1=not a number, -2=not a year , >=0 years AD */ +int Decode_date_year(char *text, int flag) +{ + int ret, i; + + for(i= 0; text[i]!=0; i++) + if(!isdigit(text[i])) + return(-1); + if(strlen(text)!=4) + return(-2); + sscanf(text, "%d", &ret); + if(ret<0 || ret>3000) + return(-2); + return(ret); +} + + +int Decode_date_timezone(char *text, struct tm *erg, int flag) +{ + int i; + static char tzs[][5]= {"GMT", "CET", "CEST", "0000", ""}; + + for(i= 0; tzs[i][0]!=0; i++) + if(strcmp(text,tzs[i])==0) { + + /* ??? >>> what to do with timezone info ? Add to ->tm_hour ? */ + + return(1); + } + if(text[0]=='+' || text[0]=='-') { + for(i= 1; text[i]!=0; i++) + if(!isdigit(text[i])) + return(-1); + if(i!=5) + return(-1); + + /* ??? >>> what to do with timezone info ? Add to ->tm_hour ? */ + + return(1); + } else { + for(i= 0; text[i]!=0; i++) + if(text[i]<'A' || text[i]>'Z') + return(-1); + if(i!=3 && i!=4) + return(-1); + return(2); + } +} + + +int Decode_date_output_format(struct tm *erg, char *text, int flag) +/* Thu Nov 8 09:07:50 CET 2007 */ +/* Sat, 03 Nov 2007 08:58:30 +0100 */ +/* Nov 7 23:24 */ +{ + int ret, i, argc= 0, seen_year= 0, seen_month= 0, seen_day= 0, seen_time= 0; + char **argv= NULL; + struct tm *now; + time_t timep; + + memset(erg, 0, sizeof(*erg)); + erg->tm_isdst= -1; + ret= Sfile_make_argv("xorriso", text, &argc, &argv, 0); + if(ret<=0) + goto ex; + for(i= 1; i=0) { + seen_month= 1; + erg->tm_mon= ret; + continue; + } + } + if(!seen_day) { + ret= Decode_date_mday(argv[i], 0); + if(ret>0) { + seen_day= 1; + erg->tm_mday= ret; + continue; + } + if(ret==-2) /* first pure number must be day of month */ + {ret= 0; goto ex;} + } + if(!seen_time) { + ret= Decode_date_hms(argv[i], erg, 0); + if(ret>0) { + seen_time= 1; + continue; + } + } + if(!seen_year) { + ret= Decode_date_year(argv[i], 0); + if(ret>0) { + erg->tm_year= ret-1900; + seen_year= 1; + continue; + } + } + + /* ignorants have to stay at the end of the loop */ + + ret= Decode_date_timezone(argv[i], erg, 0); + if(ret>=0) + continue; + ret= Decode_date_weekday(argv[i], 0); + if(ret>=0) + continue; /* ignore weekdays */ + + {ret= 0; goto ex;} /* unrecognizable component */ + } + + if(!(seen_day && seen_month)) + {ret= 0; goto ex;} + if(!seen_year) { /* then use this year */ + timep= time(NULL); + now= localtime(&timep); + erg->tm_year= now->tm_year; + } + ret= 1; +ex: + Sfile_make_argv("", "", &argc, &argv, 2); /* release storage */ + return(ret); +} + + +int Decode_xorriso_timestamp(struct tm *erg, char *code, int flag) + /* 2007.11.07.225624 */ +{ + char buf[20]; + int year,month,day,hour= 0,minute= 0,second= 0, i, l, mem; + + memset(erg, 0, sizeof(*erg)); + erg->tm_isdst= -1; + + l= strlen(code); + if(l>17 || l<10) + return(0); + strcpy(buf, code); + for(i= 0; buf[i]!=0 && i<4; i++) + if(!isdigit(buf[i])) + return(0); + if(buf[4]!='.') + return(0); + buf[4]= 0; + sscanf(buf, "%d", &year); + if(year<1900 || year>3000) + return(0); + if(!(isdigit(buf[5]) && isdigit(buf[6]) && buf[7]=='.')) + return(0); + buf[7]= 0; + sscanf(buf+5, "%d", &month); + if(month<1 || month>12) + return(0); + if(!(isdigit(buf[8]) && isdigit(buf[9]) && (buf[10]=='.' || buf[10]==0))) + return(0); + buf[10]= 0; + sscanf(buf+8, "%d", &day); + if(day<1 || day>31) + return(0); + if(l==10) + goto done; + if(!(isdigit(buf[11]) && isdigit(buf[12]) && + (isdigit(buf[13]) || buf[13]==0))) + return(0); + mem= buf[13]; + buf[13]= 0; + sscanf(buf+11, "%d", &hour); + buf[13]= mem; + if(hour<0 || hour>23) + return(0); + if(l==13) + goto done; + if(!(isdigit(buf[13]) && isdigit(buf[14]) && + (isdigit(buf[15]) || buf[15]==0))) + return(0); + mem= buf[15]; + buf[15]= 0; + sscanf(buf+13, "%d", &minute); + buf[15]= mem; + if(minute<0 || minute>59) + return(0); + if(l==15) + goto done; + if(!(isdigit(buf[15]) && isdigit(buf[16]) && buf[17]==0)) + return(0); + sscanf(buf+15, "%d", &second); + if(second<0 || second>59) + return(0); + +done:; + erg->tm_year= year-1900; + erg->tm_mon= month-1; + erg->tm_mday= day; + erg->tm_hour= hour; + erg->tm_min= minute; + erg->tm_sec= second; + return(1); +} + + +time_t Decode_timestring(char *code, time_t *date, int flag) +{ + char *cpt,scale_chr; + double value,seconds; + struct tm result_tm; + int seconds_valid= 0; + + *date= 0; + cpt= code; + if(code[0]=='-' || code[0]=='+' || code[0]=='='){ + if(code[1]==0) + return(0); + if(!isdigit(code[1])) + return(0); + value= -1; + if(code[0]=='=') { + seconds= 0; + sscanf(code+1,"%lf",&value); + } else { + seconds= time(0); + sscanf(code,"%lf",&value); + } + scale_chr= code[strlen(code)-1]; + if(isalpha(scale_chr)) + scale_chr= tolower(scale_chr); + if (scale_chr=='s') seconds+= 1.0*value; + else if(scale_chr=='h') seconds+= 3600.0*value; + else if(scale_chr=='d') seconds+= 86400.0*value; + else if(scale_chr=='w') seconds+= 86400.0*7.0*value; + else if(scale_chr=='m') seconds+= 86400.0*31.0*value; + else if(scale_chr=='y') seconds+= 86400.0*(365.25*value+1.0); + else seconds+= 1.0*value; + seconds_valid= 1; + goto completed; + } else if(Sfile_decode_datestr(&result_tm,code,0)>0) { + /* YYMMDD[.hhmm[ss]] */ + result_tm.tm_isdst= -1; + seconds= mktime(&result_tm); + seconds_valid= 1; + goto completed; + } else if(Decode_date_input_format(&result_tm,code,0)>0) { + /* MMDDhhmm[[CC]YY][.ss]] */ + result_tm.tm_isdst= -1; + seconds= mktime(&result_tm); + seconds_valid= 1; + goto completed; + } else if(Decode_xorriso_timestamp(&result_tm, code, 0)>0) { + /* 2007.11.07.225624 */ + seconds= mktime(&result_tm); + seconds_valid= 1; + goto completed; + } else if(Decode_date_output_format(&result_tm, code, 0)>0) { + /* Thu Nov 8 09:07:50 CET 2007 */; + /* Sat, 03 Nov 2007 08:58:30 +0100 */; + /* Nov 7 23:24 */; + seconds= mktime(&result_tm); + seconds_valid= 1; + goto completed; + } + return(0); +completed:; + if(!seconds_valid) + return(0); + *date= seconds; + return(1); +} + + /* ------------------------------------------------------------------------ */ @@ -1776,9 +2224,12 @@ int Xorriso_new(struct XorrisO ** xorriso,char *progname, int flag) m->global_uid= 0; m->volid[0]= 0; m->do_global_gid= 0; + m->global_gid= 0; + m->do_global_mode= 0; + m->global_dir_mode= 0555; + m->global_file_mode= 0444; m->do_overwrite= 2; m->do_reassure= 0; - m->global_gid= 0; m->indev[0]= 0; m->in_drive_handle= NULL; m->in_volset_handle= NULL; @@ -3265,19 +3716,43 @@ int Xorriso_option_alter_date(struct XorrisO *xorriso, char *time_type, char *timestring, int argc, char **argv, int *idx, int flag) { - int i, end_idx; + int i, end_idx, ret, was_failure= 0, t_type= 0; + time_t t; end_idx= Xorriso_end_idx(xorriso, argc, argv, *idx, 0); - fprintf(stderr, ">>> XORRISO : decode timestring %s\n", timestring); - fprintf(stderr, ">>> LIBISOFS : -alter_date %s %s ", - time_type, timestring); - for(i= *idx; iinfo_text, "-alter_date: Unrecognized type '%s'", + time_type); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + ret= 0; goto ex; + } + ret= Decode_timestring(timestring, &t, 0); + if(ret<=0) { + sprintf(xorriso->info_text, "-alter_date: Cannot decode timestring '%s'", + timestring); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); + ret= 0; goto ex; + } + for(i= *idx; ido_global_mode; + sopts.dir_mode= xorriso->global_dir_mode; + sopts.replace_file_mode= xorriso->do_global_mode; + sopts.file_mode= xorriso->global_file_mode; sopts.replace_uid= (xorriso->do_global_uid); sopts.uid= xorriso->global_uid; sopts.replace_gid= (xorriso->do_global_gid); @@ -879,6 +879,7 @@ handle_path_node:; Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); return(0); } + iso_tree_node_set_ctime((struct iso_tree_node *) dir, time(NULL)); /* >>> copy properties from correspondent directory in disk_path if there is any */; @@ -1902,7 +1903,7 @@ much_too_long:; tmpt= localtime_r(&mtime, &tms); if(tmpt==0) sprintf(rpt+strlen(rpt), "%12.f ",(double) mtime); - else if(time(0)-mtime < 180*86400) + else if(time(NULL)-mtime < 180*86400 && time(NULL)-mtime >= 0) sprintf(rpt+strlen(rpt), "%3s %2d %2.2d:%2.2d ", months[tms.tm_mon], tms.tm_mday, tms.tm_hour, tms.tm_min); else @@ -2045,7 +2046,7 @@ wdi_is_not_a_dir:; tmpt= localtime_r(&mtime, &tms); if(tmpt==0) sprintf(rpt+strlen(rpt), "%12.f ",(double) mtime); - else if(time(0)-mtime < 180*86400) + else if(time(NULL)-mtime < 180*86400 && time(NULL)-mtime >= 0) sprintf(rpt+strlen(rpt), "%3s %2d %2.2d:%2.2d ", months[tms.tm_mon], tms.tm_mday, tms.tm_hour, tms.tm_min); else @@ -2479,6 +2480,7 @@ int Xorriso_set_st_mode(struct XorrisO *xorriso, char *in_path, mode= iso_tree_node_get_permissions(node); mode= (mode & mode_and) | mode_or; iso_tree_node_set_permissions(node, mode); + iso_tree_node_set_ctime(node, time(NULL)); sprintf(xorriso->info_text,"Permissions now: %-5.5o %s", mode, Text_shellsafe(path, sfe, 0)); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); @@ -2497,6 +2499,7 @@ int Xorriso_set_uid(struct XorrisO *xorriso, char *in_path, uid_t uid, if(ret<=0) return(ret); iso_tree_node_set_uid(node, uid); + iso_tree_node_set_ctime(node, time(NULL)); xorriso->volset_change_pending= 1; return(1); } @@ -2512,6 +2515,30 @@ int Xorriso_set_gid(struct XorrisO *xorriso, char *in_path, gid_t gid, if(ret<=0) return(ret); iso_tree_node_set_gid(node, gid); + iso_tree_node_set_ctime(node, time(NULL)); + xorriso->volset_change_pending= 1; + return(1); +} + + +/* @parm flag bit0= atime, bit1= ctime, bit2= mtime, bit8=no auto ctime */ +int Xorriso_set_time(struct XorrisO *xorriso, char *in_path, time_t t, + int flag) +{ + int ret; + struct iso_tree_node *node; + + ret= Xorriso_get_node_by_path(xorriso, in_path, NULL, &node, 0); + if(ret<=0) + return(ret); + if(flag&1) + iso_tree_node_set_atime(node, t); + if(flag&2) + iso_tree_node_set_ctime(node, t); + if(flag&4) + iso_tree_node_set_mtime(node, t); + if(!(flag&(2|256))) + iso_tree_node_set_ctime(node, time(NULL)); xorriso->volset_change_pending= 1; return(1); } diff --git a/libisoburn/trunk/test/xorrisoburn.h b/libisoburn/trunk/test/xorrisoburn.h index 530098a3..01abe4fb 100644 --- a/libisoburn/trunk/test/xorrisoburn.h +++ b/libisoburn/trunk/test/xorrisoburn.h @@ -104,6 +104,9 @@ int Xorriso_set_uid(struct XorrisO *xorriso, char *in_path, uid_t uid, int Xorriso_set_gid(struct XorrisO *xorriso, char *in_path, gid_t gid, int flag); +/* @parm flag bit0= atime, bit1= ctime, bit2= mtime, bit8=no auto ctime */ +int Xorriso_set_time(struct XorrisO *xorriso, char *in_path, time_t t, + int flag); #endif /* Xorrisoburn_includeD */