home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / uucp / duucp-1.17 / AU-117b4-src.lha / src / util / FlatToHeirarchical.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-24  |  6.2 KB  |  319 lines

  1. /*
  2.  *  FLATTOHEIRARCHICAL.C
  3.  *
  4.  *  FLATTOHEIRARCHICAL FLAT/HEIR
  5.  *
  6.  *  This program will convert between the two types of news heirarchies.
  7.  *  You can safely ^C this program and restart it at anytime.  Note that
  8.  *  while simply renaming directories is much, much, much faster, I
  9.  *  decided to design the program this way to give it the capability
  10.  *  to 'pick up the pieces' when people screw up their own attempts to
  11.  *  convert.
  12.  */
  13.  
  14. #include <exec/types.h>
  15. #include <exec/nodes.h>
  16. #include <exec/lists.h>
  17. #include <exec/memory.h>
  18.  
  19. extern int mkdir(const char *);
  20. extern int rmdir(const char *);
  21.  
  22. #include <dos/dostags.h>
  23. #include <dos/exall.h>
  24.  
  25. #include <clib/dos_protos.h>
  26. #include <clib/exec_protos.h>
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <config.h>
  31. #include <version.h>
  32. #include <lib_protos.h>
  33. #include <owndevunit.h>
  34.  
  35. typedef struct FileInfoBlock FileInfoBlock;
  36. typedef struct Node Node;
  37. typedef struct List List;
  38.  
  39. void myexit(void);
  40. void ConvertToFlat(char *);
  41. void ConvertToHeir(char *);
  42.  
  43. void mksubdirs(char *);
  44. int  ScanDirTree(List *, char *, short);
  45. int  RenameScan(char *, char *);
  46.  
  47. struct Library *OwnDevUnitBase;
  48.  
  49. char ScanPath[1024];
  50. char DirPath[1024];
  51.  
  52. IDENT(".02");
  53.  
  54. int main(int ac, char **av)
  55. {
  56.     if (ac == 1) {
  57.     puts("FLATTOHEIRARCHICAL H[ier]     - convert to a heirarchical");
  58.     puts("FLATTOHEIRARCHICAL F[lat]     - convert back to a flat");
  59.     exit(0);
  60.     }
  61.  
  62.     atexit (myexit);
  63.     if ((OwnDevUnitBase = OpenLibrary ((UBYTE *) ODU_NAME, 0)) == NULL) {
  64.     printf ("Unable to open %s\n", ODU_NAME);
  65.     exit (20);
  66.     }
  67.  
  68.     strcpy(DirPath, GetConfigDir(UUNEWS));
  69.  
  70.     switch(av[1][0]) {
  71.     case 'f':
  72.     case 'F':
  73.     ConvertToFlat(DirPath);
  74.     break;
  75.     case 'h':
  76.     case 'H':
  77.     ConvertToHeir(DirPath);
  78.     break;
  79.     default:
  80.     puts("Bad option");
  81.     exit(10);
  82.     }
  83. }
  84.  
  85. void
  86. myexit()
  87. {
  88.     UnLockFiles();
  89.  
  90.     if (OwnDevUnitBase) {
  91.     CloseLibrary(OwnDevUnitBase);
  92.     OwnDevUnitBase = NULL;
  93.     }
  94. }
  95.  
  96. /*
  97.  *  Convert a heirarchical directory structure into a flat structure
  98.  */
  99.  
  100. void
  101. ConvertToFlat(dir)
  102. char *dir;
  103. {
  104.     List list;
  105.     Node *node;
  106.     short len = strlen(dir);
  107.  
  108.     /*
  109.      *    Obtain list of directories, e.g.:
  110.      *        uunews:
  111.      *        uunews:alt
  112.      *        uunews:alt/sys
  113.      *        uunews:comp
  114.      *        ...
  115.      *
  116.      *    Scan backwords to 'back out' of the tree
  117.      */
  118.  
  119.     NewList(&list);
  120.     if (ScanDirTree(&list, dir, 1) < 0) {
  121.     printf("Unable to scan %s\n", dir);
  122.     return;
  123.     }
  124.  
  125.     /*
  126.      *    Convert to a flat namespace by replacing all occurances of '/'
  127.      *    after the first len bytes to '.'
  128.      */
  129.  
  130.     while (node = RemTail(&list)) {
  131.     char *ptr;
  132.  
  133.     strcpy(dir, node->ln_Name);
  134.     while (ptr = strchr(dir + len + 1, '/'))
  135.         *ptr = '.';
  136.  
  137.     /*
  138.      *  If not the same path then create the flat directory (could
  139.      *  already exist, ignore return code) and rename all files
  140.      *  into it, then delete the heirarchical dir.
  141.      */
  142.  
  143.     printf("%-15s TO %-15s\n", node->ln_Name, dir);
  144.     if (strcmp(node->ln_Name, dir) != 0) {
  145.         mkdir(dir);
  146.         if (RenameScan(node->ln_Name, dir) == 0)
  147.         rmdir(node->ln_Name);
  148.         else
  149.         printf("Unable to move all files from %s\n", node->ln_Name);
  150.     } else {
  151.         /*
  152.          *    remove directory if empty (ignore error code, dir is not
  153.          *    necessarily empty)
  154.          */
  155.         rmdir(dir);
  156.     }
  157.     free(node);
  158.     }
  159. }
  160.  
  161. /*
  162.  *  Convert a flat structure to a heirarchical structure
  163.  */
  164.  
  165. void
  166. ConvertToHeir(dir)
  167. char *dir;
  168. {
  169.     List list;
  170.     Node *node;
  171.     short len = strlen(dir);
  172.  
  173.     /*
  174.      *    Obtain list of directories, e.g.:
  175.      *        uunews:
  176.      *        uunews:alt
  177.      *        uunews:alt.sys.amiga
  178.      *        uunews:comp
  179.      *        ...
  180.      *
  181.      *    Scan sequence does not matter, order can be anything.
  182.      */
  183.  
  184.     NewList(&list);
  185.     if (ScanDirTree(&list, dir, 1) < 0) {
  186.     printf("Unable to scan %s\n", dir);
  187.     return;
  188.     }
  189.  
  190.     /*
  191.      *    Convert to a heirarchical namespace by replacing all occurances of '.'
  192.      *    after the first len bytes to '/' and creating inbetween directories
  193.      *    as necessary.
  194.      */
  195.  
  196.     while (node = RemTail(&list)) {
  197.     char *ptr;
  198.  
  199.     strcpy(dir, node->ln_Name);
  200.     while (ptr = strchr(dir + len + 1, '.'))
  201.         *ptr = '/';
  202.  
  203.     /*
  204.      *  If not the same path then create the heir directory and
  205.      *  rename all files into it, then delete the original flat
  206.      *  directory.
  207.      */
  208.  
  209.     printf("%-15s TO %-15s\n", node->ln_Name, dir);
  210.  
  211.     if (strcmp(node->ln_Name, dir) != 0) {
  212.         mksubdirs(dir);
  213.         if (RenameScan(node->ln_Name, dir) == 0)
  214.         rmdir(node->ln_Name);
  215.         else
  216.         printf("Unable to move all files from %s\n", node->ln_Name);
  217.     } else {
  218.         /*
  219.          *    remove directory if empty (ignore error code, dir is not
  220.          *    necessarily empty)
  221.          */
  222.         rmdir(dir);
  223.     }
  224.     free(node);
  225.     }
  226. }
  227.  
  228. void
  229. mksubdirs(char *dir)
  230. {
  231.     BPTR lock;
  232.     char *ptr;
  233.  
  234.     if (lock = Lock ((UBYTE *) dir, SHARED_LOCK)) {
  235.     UnLock (lock);
  236.     return;
  237.     }
  238.     if (ptr = strrchr(dir, '/')) {
  239.     *ptr = 0;
  240.     mksubdirs(dir);
  241.     *ptr = '/';
  242.     }
  243.     mkdir(dir);
  244. }
  245.  
  246. int
  247. ScanDirTree (List *list, char *dir, short dirOnly)
  248. {
  249.     BPTR lock;
  250. #if !defined (__GNUC__)
  251.     __aligned
  252. #endif
  253.     FileInfoBlock fib;
  254.     int r = -1;
  255.     short len = strlen (dir);
  256.  
  257.     if (lock = Lock ((UBYTE *) dir, SHARED_LOCK)) {
  258.     r = 0;
  259.     if (Examine (lock, &fib)) {
  260.         while (ExNext (lock, &fib)) {
  261.         Node *node;
  262.  
  263.         if (len && dir[len-1] != ':')
  264.             strcat(dir, "/");
  265.         strcat(dir, fib.fib_FileName);
  266.  
  267.         if ((fib.fib_DirEntryType > 0 && dirOnly) || (fib.fib_DirEntryType < 0 && dirOnly == 0)) {
  268.             node = malloc(sizeof(Node) + strlen(dir) + 1);
  269.             node->ln_Name = (char *)(node + 1);
  270.             strcpy(node->ln_Name, dir);
  271.             AddTail (list, node);
  272.         }
  273.         if (fib.fib_DirEntryType > 0)
  274.             ScanDirTree(list, dir, dirOnly);
  275.         dir[len] = 0;
  276.         }
  277.     }
  278.     UnLock(lock);
  279.     }
  280.     return(r);
  281. }
  282.  
  283. /*
  284.  *
  285.  *
  286.  *
  287.  */
  288.  
  289. int
  290. RenameScan (char *sdir, char *ddir)
  291. {
  292.     List list;
  293.     short slen = strlen(sdir);
  294.     short dlen = strlen(ddir);
  295.     int r = -1;
  296.  
  297.     NewList(&list);
  298.  
  299.     strcpy(ScanPath, sdir);
  300.     if (ScanDirTree(&list, ScanPath, 0) == 0) {
  301.     Node *node;
  302.  
  303.     r = 0;
  304.     while (node = RemHead(&list)) {
  305.         /*printf("node %08lx name %s\n", node, node->ln_Name);*/
  306.  
  307.         strcpy(ddir + dlen, node->ln_Name + slen);
  308.         if (rename(node->ln_Name, ddir) < 0) {
  309.         r = -1;
  310.         printf("Unable to rename %s to %s\n", node->ln_Name, ddir);
  311.         }
  312.         free(node);
  313.     }
  314.     ddir[dlen] = 0;
  315.     }
  316.     return(r);
  317. }
  318.  
  319.