home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 18 REXX / 18-REXX.zip / eaprep.zip / EAPREP.CMD
OS/2 REXX Batch file  |  1994-03-06  |  24KB  |  422 lines

  1. /* ================================================================= */
  2. /* EAPREP.CMD - Create EA Backup/Restore Command Files               */
  3. /* ================================================================= */
  4. /*                                                                   */
  5. /* Author:         Mercer H. Harz                                    */
  6. /* Compuserve ID:  70431,150                                         */
  7. /* Written:        26 May 1992  v1.0                                 */
  8. /* Modified:       14 Aug 1993  v1.1 rewritten to handle directories */
  9. /*                                   and add comments                */
  10. /*                 09 Oct 1993  v1.2 modified for compatibility with */
  11. /*                                   4OS2 command processor          */
  12. /*                 06 Mar 1994  v1.3 corrects a bug introduced by    */
  13. /*                                   the v1.2 4OS2 modifications     */
  14. /*                                                                   */
  15. /* All standard disclaimers apply; this procedure is provided "as    */
  16. /* is and no guarantees or warranties are provided regarding its     */
  17. /* fitness for a particular task.                                    */
  18. /*                                                                   */
  19. /* This program is placed in the public domain by the author.        */
  20. /*                                                                   */
  21. /* ================================================================= */
  22. /*                                                                   */
  23. /* syntax:  EAPREP <drive> <EADir>                                   */
  24. /*                                                                   */
  25. /* <drive> is a required parameter.  It specifies the drive to be    */
  26. /*         processed.                                                */
  27. /* <EADir> is a required parameter.  It specifies the location where */
  28. /*         the DOS-visible Extended Attribute files are to be stored.*/
  29. /*         If the directory does not exist, it will be created.      */
  30. /*                                                                   */
  31. /* output:  Two command files:  EADir\x_BKP.CMD    (for BACKUP)      */
  32. /*                              EADir\x_RST.CMD    (for RESTORE)     */
  33. /*                                                                   */
  34. /*          where               x = drive being processed            */
  35. /*                                                                   */
  36. /* ================================================================= */
  37. /*                                                                   */
  38. /* This procedure creates OS/2 command files that can be executed to */
  39. /* copy and reattach extended attributes to/from files that are      */
  40. /* visible to a DOS backup/restore program that would otherwise not  */
  41. /* be able to handle Extended Attributes.  To backup HPFS volumes    */
  42. /* with your DOS backup software, you must run the backup in an OS/2 */
  43. /* DOS session rather than under native DOS.  If your hardware isn't */
  44. /* usable inside an OS/2 DOS session, you won't be able to backup an */
  45. /* HPFS partition with a DOS backup program.  You can backup FAT     */
  46. /* partitions with your DOS backup software from either an OS/2 DOS  */
  47. /* session or from native DOS.  This program (since it's written in  */
  48. /* OS/2 Rexx) must run from within an OS/2 command-line session.     */
  49. /*                                                                   */
  50. /* NOTE!!!!!                                                         */
  51. /*                                                                   */
  52. /* EAPREP does not perform the actual copy and reattach operations   */
  53. /* on the extended attributes.  It merely creates command files that */
  54. /* you must execute when you are ready to:                           */
  55. /*     1.  BACKUP -                                                  */
  56. /*         create the DOS-visible copies of the extended attributes  */
  57. /*  or 2.  RESTORE -                                                 */
  58. /*         reattach the extended attributes after a full restore     */
  59. /*         using the DOS backup/restore software                     */
  60. /*                                                                   */
  61. /* You should run EAPREP, followed by the backup command file that   */
  62. /* it creates, immediately prior to running the DOS backup software. */
  63. /* Ensure that your DOS backup software backs up the command files   */
  64. /* created by this program, as well as the files containing the EA   */
  65. /* copies that were created by the backup command file created by    */
  66. /* EAPREP.                                                           */
  67. /*                                                                   */
  68. /* EAPREP does not backup/restore the Workplace Shell desktop, even  */
  69. /* though some WPS state info may be saved in EAs.  Use one of the   */
  70. /* other utilities in the CIS OS/2 librarires for this purpose,      */
  71. /* either the WPSBackup program (WPSBKP.ZIP) or the DeskMan/2        */
  72. /* program (DSKMN2.ZIP).  You will need to contact the authors and   */
  73. /* pay a fee to receive unrestricted use of these other utilities.   */
  74. /*                                                                   */
  75. /* Currently the procedure uses a brute force method to achieve its  */
  76. /* ends, since there is no built-in way in REXX to determine whether */
  77. /* a file has extended attributes.  EAPREP builds a list of files on */
  78. /* the drive, then scans the list looking for a non-zero value in    */
  79. /* the extended attribute size field; for each hit, it creates a     */
  80. /* command in the backup and restore command files.  Files that are  */
  81. /* "in use" by OS/2 (such as OS2KRNL on my system) will generate     */
  82. /* errors during execution of the backup and restore command files.  */
  83. /* These can, in my experience, be ignored.                          */
  84. /*                                                                   */
  85. /* The backup and restore command files use the EAUTIL program that  */
  86. /* is furnished with OS/2.  Operation of EAUTIL is documented in the */
  87. /* online command reference.                                         */
  88. /*                                                                   */
  89. /* EAPREP has no selective processing capability; the entire drive   */
  90. /* will be scanned.  You can further refine the process by editing   */
  91. /* the output with any ASCII text editor.                            */
  92. /*                                                                   */
  93. /* EAPREP assumes you are not disk-space-constrained.  At a minimum, */
  94. /* when you run the backup command file generated by this procedure, */
  95. /* you will need slightly more free space on the drive than is       */
  96. /* occupied by the extended attributes on that drive.  The reason is */
  97. /* that the backup command file preserves the existing EAs as it     */
  98. /* makes copies that are visible to EA-unaware DOS programs.  To see */
  99. /* how much space you'll need, run CHKDSK against the drive before   */
  100. /* you run this procedure, then double the amount allocated to       */
  101. /* extended attributes, and add a "fudge" factor for directory space */
  102. /* overhead and wasted space at the end of clusters.  For those with */
  103. /* tight disk space requirements, there are instructions below on    */
  104. /* how to change the behavior of the backup command file so that the */
  105. /* extended attributes are deleted as the backup copy is created.    */
  106. /* EAPREP uses the <EADir> value as the ouput location for the work  */
  107. /* files and command files that are the output of this program, as   */
  108. /* well as the storage directory for the extended attribute copies.  */
  109. /* Work files could occupy several hundred kilobytes but are deleted */
  110. /* at the end of the program.  Each file or directory with EAs adds  */
  111. /* about 90 bytes to the backup and restore command files.           */
  112. /*                                                                   */
  113. /* The backup copies of the extended attributes will be stored in the*/
  114. /* location pointed to by the <EADir> parameter.  They are stored as */
  115. /* a set of files named dnnnnnnn.EA, where "d" represents the drive  */
  116. /* letter being processed, and "nnnnnnn" is a sequence number.  The  */
  117. /* directory, if it does not currently exist, will be created by     */
  118. /* this program, but its existence will not be checked for by the    */
  119. /* generated command files.  It is not necessary, but it is probably */
  120. /* a good idea, for you to empty the <EADir> subdirectory before     */
  121. /* running this program.  The naming convention allows you to store  */
  122. /* all DOS-visible EA files for all drives on your system in the     */
  123. /* same location, though you do not have to do so.                   */
  124. /*                                                                   */
  125. /* The restore command file contains the mirror commands required to */
  126. /* join the EAs to their owners after you've restored the system     */
  127. /* from a DOS backup.                                                */
  128. /*                                                                   */
  129. /* The backup command file uses the /P /R /S switches; these split   */
  130. /* (/S) the EAs into a backup copy, preserving (/P) the EAs with the */
  131. /* parent file, and replacing (/R) any existing backup copy of the   */
  132. /* parent's EAs that might be stored in the <EADir> subdirectory.    */
  133. /*                                                                   */
  134. /* The restore command file uses the /O /J switches; these join (/J) */
  135. /* the EAs to the parent file, overlaying (/O) any existing EAs      */
  136. /* associated with the parent.  The backup copy will be erased.  To  */
  137. /* prevent the erasure of the backup, add the /P switch to these     */
  138. /* commands.  If, rather than overlaying the current EAs (if any),   */
  139. /* you want to merge the backup EAs with the current EAs, use the    */
  140. /* /M switch rather than /O for the restoration.                     */
  141. /*                                                                   */
  142. /* Long file names may not operate properly with DOS backup/restore  */
  143. /* software; this will depend on whether OS/2 will properly create   */
  144. /* filenames in 8.3 format when backing up/restoring with DOS s/w.   */
  145. /* I haven't tested long file names because I don't have any HPFS    */
  146. /* volumes right now.  My advice is to stick with 8.3 filenames on   */
  147. /* HPFS volumes until you have long-name-aware backup/restore s/w.   */
  148. /*                                                                   */
  149. /* ================================================================= */
  150.  
  151. /* ------------------------------------------------------------------ */
  152. /*  MAKE COMMAND-LINE ARGUMENTS AVAILABLE                             */
  153. /* ------------------------------------------------------------------ */
  154.     arg Drive EADir
  155.  
  156. /* ------------------------------------------------------------------ */
  157. /*  MAKE REXX UTILITY FUNCTIONS AVAILABLE                             */
  158. /* ------------------------------------------------------------------ */
  159.     call RxFuncAdd 'SysLoadFuncs','RexxUtil','SysLoadFuncs'
  160.     call SysLoadFuncs
  161.  
  162. /* ------------------------------------------------------------------ */
  163. /*  SAY HELLO                                                         */
  164. /* ------------------------------------------------------------------ */
  165.  
  166.     Version = "1.3"
  167.     Written = "6 Mar 1994"
  168.  
  169.     TimeStamp = time()
  170.     DateStamp = date()
  171.     hdr = "EAP"
  172.     say " "
  173.     say hdr"00I: EAPREP v"Version" - Ext. Attribute Backup/Restore Preparation"
  174.     say hdr"01I: Written by Mercer H. Harz, "Written"."
  175.     say hdr"02I: Starting at "TimeStamp" on "DateStamp"."
  176.     say " "
  177.  
  178. /* ------------------------------------------------------------------ */
  179. /*  CHECK FOR PRESENCE OF COMMAND-LINE ARGUMENTS                      */
  180. /* ------------------------------------------------------------------ */
  181.     if length(Drive) = 0   then signal USAGE
  182.     if length(EADir) = 0   then signal USAGE
  183.     if right(EADir,1) = '\' then
  184.         EADir = substr(EADir, 1, length(EADir) - 1)
  185.  
  186. /* ------------------------------------------------------------------ */
  187. /*  CHECK FOR VALIDITY OF SELECTED DRIVE                              */
  188. /* ------------------------------------------------------------------ */
  189.     ValDrives = SysDriveMap()
  190.     Drive = left(Drive,1)
  191.     if pos(Drive,ValDrives) = 0 then signal BADDRV
  192.  
  193. /* ------------------------------------------------------------------ */
  194. /*  CHECK FOR VALIDITY OF SELECTED EA STORAGE DIRECTORY               */
  195. /* ------------------------------------------------------------------ */
  196.     CurrDir = directory()                   /* save current directory */
  197.     CheckDir = directory(EADir)             /* does EADir exist?      */
  198.     if CheckDir = EADir then signal SETWORK /* if so, continue        */
  199.     rc = SysMkDir(EADir)                    /* if not, create it      */
  200.     if rc <> 0 then signal BADMD            /* advise user of failure */
  201.     say hdr"03W: Created directory "EADir
  202.  
  203. /* ------------------------------------------------------------------ */
  204. /*  SETUP AND INITIALIZE THE WORK FILES                               */
  205. /* ------------------------------------------------------------------ */
  206. SETWORK:
  207.     CurrDir = directory(CurrDir)            /* return to starting dir */
  208.  
  209.     WorkFile = EADir'\'Drive'.wrk'
  210.     BackupFile = EADir'\'Drive'_bkp.cmd'    /* now initialize the     */
  211.     RestoreFile = EADir'\'Drive'_rst.cmd' /* work files               */
  212.     if length(stream(BackupFile,'c','query exists')) > 0 then
  213.         call SysFileDelete(BackupFile)
  214.     if length(stream(RestoreFile,'c','query exists')) > 0 then
  215.         call SysFileDelete(RestoreFile)
  216.  
  217. /* ------------------------------------------------------------------ */
  218. /*  CREATE THE WORK FILE DIRECTORY LISTING IN HPFS FORMAT             */
  219. /* ------------------------------------------------------------------ */
  220.     say hdr'10I: Obtaining directory for drive 'Drive':... please be patient...'
  221.     say " "
  222.  
  223.     '@dir 'Drive':\*.* /N /S /A /O:GN > 'WorkFile
  224.     if rc <> 0 then signal BADDIR
  225.  
  226. /* ------------------------------------------------------------------ */
  227. /*  OPEN THE WORK FILES FOR USE BY THE PROGRAM                        */
  228. /* ------------------------------------------------------------------ */
  229.     Result = stream(WorkFile,'c','open read')
  230.     if Result <> "READY:" then signal BADWRK
  231.  
  232.     Result = stream(BackupFile,'c','open write')
  233.     if Result <> "READY:" then signal BADBKP
  234.  
  235.     Result = stream(RestoreFile,'c','open write')
  236.     if Result <> "READY:" then signal BADRST
  237.  
  238. /* ------------------------------------------------------------------ */
  239. /*  FINAL INITIALIZATIONS                                             */
  240. /* ------------------------------------------------------------------ */
  241.     EACount = 0         /* number of objects with extended attributes */
  242.     NumDirs = 0         /* number of (sub)directories processed       */
  243.     NumFiles = 0        /* number of directory entries processed      */
  244.  
  245.     say hdr"11I: Directories       Entries      Entries"
  246.     say hdr"12I:   Processed     Processed     with EAs"
  247.     say hdr"13I: -----------     ---------     --------"
  248.     parse value SysCurPos() with row col
  249.  
  250. /* ------------------------------------------------------------------ */
  251. /*   MAIN PROCESSING LOOP  ---  look for entries with EAs             */
  252. /* ------------------------------------------------------------------ */
  253.     do until lines(WorkFile) = 0    /* run until end-of-file          */
  254.         buff = linein(WorkFile)
  255.         parse var buff word1 word2 word3 EASize FName word6
  256.         if buff = " " then iterate           /* --------------------- */
  257.         if word1 = "The" then iterate        /* Ignore the whitespace */
  258.         if word1 = "Totals" then iterate     /* in the directory      */
  259.         if word1 = "Volume" then iterate     /* listing               */
  260.         if word2 = "bytes" then iterate      /*                       */
  261.         if word2 = "file(s)" then iterate    /* --------------------- */
  262.         if word1 = "Directory" then do
  263.             NumDirs = NumDirs + 1      /* perform control-break pro-  */
  264.                                        /* cessing for each directory  */
  265.             Len = length(word3)                           /*  v1.3    */
  266.             LastChar  = substr(word3,Len,1)               /*  v1.3    */
  267.             if LastChar <> '\' then word3 = word3'\'      /*  v1.3    */
  268.             LastSlash = lastpos('\',word3)                /*  v1.2    */
  269.             CurrentDir = substr(word3,1,(LastSlash-1))    /*  v1.2    */
  270.             rc = SysCurPos(row,0)
  271.             buff = hdr'14I: 'right(NumDirs,11)'     'right(NumFiles,9)'     'right(EACount,8)
  272.             call charout ,buff
  273.             iterate
  274.         end
  275.         NumFiles = NumFiles + 1    /* this is a file/directory entry  */
  276.         if EASize > 0 then do      /* if it has EAs attached, create  */
  277.             EACount = EACount + 1  /* the backup/restore commands     */
  278.             EAIndex = right(EACount,7,'0')
  279.             DataFile = CurrentDir'\'FName
  280.             Len  = length(DataFile)
  281.             if Len < 50 then Len = 50
  282.             DataFile = left(DataFile,Len,' ')
  283.             EAFile  = EADir'\'Drive||EAIndex'.EA'
  284.             Len  = length(EAFile)
  285.             if Len < 20 then Len = 20
  286.             EAFile  = left(EAFile,Len,' ')
  287.             BackupCmd  = 'EAUTIL 'DataFile' 'EAFile' /P /R /S'
  288.             RestoreCmd = 'EAUTIL 'DataFile' 'EAFile' /O /J'
  289.             call lineout BackupFile, BackupCmd
  290.             call lineout RestoreFile, RestoreCmd
  291.         end
  292.     end
  293.     rc = SysCurPos(row,0)
  294.     buff = hdr'14I: 'right(NumDirs,11)'     'right(NumFiles,9)'     'right(EACount,8)
  295.     call charout ,buff
  296.  
  297. /* ------------------------------------------------------------------ */
  298. /*   WE'RE DONE - TIME TO CLEAN UP AFTER OURSELVES                    */
  299. /* ------------------------------------------------------------------ */
  300.     Result = stream(WorkFile,'c','close')
  301.     Result = stream(BackupFile,'c','close')
  302.     Result = stream(RestoreFile,'c','close')
  303.     call SysFileDelete(WorkFile)
  304.     if EACount = 0 then do
  305.         call SysFileDelete(BackupFile)
  306.         call SysFileDelete(RestoreFile)
  307.     end
  308.  
  309.     say " "
  310.     say " "
  311.     if EACount > 0 then do
  312.         say hdr"96I: "EACount" Commands to BACKUP EAs are stored in "BackupFile
  313.         say hdr"97I: "EACount" Commands to RESTORE EAs are stored in "RestoreFile
  314.       end
  315.     else say hdr"98W: EA Backup and Restore command files were not created."
  316.     signal ENDPGM
  317.  
  318. /* ------------------------------------------------------------------ */
  319. /*   DIRECTORY WORK FILE COULD NOT BE CREATED                         */
  320. /* ------------------------------------------------------------------ */
  321. BADDIR:
  322.     savrc = rc
  323.     call SysFileDelete(WorkFile)
  324.     say hdr"51E: Sorry, there was a problem obtaining a directory for drive "Drive":."
  325.     rc = savrc
  326.     signal DOSERR   /*  clean up after ourselves   */
  327.  
  328. /* ------------------------------------------------------------------ */
  329. /*   DIRECTORY WORK FILE COULD NOT BE OPENED FOR INPUT                */
  330. /* ------------------------------------------------------------------ */
  331. BADWRK:
  332.     call SysFileDelete(WorkFile)
  333.     say hdr"53E: Sorry, there was a problem reading directory file "WorkFile"."
  334.     signal BADSTRM  /*  clean up after ourselves   */
  335.  
  336. /* ------------------------------------------------------------------ */
  337. /*   BACKUP FILE COULD NOT BE OPENED FOR OUTPUT                       */
  338. /* ------------------------------------------------------------------ */
  339. BADBKP:
  340.     call SysFileDelete(BackupFile)
  341.     call SysFileDelete(WorkFile)
  342.     say hdr"54E: Sorry, there was a problem opening backup command file "BackupFile"."
  343.     signal BADSTRM  /*  clean up after ourselves   */
  344.  
  345. /* ------------------------------------------------------------------ */
  346. /*   RESTORE FILE COULD NOT BE OPENED FOR OUTPUT                      */
  347. /* ------------------------------------------------------------------ */
  348. BADRST:
  349.     call SysFileDelete(RestoreFile)
  350.     call SysFileDelete(BackupFile)
  351.     call SysFileDelete(WorkFile)
  352.     say hdr"55E: Sorry, there was a problem opening restore command file "RestoreFile"."
  353.     signal BADSTRM  /*  clean up after ourselves   */
  354.  
  355. /* ------------------------------------------------------------------ */
  356. /*   ERROR ACCESSING STREAM DEVICE                                    */
  357. /* ------------------------------------------------------------------ */
  358. BADSTRM:
  359.     say hdr"59E: Stream Error ("Reason")"
  360.     signal ENDPGM
  361.  
  362. /* ------------------------------------------------------------------ */
  363. /*   USER HAS NOT ENTERED A VALID DRIVE LETTER                        */
  364. /* ------------------------------------------------------------------ */
  365. BADDRV:
  366.     say hdr"61E: Drive "Drive": is not a valid selection."
  367.     say hdr"62W: Please select a drive from the following list."
  368.     say hdr"63W: "ValDrives
  369.     signal ENDPGM
  370.  
  371. /* ------------------------------------------------------------------ */
  372. /*   UNABLE TO CREATE EA STORAGE DIRECTORY                            */
  373. /* ------------------------------------------------------------------ */
  374. BADMD:
  375.     say hdr"71E: Sorry, unable to create "EADir
  376.     signal DOSERR
  377.  
  378. /* ------------------------------------------------------------------ */
  379. /*   TRANSLATE DOS ERROR CODES                                        */
  380. /* ------------------------------------------------------------------ */
  381. DOSERR:
  382.     select
  383.        when rc =   2 then reason = "File not found."
  384.        when rc =   3 then reason = "Path not found."
  385.        when rc =   5 then reason = "Access Denied."
  386.        when rc =  26 then reason = "Not a DOS disk."
  387.        when rc =  87 then reason = "Invalid Parameter."
  388.        when rc = 108 then reason = "Drive Locked."
  389.        when rc = 206 then reason = "Filename exceeds range."
  390.        otherwise          reason = "Unknown Error."
  391.     end
  392.     say hdr"90E: Return Code = "right(rc,3,'0')" : "reason
  393.     signal ENDPGM
  394.  
  395. /* ------------------------------------------------------------------ */
  396. /*   USER HAS NOT ENTERED A REQUIRED PARAMETER                        */
  397. /* ------------------------------------------------------------------ */
  398. USAGE:
  399.     say hdr"80E: A required parameter is missing."
  400.     say "  "
  401.     say hdr"81I: Usage:"
  402.     say hdr"82I:        EAPREP  Drive  EADir"
  403.     say hdr"83I: where"
  404.     say hdr"84I:        Drive  = disk drive to be processed"
  405.     say hdr"85I:        EADir  = location (on any drive with adequate space)"
  406.     say hdr"86I:                 where EAPREP will store its output and the"
  407.     say hdr"87I:                 files containing extended attribute copies."
  408.     say "  "
  409.     say hdr"88I: Both parameters are required; no defaults are taken."
  410.     say hdr"89I: EADir will be created if it does not exist."
  411.  
  412. /* ------------------------------------------------------------------ */
  413. /*   ALL ROUTINES EXIT FROM THIS POINT TO ENSURE CORRECT CLEANUP      */
  414. /* ------------------------------------------------------------------ */
  415. ENDPGM:
  416.     call SysDropFuncs
  417.     TimeStamp = time()
  418.     DateStamp = date()
  419.     say " "
  420.     say hdr"99I: Finished at "TimeStamp" on "DateStamp"."
  421.     return
  422.