;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; Copyright 2011 Fidelity Information Services, Inc ; ; ; ; This source code contains the intellectual property ; ; of its copyright holder(s), and is made available ; ; under a license. If you do not know the terms of ; ; the license, please stop and do not read further. ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; dircompare ; mumps -r dircompare , where filename ; is the output of ls -lR ; of pro in either the build directory or the install directory. ; If the deletefilename is NOP then there are no delete entries. ; If the addfilename is NOP then there are no add entries. ; If the deletedirectory is NOP then there are no deldirectory entries. ; The first few lines of the three files are the copyright lines. Other comment lines may be included after ; the copyright lines and all are eaten before the data is read into the database. No spaces are allowed between the comments ; lines. ; The format of the deletefile is shown below. Its purpose is to delete files from the list of permissions and files ; which are written to standard output. ; The format of the addfile is shown below. Its purpose is to add files to the list of permissions and files ; which are written to standard output. To add files before an existing entry, the tryadd function is used. ; To add files after the last file in a directory, the same format is used in the addfile, but the filename must be ; after the last entry (i.e. must not exist). The tryinsert function adds files to the end of a directory. It ; assumes that at least one file exists in the directory. An example of both forms is given prior to the loadadd function. dircompare ; set etrap so we get debug info and exit mumps set $etrap="use $P write $zstatus,!,""Error line: "" zprint @$zposition halt" ; read the delete file into global memory kill ^delentries kill ^addentries kill ^deldirentries if 4'=$LENGTH($ZCMDLINE," ") do . write "Usage: dircompare ",! halt set infile=$PIECE($ZCMDLINE," ",1) if $ZSEARCH("foo.bar") ; ensure a new search if '$$uniquefile("infile") halt set deletefile=$PIECE($ZCMDLINE," ",2) if "NOP"'=deletefile do . if '$$uniquefile("deletefile") halt . do loaddelete(deletefile) set addfile=$PIECE($ZCMDLINE," ",3) if "NOP"'=addfile do . if '$$uniquefile("addfile") halt . do loadadd(addfile) set deldirfile=$PIECE($ZCMDLINE," ",4) if "NOP"'=deldirfile do . if '$$uniquefile("deldirfile") halt . do loaddeldir(deldirfile) set (directorydelete,nonewline)=1 open infile:(readonly) use infile:exception="GOTO EOF" for read dirname,x do; read a directory and eat the next line which is size info; ; terminated by exception="GOTO EOF" . if $DATA(^deldirentries(dirname)) set directorydelete=1 ; flag directory to delete . else do .. use $P .. if 'nonewline write ! .. write dirname,! .. set (^addmatch,directorydelete,nonewline)=0 . for use infile read x do quit:""=x .. if ""=x do quit; if it is a blank line then tryinsert ... ;in case a file(s) need(s) to be added to the end of the directory ... if $DATA(^addentries(dirname)) do tryinsert(dirname) .. if directorydelete quit .. set filename=$$getfilename(x) ; get the filename .. if $DATA(^addentries(dirname)) do tryadd(dirname,filename,infile) .. if $DATA(^delentries(dirname)),$$trydelete(dirname,filename) quit .. set ext=$$getext(filename) .. if (".hlp"=ext)!(".csh"=ext)!(".c"=ext) quit .. if (".gtc"=ext) do zapgtc(.x) set filename=$$getfilename(x) ; get the modified filename .. set perm=$PIECE(x," ",1) ; get the first piece which is the permission field .. ; if it is a symbolic link then leave it alone. Otherwise, make some permission changes .. if ("lrwxrwxrwx"'=perm)&("lrwxr-xr-x"'=perm) do ... do rmwrite(.perm),zapworld(.perm) ... if (".a"=ext)!(".o"=ext)!(".m"=ext)!(".dat"=ext)!(".gld"=ext)!(".h"=ext) do rmxall(.perm) .. use $P .. write perm," ",filename,! EOF if ('directorydelete&$DATA(^addentries(dirname))) do tryinsert(dirname) close infile halt trydelete(dirname,filename) quit $data(^delentries(dirname,filename)) tryadd(dirname,filename,infile) set ret=0 if $DATA(^addentries(dirname,filename)),$increment(^addmatch) do . use $P . for j=1:1:^addentries(dirname,filename) write ^addentries(dirname,filename,j),! . use infile . quit quit tryinsert(dirname) set nummatch=^addentries(dirname) if nummatch>^addmatch&$DATA(^addentries(dirname,"zzz_insert")) do . use $P . for j=1:1:^addentries(dirname,"zzz_insert") write ^addentries(dirname,"zzz_insert",j),! . use infile quit rmwrite(perm) ; do the equivalent of chmod a-w by translating permission w to - set perm=$TRANSLATE(perm,"w","-") quit zapgtc(str) set instr=str set a=$FIND(instr,".gtc") set str=$EXTRACT(instr,1,a-5)_$EXTRACT(instr,a,$LENGTH(instr)) ; make remove group executable to match install if not a link if '$FIND(instr,">") set str=$EXTRACT(str,1,6)_"-"_$EXTRACT(instr,8,$LENGTH(str)) ; may need to do it to the modified string if it is a link set a=$FIND(str,".gtc") set str=$EXTRACT(str,1,a-5)_$EXTRACT(str,a,$LENGTH(str)) quit makelink(perm,filename) set perm="l"_$EXTRACT(perm,2,10) set filename=filename_" -> ../"_filename quit zapworld(perm) ; get everything up to world field and add --- to tail set perm=$EXTRACT(perm,1,7)_"---" quit addgrpx(perm) set perm=$EXTRACT(perm,1,6)_"x"_$EXTRACT(perm,8,$LENGTH(perm)) quit ;do the equivalent of chmod a-x by translating x to - in perm rmxall(perm) set perm=$TRANSLATE(perm,"x","-") quit ; loaddelete(fdelete) - fdelete is the name of the delete file to load ; assume delete file starts with a directory name followed by a colon and has a blank line before each subdirectory ; assumes the last line is not blank. It is ok to have a directory with no entries under it ; example: ; ; pro: ; test.m ; file.o ; ; pro/sub1: ; test.m -> ../test.m ; ; pro/sub1/sub2: ; ; pro/sub3: ; afile.m ; ; The format of the ^delentries array for the above example is: ; ^delentries("pro:","test.m")="" ; ^delentries("pro:","file.o")="" ; ^delentries("pro/sub1:","test.m -> ../test.m")="" ; ^delentries("pro/sub3:","afile.m")="" loaddelete(fdelete) new delentries,dirname,file open fdelete:(readonly) use fdelete ; eat the copyright lines which start with a # and any other comment lines with a # in them for quit:$ZEOF read dirname do ; read the directory . if ('$find(dirname,"#")) for read file quit:$ZEOF!'$length(file) do:$length(file) .. set ^delentries(dirname,file)="" close fdelete quit ; loadadd(fadd) - fadd is the name of the add file to load ; assume addfile starts with a directory name follwed by a colon and has a blank line before each subdirectory ; assumes the last line is not blank. It is ok to have a directory with no entries under it ; the field separators must be a % ; the add entries start with a existing file before which the following permission and file will be inserted ; The exception to this rule is if the file or files is to be entered after the last entry in a directory ; In this case, you must use the file name zzz_insert which will not match any file in the directory ; There can be multiple files to insert before the current file (or after the final line if match not found) ; example: ; ; pro: ; gtmcshrc.gtc%-r-xr-x--- gtmbase ; gtmhelp.dat%-r-xr-x--- gtmcshrc ; gtmsecshr%-r-xr-x--- gtmprofile ; gtmsecshr%-r-xr-x--- gtmprofile2 ; zzz_insert%lrwxrwxrwx GETPASS.m -> ../GETPASS.m ; pro/plugin: ; pro/plugin/gtmcrypt: ; utf8%-r--r----- source.tar ; pro/plugin/gtmcrypt/utf8: ; zzz_insert%lrwxrwxrwx GETPASS.m -> ../GETPASS.m ; ^addentries("pro/plugin/gtmcrypt/utf8:")=1 ; ^addentries("pro/plugin/gtmcrypt/utf8:","zzz_insert")=1 ; ^addentries("pro/plugin/gtmcrypt/utf8:","zzz_insert",1)="lrwxrwxrwx GETPASS.m -> ../GETPASS.m" ; ^addentries("pro/plugin/gtmcrypt:")=1 ; ^addentries("pro/plugin/gtmcrypt:","utf8")=1 ; ^addentries("pro/plugin/gtmcrypt:","utf8",1)="-r--r----- source.tar" ; ^addentries("pro/plugin:")=0 ; ^addentries("pro:")=5 ; ^addentries("pro:","gtmcshrc.gtc")=1 ; ^addentries("pro:","gtmcshrc.gtc",1)="-r-xr-x--- gtmbase" ; ^addentries("pro:","gtmhelp.dat")=1 ; ^addentries("pro:","gtmhelp.dat",1)="-r-xr-x--- gtmcshrc" ; ^addentries("pro:","gtmsecshr")=2 ; ^addentries("pro:","gtmsecshr",1)="-r-xr-x--- gtmprofile" ; ^addentries("pro:","gtmsecshr",2)="-r-xr-x--- gtmprofile2" ; ^addentries("pro:","zzz_insert")=1 ; ^addentries("pro:","zzz_insert",1)="lrwxrwxrwx GETPASS.m -> ../GETPASS.m" ; The ^addentries("pro/plugin/gtmcrypt/utf8:")=1 is 1 because there is only one unique input file to match ; The ^addentries("pro/plugin/gtmcrypt:")=1 is 1 because there is only one unique input file to match ; The ^addentries("pro/plugin:")=0 because there are no files to match ; The ^addentries("pro:")=5 is 5 because there are five unique input files to match and add files before loadadd(fadd) open fadd:(readonly) use fadd ; read the first directory for read dirname quit:'$find(dirname,"#") set ^addentries(dirname)=0 use fadd for read x quit:$ZEOF do . if x="" read dirname set ^addentries(dirname)=0 . else do .. ; parse the line .. set match=$PIECE(x,"%",1) .. set add=$PIECE(x,"%",2) .. if '$DATA(^addentries(dirname,match)) set ^addentries(dirname,match)=0 .. set ^addentries(dirname)=^addentries(dirname)+1 .. set ^addentries(dirname,match)=^addentries(dirname,match)+1 .. set ^addentries(dirname,match,^addentries(dirname,match))=add use $P quit ; loaddeldir(fdeldir) - fdeldir is the name of the delete file to load ; example: ; ; pro: ; pro/sub1: ; ; The format of the ^delentries array for the above example is: ; ^deldirentries("pro:")=0 ; ^deldirentries("pro/sub1:")=0 loaddeldir(fdeldir) open fdeldir:(readonly) use fdeldir for read dirname quit:$ZEOF if '$find(dirname,"#") set ^deldirentries(dirname)=0 use $P quit uniquefile(f) new fn,ok set ok=1 set same=0 for fn="infile","deletefile","addfile","deletedirfile" do . if f'=fn,$DATA(@fn),@f=@fn set ok=0 write !,f," and ",fn," files (",@f,") can't be the same",! set same=1 quit if same quit ok if ""=$ZSEARCH(@f) set ok=0 write !,f," file: ",@f," does not exist",! quit ok getext(file) ; return the extension of the filename or null if none ; get the last piece which will be the actual filename quit $ZPARSE($piece(file," ",$length(file," ")),"TYPE") ; getfilename ; function to return the ninth field which is the file name ; there will be multiple spaces between the fields preceeding it so count them as one space ; getfilename(line) set col=1 set strlength=$LENGTH(line) for quit:(col=9) do . set position=$find(line," ") . set line=$EXTRACT(line,position,strlength) . if " "'=$EXTRACT(line,1) set col=col+1 ;next character is not a space so it is a valid field quit line