home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 620.lha / mountshare / mountshare.c < prev    next >
C/C++ Source or Header  |  1992-02-16  |  10KB  |  461 lines

  1. ;/*-
  2. dcc -r -ms -proto -new -v mountshare.c -o mountshare
  3. quit
  4. *   ^^ This is PURE code!
  5. */
  6. /*-
  7.  * $Id$
  8.  * $Log$
  9.  *
  10.  * SHARE.C
  11.  *
  12.  * This code is (C) Copyright 1992 by Olaf Seibert. All rights reserved.
  13.  * May not be used or copied without a licence.
  14. -*/
  15.  
  16. #include <functions.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20.  
  21. #ifndef EXEC_TYPES_H
  22. #include <exec/types.h>
  23. #endif
  24. #ifndef EXEC_MEMORY_H
  25. #include <exec/memory.h>
  26. #endif
  27. #ifndef LIBRARIES_DOSEXTENS_H
  28. #include <libraries/dosextens.h>
  29. #endif
  30. #ifndef LIBRARIES_FILEHANDLER_H
  31. #include <libraries/filehandler.h>
  32. #endif
  33. #ifndef RESOURCES_FILESYSRES_H
  34. #include <resources/filesysres.h>
  35. #endif
  36.  
  37. extern struct DosLibrary *DOSBase;
  38.  
  39. typedef void   *(*fptr) (long *, void *);
  40.  
  41. struct DosInfo *DosInfo;
  42. struct FileSysResource *FileSysResource;
  43. char        CreateFileSysEntry,
  44.         TryLoadHandler,
  45.         TryHandlerNames = 1,
  46.         TryDosType = 1,
  47.         TryFileSysEntry;
  48.  
  49. #define nodb(x)   x
  50. #define db(x) /* x */
  51.  
  52. void
  53. printbstr(BPTR bstr)
  54. {
  55.     char       *str = BADDR(bstr);
  56.  
  57.     if (bstr)
  58.     fwrite(str + 1, str[0], 1, stdout);
  59.     else
  60.     printf("<NULL>");
  61. }
  62.  
  63. void           *
  64. traverse_bcpl(fptr function, BPTR start, void *context)
  65. {
  66.     db(printf("traverse_bcpl: %x -> ", start);)
  67.     start = BADDR(start);
  68.     db(printf("%x\n", start);)
  69.     while (start && (context = function((long *) start, context))) {
  70.     start = BADDR(((long *) start)[0]);
  71.     db(printf("traverse_bcpl: next is %x\n", start);)
  72.     }
  73.     return context;
  74. }
  75.  
  76. struct c1 {
  77.     char       *name;
  78.     struct DeviceNode *dn;
  79. };
  80.  
  81. void           *
  82. compare_name(long *node, void *context)
  83. {
  84.     struct c1       *c1 = (struct c1 *) context;
  85.     struct DeviceNode *dnv = (struct DeviceNode *) node;
  86.     char       *dnvname = BADDR(dnv->dn_Name);
  87.  
  88.     db(printf("compare_name: ");
  89.        printbstr(dnv->dn_Name);
  90.        printf("\n");)
  91.     if (dnv->dn_Type == DLT_DEVICE &&
  92.     dnvname[0] == strlen(c1->name) &&
  93.     strnicmp(c1->name, &dnvname[1], dnvname[0]) == 0) {
  94.     c1->dn = dnv;
  95.     db(printf("Type %ld Stack %ld Pri %ld Start %lx SegList %lx Task %lx GV %ld\n",
  96.            dnv->dn_Type,
  97.            dnv->dn_StackSize,
  98.            dnv->dn_Priority,
  99.            dnv->dn_Startup,
  100.            dnv->dn_SegList,
  101.            dnv->dn_Task,
  102.            dnv->dn_GlobalVec);)
  103.     return NULL;
  104.     }
  105.     return context;
  106. }
  107.  
  108. struct DeviceNode *
  109. find_name(char *name)
  110. {
  111.     struct c1        dn;
  112.  
  113.     dn.name = name;
  114.     dn.dn = NULL;
  115.  
  116.     traverse_bcpl(compare_name, DosInfo->di_DevInfo, &dn);
  117.  
  118.     return dn.dn;
  119. }
  120.  
  121. void
  122. load_handler(struct DeviceNode *dn)
  123. {
  124.     char        name[256];
  125.     char       *handler;
  126.  
  127.     if (!TryLoadHandler)
  128.     return;
  129.  
  130.     nodb(if (dn->dn_SegList != 0) {
  131.     printf("Handler already loaded!\n");
  132.     return;
  133.     })
  134.     nodb(if (dn->dn_Task != 0) {
  135.     printf("Handler already running!\n");
  136.     return;
  137.     })
  138.     handler = BADDR(dn->dn_Handler);
  139.     if (handler == 0) {
  140.     printf("Device has no Handler file\n");
  141.     return;
  142.     }
  143.     strncpy(name, handler + 1, *handler);
  144.     name[*handler] = '\0';
  145.  
  146.     dn->dn_SegList = LoadSeg(name);
  147.     if (dn->dn_SegList) {
  148.     printf("%s loaded.\n", name);
  149.     } else {
  150.     printf("Loading %s failed: error %ld.\n", name, IoErr());
  151.     }
  152. }
  153.  
  154. /*
  155.  * Try to get the DosType values from the mountlist. This is quite a
  156.  * work!
  157.  * We must be reasonable sure that the dn_Startup fields both refer
  158.  * to a FileSysStarupMsg. They must both be pointers (and not some
  159.  * small integral values, as used to distinguish CON and RAW, for
  160.  * example). We also assume that fssm_Unit values <= 0xFFFF.
  161.  */
  162.  
  163. unsigned long
  164. get_dostype(struct DeviceNode *dn)
  165. {
  166.     struct FileSysStartupMsg *dnmsg;
  167.  
  168.     dnmsg = BADDR(dn->dn_Startup);
  169.     if (dnmsg &&
  170.     (long)dnmsg > 100 &&
  171.     dnmsg->fssm_Unit <= 0x0000FFFF
  172.     ) {
  173.     long           *dnenv = BADDR(dnmsg->fssm_Environ);
  174.  
  175.     /* actually struct DosEnvec */
  176.  
  177.     if (dnenv && dnenv[0] >= DE_DOSTYPE)
  178.         return dnenv[DE_DOSTYPE];
  179.     }
  180.  
  181. #define NODOSTYPE    ID_NO_DISK_PRESENT
  182.     return NODOSTYPE;
  183. }
  184.  
  185. int
  186. find_filesysentry(unsigned long dostype, struct DeviceNode *dn)
  187. {
  188.     if (TryFileSysEntry && FileSysResource) {
  189.     struct FileSysEntry *fse,
  190.                *next;
  191.  
  192.     for (fse = FileSysResource->fsr_FileSysEntries.lh_Head;
  193.          next = fse->fse_Node.ln_Succ;
  194.          fse = next) {
  195.         db(printf("Name %lx %s DosType %lx Version %lx SegList %lx\n",
  196.         fse->fse_Node.ln_Name,
  197.         fse->fse_Node.ln_Name,
  198.         fse->fse_DosType,
  199.         fse->fse_Version,
  200.         fse->fse_SegList);)
  201.         if (fse->fse_DosType == dostype) {
  202.         /*
  203.          * Patch the data from the FileSysEntry into the
  204.          * DeviceNode.
  205.          */
  206.         if (dn) {
  207.             long       *dnl = (long *)&dn->dn_Type;
  208.             long       *fsel = (long *)&fse->fse_Type;
  209.             unsigned long   patchflags = fse->fse_PatchFlags;
  210.  
  211.             while (patchflags) {
  212.             if (patchflags & 1) {
  213.                 nodb(*dnl = *fsel;)
  214.             }
  215.             dnl++;
  216.             fsel++;
  217.             patchflags >>= 1;
  218.             }
  219.         }
  220.  
  221.         return 1;    /* We found it */
  222.         }
  223.     }
  224.     }
  225.     return 0;            /* Didn't find anything */
  226. }
  227.  
  228. void
  229. make_filesysentry(struct DeviceNode *master)
  230. {
  231.     unsigned long dostype;
  232.  
  233.     if (!CreateFileSysEntry) {
  234.     return;
  235.     }
  236.  
  237.     dostype = get_dostype(master);
  238.     if (dostype != NODOSTYPE && find_filesysentry(dostype, NULL) == 0) {
  239.  
  240.     /*
  241.      * So, there is no appropriate FileSysEntry for this DosType.
  242.      * Let's create one!
  243.      */
  244.     if (FileSysResource == NULL) {
  245.         FileSysResource = AllocMem(sizeof(struct FileSysResource),
  246.                        MEMF_PUBLIC | MEMF_CLEAR);
  247.         if (FileSysResource) {
  248.         NewList(&FileSysResource->fsr_FileSysEntries);
  249.         AddResource(FileSysResource);
  250.         }
  251.     }
  252.  
  253.     if (FileSysResource) {
  254.         struct FileSysEntry *fse;
  255.  
  256.         fse = AllocMem(sizeof(*fse), MEMF_PUBLIC | MEMF_CLEAR);
  257.         if (fse) {
  258.         fse->fse_DosType = dostype;
  259.         fse->fse_SegList = master->dn_SegList;
  260. #define patchbit(x) ((offsetof(struct FileSysEntry, x) - \
  261.               offsetof(struct FileSysEntry, fse_Type)) / sizeof(long))
  262.         fse->fse_PatchFlags |= 1 << patchbit(fse_SegList);
  263.  
  264.         AddTail(&FileSysResource->fsr_FileSysEntries, &fse->fse_Node);
  265.  
  266.         }
  267.     }
  268.     }
  269. }
  270.  
  271. struct c2 {
  272.     struct DeviceNode *master;
  273. };
  274.  
  275. void           *
  276. change(long *node, void *context)
  277. {
  278.     struct c2       *c2 = (struct c2 *) context;
  279.     struct DeviceNode *dnv = (struct DeviceNode *) node;
  280.     struct DeviceNode *master = c2->master;
  281.     unsigned long   dnvDosType;
  282.  
  283.     db(printf("change: ");
  284.        printbstr(dnv->dn_Name);
  285.        printf("\n");)
  286.  
  287.     if (dnv->dn_Type != DLT_DEVICE || dnv->dn_Type != master->dn_Type) {
  288.     db(printf("Not a device\n");)
  289.     return context;     /* keep looking */
  290.     }
  291.     nodb(if (dnv->dn_SegList != 0) {
  292.     db(printf("Device has SegList\n");)
  293.     return context;     /* keep looking */
  294.     })
  295.     nodb(if (dnv->dn_Task != 0) {
  296.     db(printf("Device has Task\n");)
  297.     return context;     /* keep looking */
  298.     })
  299.     /*
  300.      * See if both have the same handler filename.
  301.      */
  302.     if (TryHandlerNames) {
  303.     char           *dnvhandler = BADDR(dnv->dn_Handler);
  304.     char           *masterhandler = BADDR(master->dn_Handler);
  305.  
  306.     db(printf("Handlers: '");
  307.        printbstr(dnv->dn_Handler);
  308.        printf("' - '");
  309.        printbstr(master->dn_Handler);
  310.        printf("'\n");)
  311.  
  312.     if (dnvhandler && masterhandler) {
  313.  
  314.         if (strnicmp(&dnvhandler[0], &masterhandler[0], masterhandler[0])
  315.         == 0) {
  316.         if (dnv->dn_SegList == 0) {
  317.             dnv->dn_SegList = master->dn_SegList;
  318.  
  319.             /* Inform the user what happened */
  320.             printbstr(master->dn_Name);
  321.             printf(" and ");
  322.             printbstr(dnv->dn_Name);
  323.             printf(" share handler ");
  324.             printbstr(dnv->dn_Handler);
  325.             printf(": SegList copied.\n");
  326.             goto done;
  327.         }
  328.         }
  329.     }
  330.     }
  331.     /*
  332.      * Try if the DosType values from the mountlist match.
  333.      */
  334.     dnvDosType = get_dostype(dnv);
  335.     if (TryDosType) {
  336.  
  337.     if (dnvDosType != NODOSTYPE && dnvDosType == get_dostype(master)) {
  338.         db(printf("Dostypes %08x match!\n", dnvDosType);)
  339.         if (dnv->dn_SegList == 0) {
  340.         nodb(dnv->dn_SegList = master->dn_SegList;)
  341.  
  342.         /* Inform the user what happened */
  343.         printbstr(master->dn_Name);
  344.         printf(" and ");
  345.         printbstr(dnv->dn_Name);
  346.         printf(" have the same DosType (0x%08lx): SegList copied\n",
  347.             dnvDosType);
  348.         goto done;
  349.         }
  350.     }
  351.     }
  352.     /*
  353.      * Try to find a FileSysResource with this DosType.
  354.      */
  355.     if (TryFileSysEntry && dnvDosType != NODOSTYPE) {
  356.     if (find_filesysentry(dnvDosType, dnv)) {
  357.         /* Inform the user what happened */
  358.         printf("There is a FileSysEntry with DosType 0x%08lx: "
  359.            "DeviceNode of ",
  360.         dnvDosType);
  361.         printbstr(dnv->dn_Name);
  362.         printf(" patched.\n");
  363.  
  364.         goto done;
  365.     }
  366.     }
  367. done:
  368.     return context;
  369. }
  370.  
  371. void
  372. spread(struct DeviceNode * master)
  373. {
  374.     struct c2        dn;
  375.  
  376.     dn.master = master;
  377.     traverse_bcpl(change, DosInfo->di_DevInfo, &dn);
  378. }
  379.  
  380. void
  381. find_devlist(void)
  382. {
  383.     struct RootNode *rn = (struct RootNode *) DOSBase->dl_Root;
  384.  
  385.     DosInfo = (struct DosInfo *) BADDR(rn->rn_Info);
  386. }
  387.  
  388. void
  389. find_filesysr(void)
  390. {
  391.     FileSysResource = OpenResource(FSRNAME);
  392. }
  393.  
  394. void
  395. usage(void)
  396. {
  397.     printf("usage: MountShare {{[+-][lchdf]} {<devicename>}}\n"
  398.        " +l: load Handler/FileSystem file\n"
  399.        " +c: create FileSysEntry\n"
  400.        " -h: don't compare Handler/FileSystem filenames\n"
  401.        " -d: don't compare DosType values\n"
  402.        " +f: search FileSysEntries\n"
  403.        "The option opposite to default is shown.\n");
  404.     exit(10);
  405. }
  406.  
  407. int
  408. main(int argc, char **argv)
  409. {
  410.     int ac;
  411.     char **av;
  412.  
  413.     ac = argc - 1;
  414.     av = argv + 1;
  415.  
  416.     if (ac < 1)
  417.     usage();
  418.  
  419.     find_devlist();
  420.     find_filesysr();
  421.  
  422.     while (ac > 0) {
  423.     if (av[0][0] == '-' || av[0][0] == '+') {
  424.         int val = av[0][0] == '+';
  425.  
  426.         switch (av[0][1]) {
  427.         case 'l':
  428.         TryLoadHandler = val;
  429.         break;
  430.         case 'c':
  431.         CreateFileSysEntry = val;
  432.         break;
  433.         case 'h':
  434.         TryHandlerNames = val;
  435.         break;
  436.         case 'd':
  437.         TryDosType = val;
  438.         break;
  439.         case 'f':
  440.         TryFileSysEntry = val;
  441.         break;
  442.         default:
  443.         usage();
  444.         }
  445.     } else {
  446.         struct DeviceNode *master;
  447.  
  448.         master = find_name(av[0]);
  449.         if (master) {
  450.         load_handler(master);
  451.         make_filesysentry(master);
  452.         spread(master);
  453.         } else {
  454.         printf("No device %s found.\n", av[0]);
  455.         }
  456.     }
  457.     ac--;
  458.     av++;
  459.     }
  460. }
  461.