home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 1 / FFMCD01.bin / bbs / libdisks / d700t799 / disk774.lha / ExtraCmds / src / DirTree.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-05  |  9.4 KB  |  364 lines

  1. /* Copyright (c) 1992 Torsten Poulin
  2.  * 23-Feb-92 Version 1
  3.  *
  4.  * The bit-map code in this program was picked up from Dr. Dobb's
  5.  * I think, but I don't remember which volume ;-(
  6.  */
  7.  
  8. /* Define LOCKALL to ensure that directories being examined
  9.  * don't disappear before we're done with them.
  10.  * The disadvantage is that we use more memory.
  11.  */
  12. #define LOCKALL
  13.  
  14.  
  15. /****** English:DIRTREE ***************************************************
  16. *
  17. *   FORMAT
  18. *       DirTree [DIR] {<directory>} [NOHEAD]
  19. *
  20. *   TEMPLATE
  21. *       DIR/A/M,NOHEAD/S
  22. *
  23. *   PURPOSE
  24. *       To print sub-directory trees.
  25. *
  26. *   SPECIFICATION
  27. *       DirTree displays the sub-directory trees for the directories
  28. *       or volumes specified in the DIR argument.  The NOHEAD switch
  29. *       suppresses the printing of the header information.
  30. *
  31. *   EXAMPLE
  32. *           1> DIRTREE ram:
  33. *           Directory tree for "ram:" on Saturday 22-Feb-92
  34. *
  35. *           Ram Disk
  36. *           +---Clipboards
  37. *           +---env
  38. *           |   `---sys
  39. *           |  
  40. *           `---T
  41. *
  42. *   SEE ALSO
  43. *       DIR, LIST
  44. *
  45. ***************************************************************************
  46. *
  47. */
  48. /****** dansk:DIRTREE *****************************************************
  49. *
  50. *   FORMAT
  51. *       DirTree [DIR] {<katalog>} [NOHEAD]
  52. *
  53. *   SKABELON
  54. *       DIR/A/M,NOHEAD/S
  55. *
  56. *   FORMÅL
  57. *       At udskrive underkatalogtræer.
  58. *
  59. *   SPECIFIKATION
  60. *       DirTree viser underkatalogtræer for de kataloger eller diske
  61. *       som er givet ved argumentet DIR.  Kontakten NOHEAD
  62. *       undertrykker udskrivningen af overskriftinformationen.
  63. *
  64. *   EKSEMPEL
  65. *           1> DIRTREE ram:
  66. *           Directory tree for "ram:" on Saturday 22-Feb-92
  67. *
  68. *           Ram Disk
  69. *           +---Clipboards
  70. *           +---env
  71. *           |   `---sys
  72. *           |  
  73. *           `---T
  74. *
  75. *   SE OGSÅ
  76. *       DIR, LIST
  77. *
  78. ***************************************************************************
  79. *
  80. */
  81.  
  82.  
  83. #include <exec/types.h>
  84. #include <exec/memory.h>
  85. #include <dos/dos.h>
  86. #include <dos/dostags.h>
  87. #include <dos/datetime.h>
  88. #include <string.h>
  89.  
  90. #include <proto/exec.h>
  91. #include <proto/dos.h>
  92.  
  93. /* my include files are for early V36, so ... */
  94. #pragma libcall UtilityBase Stricmp A2 9802
  95. LONG Stricmp(char *, char *);
  96.  
  97. #define BAR "|   "
  98. #define ELL "`---"
  99. #define TEE "+---"
  100.  
  101. struct nameList {
  102.     struct nameList *next;
  103.     char *name;
  104. #ifdef LOCKALL
  105.     BPTR lock;
  106. #endif
  107. };
  108.  
  109. typedef struct global {
  110.     struct Library      *SysBase;
  111.     struct DosLibrary   *DOSBase;
  112.     struct Library      *UtilityBase;
  113.  
  114.     char Map[64 / 8];
  115. } Global;
  116.  
  117. char const *version = "\0$VER: DirTree 37.1 (23.2.92) ©1992 Torsten Poulin";
  118.  
  119. static VOID setbit(Global *global, LONG c, LONG val);
  120. static VOID print_bars(Global *global, LONG depth, LONG terminate);
  121. static LONG printdtree(Global *global, UBYTE *dname, LONG others);
  122. LONG dirtree(Global *global, char *dirname, BOOL nohead);
  123.  
  124.  
  125. LONG entrypoint(VOID)
  126. {
  127.     struct Library      *SysBase;
  128.     struct DosLibrary   *DOSBase;
  129.     struct Library      *UtilityBase;
  130.     Global *global;
  131.         
  132.     struct RDArgs *args;
  133.     LONG   arg[2];
  134.     LONG   rc = RETURN_OK;
  135.     UBYTE  **dir;
  136.  
  137.     arg[0] = arg[1] = 0L;
  138.     
  139.     SysBase = *(struct Library **) 4L;
  140.     
  141.     if(!(global = AllocMem(sizeof(Global), MEMF_PUBLIC | MEMF_CLEAR)))
  142.         return RETURN_FAIL;
  143.  
  144.     global->SysBase = SysBase;
  145.     if(!(global->DOSBase = DOSBase = (struct DosLibrary *)
  146.                         OpenLibrary("dos.library", 37L)))
  147.     {
  148.         rc = RETURN_FAIL;
  149.         goto noDOS;
  150.     }
  151.     if(!(global->UtilityBase = UtilityBase = 
  152.                         OpenLibrary("utility.library", 37L)))
  153.     {
  154.         rc = RETURN_FAIL;
  155.         goto noUtility;
  156.     }
  157.                                                                         
  158.     if(args = ReadArgs("DIR/A/M,NOHEAD/S", arg, NULL))
  159.     {
  160.         for(dir = (UBYTE **) *arg; *dir && rc == RETURN_OK; dir++)
  161.             rc = dirtree(global, *dir, (BOOL) arg[1]);
  162.         FreeArgs(args);
  163.     }
  164.     else
  165.     {
  166.         LONG err = IoErr();
  167.         PrintFault(err, "DirTree");
  168.         rc = RETURN_ERROR;
  169.     }
  170.     
  171.     CloseLibrary(UtilityBase);
  172.  noUtility:
  173.     CloseLibrary((struct DosBase *) DOSBase);
  174.  noDOS:
  175.     FreeMem(global, sizeof(Global));
  176.     return rc;
  177. }
  178.  
  179.  
  180. #define testbit(x)  ( global->Map[x >> 3] & (1 << (x & 0x07)) )
  181.  
  182. static VOID setbit(Global *global, LONG c, LONG val)
  183. {
  184.     if(val)
  185.         global->Map[c >> 3] |= 1 << (c & 0x07);
  186.     else
  187.         global->Map[c >> 3] &= ~(1 << (c & 0x07));
  188. }
  189.  
  190.  
  191. static VOID print_bars(Global *global, LONG depth, LONG terminate)
  192. {
  193.     struct DosLibrary *DOSBase = global->DOSBase;
  194.     LONG i;
  195.     
  196.     for(i = 0; i < depth - 1; i++)
  197.         PutStr(testbit(i) ? BAR : "    ");
  198.         
  199.     if(terminate)
  200.         PutStr("\n");
  201. }
  202.  
  203.  
  204. static LONG printdtree(Global *global, UBYTE *dname, LONG others)
  205. {
  206.     struct Library    *SysBase      = global->SysBase;
  207.     struct DosLibrary *DOSBase      = global->DOSBase;
  208.     struct Library    *UtilityBase  = global->UtilityBase;
  209.     
  210.     struct FileInfoBlock *m;
  211.     BPTR   lock, oldlock;
  212.     static LONG depth = -1;
  213.     LONG   count = 0;
  214.     LONG   rc = RETURN_OK;
  215.     ULONG  ADOtag = TAG_DONE;
  216.     struct nameList *list, *p;
  217.     BOOL   OutOfMemory = FALSE;
  218.  
  219.     list = NULL;
  220.  
  221.     m = AllocDosObject(DOS_FIB, (struct TagItem *) &ADOtag);
  222.     
  223.     if(lock = Lock(dname, SHARED_LOCK))
  224.     {
  225.         oldlock = CurrentDir(lock);
  226.         if(Examine(lock, m))
  227.         {
  228.             if(m->fib_DirEntryType < 0)
  229.             {
  230.                 PrintFault(ERROR_OBJECT_WRONG_TYPE, dname);
  231.                 CurrentDir(oldlock);
  232.                 UnLock(lock);
  233.                 FreeDosObject(DOS_FIB, m);
  234.                 return RETURN_WARN;
  235.             }
  236.  
  237.             if(++depth)
  238.             {
  239.                 print_bars(global, depth, 0);
  240.                 PutStr(others ? TEE : ELL);
  241.             }
  242.             PutStr(m->fib_FileName /*dname*/);
  243.             PutStr("\n");
  244.  
  245.             while(ExNext(lock, m))
  246.                 if(m->fib_DirEntryType > 0)
  247.                 {
  248.                     struct nameList *newnode;
  249.  
  250.                     /* Store the directory name */
  251.                     if(!(newnode = AllocMem(sizeof(struct nameList),
  252.                                             MEMF_PUBLIC)))
  253.                     {
  254.                         PrintFault(ERROR_NO_FREE_STORE, "DirTree");
  255.                         rc = RETURN_FAIL;
  256.                         OutOfMemory = TRUE;
  257.                         break;
  258.                     }
  259.                     if(!(newnode->name = AllocMem(strlen(m->fib_FileName) + 1,
  260.                                                   MEMF_PUBLIC)))
  261.                     {
  262.                         PrintFault(ERROR_NO_FREE_STORE, "DirTree");
  263.                         rc = RETURN_FAIL;
  264.                         OutOfMemory = TRUE;
  265.                         break;
  266.                     }
  267.                     strcpy(newnode->name, m->fib_FileName);
  268. #ifdef LOCKALL
  269.                     newnode->lock = Lock(m->fib_FileName, SHARED_LOCK);
  270. #endif
  271.                     /* Insert */
  272.                     newnode->next = NULL;
  273.                 
  274.                     if(list == NULL)    /* insert into empty list */
  275.                         list = newnode;
  276.                     else
  277.                     {
  278.                         /* inserting into nonempty list */
  279.                         p = list;
  280.  
  281.                         if(Stricmp(m->fib_FileName, p->name) < 0)
  282.                         {
  283.                             /* insert before first node */
  284.                             newnode->next = list;
  285.                         list = newnode;
  286.                         }
  287.                         else
  288.                         {
  289.                             /* general case */
  290.                         for(; p->next; p = p->next)
  291.                             if(Stricmp(m->fib_FileName,p->next->name) < 0)
  292.                                 break;
  293.                         newnode->next = p->next;
  294.                         p->next = newnode;
  295.                         }
  296.                     }
  297.                     ++count;
  298.                 }
  299.         }
  300.  
  301.         /* Traverse the list and free up memory */
  302.         for(p = list; p; )
  303.         {
  304.             struct nameList *remember;
  305.                 
  306.             remember = p;
  307.             if(!OutOfMemory)
  308.             {
  309.                 --count;
  310.                 setbit(global, depth, count);
  311.                 rc = printdtree(global, p->name, count);
  312.             }
  313.             p = p->next;
  314. #ifdef LOCKALL
  315.             UnLock(remember->lock);
  316. #endif
  317.             FreeMem(remember->name, strlen(remember->name) + 1);
  318.             FreeMem(remember, sizeof(struct nameList));
  319.         }
  320.         CurrentDir(oldlock);
  321.         UnLock(lock);
  322.     }
  323.     else
  324.     {
  325.         LONG err = IoErr();
  326.         PrintFault(err, dname);
  327.         rc = RETURN_ERROR;
  328.     }
  329.     if(!others)
  330.         print_bars(global, depth, 1);
  331.     --depth;
  332.   
  333.     FreeDosObject(DOS_FIB, m);  
  334.     return rc;
  335. }
  336.  
  337.  
  338. LONG dirtree(Global *global, char *dirname, BOOL nohead)
  339. {
  340.     struct DosLibrary *DOSBase = global->DOSBase;
  341.     struct DateTime dt;
  342.     char day[LEN_DATSTRING], date[LEN_DATSTRING];
  343.     
  344.     if(!nohead)
  345.     {
  346.         DateStamp(&dt.dat_Stamp);
  347.         dt.dat_Format  = FORMAT_DOS;
  348.         dt.dat_Flags   = NULL;
  349.         dt.dat_StrDay  = day;
  350.         dt.dat_StrDate = date;
  351.         dt.dat_StrTime = NULL;
  352.         DateToStr(&dt);
  353.  
  354.         PutStr("Directory tree for \"");
  355.         PutStr(dirname);
  356.         PutStr("\" on ");
  357.         PutStr(day);
  358.         PutStr(" ");
  359.         PutStr(date);
  360.         PutStr("\n\n");
  361.     }
  362.     return printdtree(global, dirname, 0);
  363. }
  364.