#! /usr/bin/gawk -f # Last edited on 2009-01-11 16:24:32 by stolfi BEGIN { PROG_DESC = "reformats the output of \"tar -tvf {FILE}.tar\" to size-date-name"; PROG_NAME = "tar-tvf-to-sdf"; PROG_HELP = ( \ PROG_NAME " [ -v showLinks={BOOL} ] [ -v showAll={BOOL} ] < {INFILE}.dir > {OUTFILE}.fsd" \ ); PROG_INFO = ( \ "\nNAME" \ "\n ${PROG_NAME} - ${PROG_DESC}." \ "\n" \ "\nSYNOPSIS" \ "\n ${PROG_HELP[@]}" \ "\n" \ "\nDESCRIPTION" \ "\n Reads from standard input a list of files produced by" \ "\n\"tar -tvf {FILE}.tar\" (or \"tar -tvzf {FILE}.tgz\"." \ "\n" \ "\n Normally writes to standard output the plain files in" \ "\nthat list, converted to the format" \ "\n \"{SIZE} {DATE}-{TIME} {NAME}\"" \ "\nproduced by {find-all-files-size-date}." \ "\n" \ "\n If {showLinks} is set,also outputs plain files, pipe sockets," \ "\nhard links, and symbolic links, as zero-length files; but omits" \ "\ndirectories." \ "\n" \ "\n If {showAll} is set to 1, lists entryes of al types, " \ "\nincluding directories, and expands the output format to" \ "\n \"{SIZE} {DATE}-{TIME} {TYPE} {NAME}\"" \ "\nwhere {TYPE} is " \ "\n" \ "\n \"F\" for plain files" \ "\n \"L\" for symbolic links" \ "\n \"H\" for hard links" \ "\n \"D\" for directories" \ "\n \"P\" for pipe sockets" \ "\n \"U\" for anything else" \ "\n" \ "\nOPTIONS" \ "\n None yet." \ "\n" \ "\nSEE ALSO" \ "\n find-all-files-size-date(1), tar(1)" \ "\nAUTHOR" \ "\n Created 2007-03-03 by Jorge Stolfi, Unicamp" \ ) bad_tar_time = 0; # Set to TRUE when a bad tar time format is detected. if (showLinks == "") { showLinks = 0; } if ((showTypes != 0) && (showTypes != 1)) { arg_error("bad {showTypes}"); } if (showAll == "") { showAll = 0; } if ((showAll != 0) && (showAll != 1)) { arg_error("bad {showAll}"); } } /^[d][-r]/ { # Directory. # Check field count: if (NF != 6) { data_error(("invalid field count in directory entry")); } # Skip unless asked: if (showAll) { process_line("D"); } next; } /^[-][-r]/ { # Ordinary file. # Check field count: if (NF != 6) { data_error(("invalid field count in ordinary file entry")); } process_line("F"); next; } /^[l][-r]/ { # Symbolic link. # Check field count: if ((NF != 8) || ($7 != "->")) { data_error(("invalid field count in symlink entry")); } # Skip unless asked: if (showAll || showLinks) { process_line("L"); } next; } /^[h][-r]/ { # Hard link. # Check field count: if ((NF != 9) || ($7 != "link") || ($8 != "to")) { data_error(("invalid field count in hardlink entry")); } # Skip unless asked: if (showAll || showLinks) { process_line("H"); } next; } /^[p][-r]/ { # Pipe socket. # Check field count: if (NF != 6) { data_error(("invalid field count in pipe socket entry")); } # Skip unless asked: if (showAll || showLinks) { process_line("P"); } next; } // { # Unknown entry type. # Check field count: data_warning(("unknown entry type")); if (NF != 6) { data_error(("invalid field count in entry of unknown type")); } # Skip unless asked: if (showAll) { process_line("U"); } next; } function process_line(ty) { # Outputs a line of type {ty}, reformatted: # Get fields: sz = $3; # File size in bytes. dt = $4; # Numeric date "{YYYY}-{mm}-{dd}". tm = $5; # Modification time "{HH}:{MM}:{SS}". fn = $6; # File name. if (sz !~ /^[0-9]+$/) { data_error(("bad size field \"" sz "\"")); } if (dt !~ /^[12][09][0-9][0-9]-[01][0-9]-[0-3][0-9]$/) { data_error(("bad date field \"" dt "\"")); } if (tm !~ /^[0-2][0-9][:][0-6][0-9]([:][0-6][0-9]|)$/) { data_error(("bad time field \"" tm "\"")); } # Reformat the mod-time field: gsub(/[:]/, "", tm); # Some tar versions print only the hour and minute, not the second (what a crock!): if (length(tm) == 4) { if (! bad_tar_time) { data_warning(("bad tar time format: no seconds, using \"00\"")); bad_tar_time = 1; } tm = ( tm "00" ); } if (showAll) { printf "%12s %s-%s %s %s\n", sz, dt, tm, ty, fn; } else { printf "%12s %s-%s %s\n", sz, dt, tm, fn; } } function arg_error(msg) { printf "** %s\n", msg > "/dev/stderr"; abort = 1; exit(abort); } function data_error(msg) { printf "%s:%s: ** %s\n «%s»\n", FILENAME, FNR, msg, $0 > "/dev/stderr"; abort = 1; exit(abort); } function data_warning(msg) { printf "%s:%s: %s\n «%s»\n", FILENAME, FNR, msg, $0 > "/dev/stderr"; }