home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 396.lha / MSH_v1.30s / src / hanmain.c < prev    next >
C/C++ Source or Header  |  1990-07-10  |  10KB  |  451 lines

  1. /*-
  2.  * $Id: hanmain.c,v 1.30 90/06/04 23:16:50 Rhialto Rel $
  3.  * $Log:    hanmain.c,v $
  4.  * Revision 1.30  90/06/04  23:16:50  Rhialto
  5.  * Release 1 Patch 3
  6.  * 
  7.  *  HANMAIN.C
  8.  *
  9.  *  The code for the messydos file system handler.
  10.  *
  11.  *  Some start/stop stuff that is not really part of the
  12.  *  file system itself but that must be done anyway.
  13.  *
  14.  *  This code is (C) Copyright 1989 by Olaf Seibert. All rights reserved. May
  15.  *  not be used or copied without a licence.
  16. -*/
  17.  
  18. #include "dos.h"
  19. #include "han.h"
  20.  
  21. #ifdef HDEBUG
  22. #   define    debug(x)  dbprintf x
  23. #else
  24. #   define    debug(x)
  25. #endif
  26.  
  27. extern int    CheckBootBlock;
  28. extern char    DotDot[1 + 8 + 3];
  29. struct Library *IntuitionBase;
  30. static char RCSId[] = "Messydos filing system $Revision: 1.30 $ $Date: 90/06/04 23:16:50 $, by Olaf Seibert";
  31.  
  32. byte
  33. ToUpper(ch)
  34. register byte    ch;
  35. {
  36.     if (ch >= 'a' && ch <= 'z')
  37.     return ch + ('A' - 'a');
  38.     if (ch == '.')
  39.     return '!';
  40.     return ch & ~DIR_DELETED_MASK;
  41. }
  42.  
  43. long
  44. lmin(a, b)
  45. long        a,
  46.         b;
  47. {
  48.     return (a < b) ? a : b;
  49. }
  50.  
  51. byte           *
  52. ZapSpaces(begin, end)
  53. register byte  *begin,
  54.            *end;
  55. {
  56.     while (end > begin && end[-1] == ' ')
  57.     *--end = '\0';
  58.  
  59.     return end;
  60. }
  61.  
  62. /*
  63.  * Map an arbitrary file name to MS-DOS conventions. The output format is
  64.  * 8+3 without dot, padded with spaces, suitable for direct comparison
  65.  * with directory entries. Return a pointer to the delimiter found ('\0'
  66.  * or '/'). [[Make sure that Examine/ExNext return a proper inverse of
  67.  * this...]]
  68.  */
  69.  
  70. byte           *
  71. ToMSName(dest, source)
  72. byte           *dest;
  73. register byte  *source;
  74. {
  75.     byte       *dotp;
  76.     byte       *slashp;
  77.     register int    i,
  78.             len;
  79.  
  80.     if (*source == '/') {       /* parentdir */
  81.     strncpy(dest, DotDot, 8 + 3);   /* ".." */
  82.     return source;
  83.     }
  84.     /*
  85.      * Remove any strictly leading dots. .info -> info, .indent.pro ->
  86.      * indent.pro, .profile -> profile, etc.
  87.      */
  88.     while (*source == '.')
  89.     source++;
  90.  
  91.     /*
  92.      * Find dot and slash which are delimiters of name and extension.
  93.      */
  94.     {
  95.     register byte  *cp;
  96.  
  97.     cp = source;
  98.     while (*cp) {
  99.         if (*cp == '.' || *cp == '/')
  100.         break;
  101.         cp++;
  102.     }
  103.     dotp = cp;
  104.     while (*cp) {
  105.         if (*cp == '/')
  106.         break;
  107.         cp++;
  108.     }
  109.     slashp = cp;
  110.     }
  111.  
  112.     len = dotp - source;
  113.     if (len > 8)
  114.     len = 8;
  115.  
  116.     for (i = 0; i < len; i++) {
  117.     *dest++ = ToUpper(*source++);
  118.     }
  119.     for (; i < 8; i++) {
  120.     *dest++ = ' ';
  121.     }
  122.  
  123.     source = dotp + 1;
  124.     len = slashp - source;    /* so will be -1 if no suffix */
  125.     if (len > 3)
  126.     len = 3;
  127.  
  128.     for (i = 0; i < len; i++) {
  129.     *dest++ = ToUpper(*source++);
  130.     }
  131.     for (; i < 3; i++) {
  132.     *dest++ = ' ';
  133.     }
  134.  
  135.     return slashp;
  136. }
  137.  
  138. /*
  139.  * Do the Info call.
  140.  */
  141.  
  142. long
  143. MSDiskInfo(infodata)
  144. struct InfoData *infodata;
  145. {
  146.     extern DEVLIST *VolNode;
  147.  
  148.     setmem(infodata, sizeof (*infodata), 0);
  149.  
  150.     infodata->id_DiskState = IDDiskState;
  151.     infodata->id_DiskType = IDDiskType;
  152.     infodata->id_UnitNumber = UnitNr;
  153.  
  154.     infodata->id_VolumeNode = (BPTR) CTOB(VolNode);
  155.     infodata->id_InUse = LockList ? 1 : 0;
  156.  
  157.     if (IDDiskType == ID_DOS_DISK) {
  158.     infodata->id_NumBlocks = Disk.nsects;
  159.     infodata->id_NumBlocksUsed = Disk.nsects - Disk.nsectsfree;
  160.     infodata->id_BytesPerBlock = Disk.bps;
  161.     }
  162.     return DOSTRUE;
  163. }
  164.  
  165. /*
  166.  * We (re-)establish our List of MSFileLocks after a disk has been
  167.  * (re-)inserted. If there are no known locks, we make the root lock from
  168.  * the volume label, if there is one.
  169.  *
  170.  * We get a special cookie to hand to a cleanup routine that we must call
  171.  * when finally all locks on the current disk are UnLock()ed. (this is
  172.  * actually the volume node, but we don't want to know that.)
  173.  *
  174.  * This must be called some time after IdentifyDisk().
  175.  */
  176.  
  177. void
  178. MSDiskInserted(locks, cookie)
  179. register struct LockList **locks;
  180. void           *cookie;
  181. {
  182.     debug(("MSDiskInserted %08lx\n", cookie));
  183.  
  184.     LockList = *locks;
  185.  
  186.     if (LockList == NULL) {
  187.     LockList = NewLockList(cookie);
  188.     RootLock = MakeLock(NULL, &Disk.vollabel, SHARED_LOCK);
  189.     } else {
  190.     RootLock = MSDupLock(GetTail(&LockList->ll_List));
  191.     }
  192.  
  193.     InitCacheList();
  194. }
  195.  
  196. /*
  197.  * Remove the current disk. A place is offered to save the current
  198.  * LockList to restore later. We must unlock the root lock since it isn't
  199.  * a real reference to the disk, just a placeholder for dummies that hand
  200.  * us NULL locks.
  201.  */
  202.  
  203. int
  204. MSDiskRemoved(locks)
  205. register struct LockList **locks;
  206. {
  207. #ifndef READONLY
  208.     if (FatDirty || (DelayState & DELAY_DIRTY))
  209.     MSUpdate(1);            /* Force a requester */
  210. #endif
  211.  
  212.     FreeFat();
  213.     FreeCacheList();
  214.  
  215.     IDDiskType = ID_NO_DISK_PRESENT;
  216.     *locks = NULL;
  217.  
  218.     if (RootLock == NULL) {
  219.     debug(("MSDiskRemoved with no RootLock\n"));
  220.     return 1;
  221.     }
  222. #ifdef HDEBUG
  223.     if (RootLock != GetTail(&LockList->ll_List)) {
  224.     debug(("RootLock not at end of LockList!\n"));
  225.     /* Get the lock on the root dir at the tail of the List */
  226.     Remove(RootLock);
  227.     AddTail(&LockList->ll_List, RootLock);
  228.     }
  229. #endif
  230.  
  231.     /*
  232.      * If there are no real locks on the disk, we need not keep any
  233.      * information about it.
  234.      */
  235.  
  236.     MSUnLock(RootLock);         /* may call FreeLockList and free VolNode
  237.                  * (!) */
  238.     RootLock = NULL;
  239.  
  240.     if (LockList) {
  241.     *locks = LockList;    /* VolNode can't be gone now... */
  242.     LockList = NULL;
  243.     return 0;        /* not all references gone */
  244.     } else {
  245.     return 1;        /* all gone, even the VolNode */
  246.     }
  247. }
  248.  
  249. void
  250. HanCloseDown()
  251. {
  252. #ifdef HDEBUG
  253.     register struct MSFileLock *fl;
  254.  
  255.     while (LockList && (fl = (struct MSFileLock *) GetHead(&LockList->ll_List))) {
  256.     debug(("UNLOCKING %08lx: ", fl));
  257.     PrintDirEntry(&fl->msfl_Msd);
  258.     MSUnLock(fl);           /* Remove()s it from this List */
  259.     }
  260. #endif
  261.     if (DiskIOReq) {
  262.     if (DiskIOReq->iotd_Req.io_Unit) {
  263.         MSUpdate(1);
  264.         CloseDevice(DiskIOReq);
  265.     }
  266.     DeleteExtIO(DiskIOReq);
  267.     DiskIOReq = NULL;
  268.     }
  269.     if (TimeIOReq) {
  270.     if (TimeIOReq->tr_node.io_Unit) {
  271.         WaitIO(TimeIOReq);
  272.         CloseDevice(TimeIOReq);
  273.     }
  274.     DeleteExtIO(TimeIOReq);
  275.     TimeIOReq = NULL;
  276.     }
  277.     if (DiskReplyPort) {
  278.     DeletePort(DiskReplyPort);
  279.     DiskReplyPort = NULL;
  280.     }
  281.     if (IntuitionBase) {
  282.     CloseLibrary(IntuitionBase);
  283.     IntuitionBase = NULL;
  284.     }
  285. }
  286.  
  287. int
  288. HanOpenUp()
  289. {
  290.     LockList = NULL;
  291.     RootLock = NULL;
  292.     Fat = NULL;
  293.     IDDiskState = ID_WRITE_PROTECTED;
  294.     IDDiskType = ID_NO_DISK_PRESENT;
  295.     DelayState = DELAY_OFF;
  296.     Disk.bps = MS_BPS;
  297.     CheckBootBlock = 1;
  298.     InitCacheList();
  299.  
  300.     TimeIOReq = NULL;
  301.  
  302. #ifdef HDEBUG
  303.     if (!(DiskReplyPort = CreatePort("MSH:disk.replyport", -1L)))
  304.     goto abort;
  305. #else
  306.     if (!(DiskReplyPort = CreatePort(NULL, -1L)))
  307.     goto abort;
  308. #endif
  309.  
  310.     debug(("DiskReplyPort = 0x%08lx\n", DiskReplyPort));
  311.  
  312.     if (!(DiskIOReq = CreateExtIO(DiskReplyPort, (long) sizeof (*DiskIOReq)))) {
  313.     debug(("Failed to CreateExtIO\n"));
  314.     goto abort;
  315.     }
  316.     if (OpenDevice(DevName, UnitNr, DiskIOReq, DevFlags | TDF_ALLOW_NON_3_5)) {
  317.     debug(("Failed to OpenDevice\n"));
  318.     goto abort;
  319.     }
  320.     TimeIOReq = (struct timerequest *) CreateExtIO(DiskReplyPort,
  321.                          (long) sizeof (*TimeIOReq));
  322.  
  323.     if (TimeIOReq == NULL || OpenDevice(TIMERNAME, UNIT_VBLANK, TimeIOReq, 0L))
  324.     goto abort;
  325.     TimeIOReq->tr_node.io_Flags = IOF_QUICK;    /* For the first WaitIO() */
  326.  
  327.     IntuitionBase = OpenLibrary("intuition.library", 0L);
  328.     return DOSTRUE;
  329.  
  330. abort:
  331.     HanCloseDown();
  332.     return 0;
  333. }
  334.  
  335. /*
  336.  * Relabel the disk. We create new labels if necessary.
  337.  */
  338.  
  339. long
  340. MSRelabel(newname)
  341. byte           *newname;
  342. {
  343. #ifdef READONLY
  344.     return DOSFALSE;
  345. #else
  346.     /*
  347.      * A null or empty string means: remove the label, if any.
  348.      */
  349.     if (!newname || !*newname) {
  350.     if ((int) RootLock->msfl_DirSector >= (int) Disk.rootdir) {
  351.         RootLock->msfl_Msd.msd_Name[0] = DIR_DELETED;
  352.         RootLock->msfl_Msd.msd_Attributes = 0;
  353.         WriteFileLock(RootLock);
  354.         RootLock->msfl_Msd = FakeRootDirEntry.de_Msd;
  355.         RootLock->msfl_DirSector = -1;
  356.         Disk.vollabel = FakeRootDirEntry;
  357.     }
  358.     return DOSTRUE;
  359.     }
  360.     /*
  361.      * No label yet? Then we must create one, even if we need to move
  362.      * something else for it.
  363.      */
  364.  
  365.     if ((int) RootLock->msfl_DirSector < 0) {
  366.     struct MSFileLock *new;
  367.  
  368.     new = MSLock(RootLock, "><>.\\", EXCLUSIVE_LOCK ^ MODE_CREATEFILE);
  369.     if ((new == NULL) && (new = EmptyFileLock)) {
  370.         error = 0;
  371.         if (new->msfl_DirSector == Disk.rootdir) {
  372.         RootLock->msfl_DirSector = Disk.rootdir;
  373.         RootLock->msfl_DirOffset = new->msfl_DirOffset;
  374.         } else {
  375.         /*
  376.          * Move something out of the first directory block. Try
  377.          * not to move system files or directories (. ..), but
  378.          * we'll do it if we need to. Set the root dir date to
  379.          * now.
  380.          */
  381.         byte           *fromsec;
  382.         byte           *tosec;
  383.         register struct MsDirEntry *dir;
  384.  
  385.         fromsec = GetSec(Disk.rootdir);
  386.         tosec = GetSec(new->msfl_DirSector);
  387.  
  388.         dir = (struct MsDirEntry *) fromsec;
  389.         while (dir->msd_Attributes & (ATTR_SYSTEM | ATTR_DIRECTORY)) {
  390.             if ((byte *) ++dir >= fromsec + Disk.bps) {
  391.             --dir;    /* Back to last entry in the block */
  392.             break;    /* and move it no matter what */
  393.             }
  394.         }
  395.         CopyMem(dir, tosec + new->msfl_DirOffset,
  396.             (long) sizeof (struct MsDirEntry));
  397.         MarkSecDirty(tosec);
  398.         RootLock->msfl_DirSector = Disk.rootdir;
  399.         RootLock->msfl_DirOffset = (byte *) dir - fromsec;
  400.  
  401.         FreeSec(tosec);
  402.         FreeSec(fromsec);
  403.  
  404.         }
  405.     }
  406.     EmptyFileLock = NULL;
  407.     MSUnLock(new);
  408.     }
  409.     if ((int) RootLock->msfl_DirSector >= Disk.rootdir) {
  410.     struct DateStamp dateStamp;
  411.  
  412.     /*
  413.      * The easy part: Copy the name to Disk.vollabel and RootLock.
  414.      */
  415.     {
  416.         register int    i;
  417.         register byte  *s,
  418.                *d;
  419.  
  420.         s = newname;
  421.         d = Disk.vollabel.de_Msd.msd_Name;
  422.         for (i = 0; i < 8 + 3; i++) {
  423.         if (s[0])
  424.             *d++ = ToUpper(*s++);
  425.         else
  426.             *d++ = ' ';
  427.         }
  428.     }
  429.     DateStamp(&dateStamp);
  430.     ToMSDate(&Disk.vollabel.de_Msd.msd_Date,
  431.          &Disk.vollabel.de_Msd.msd_Time, &dateStamp);
  432.     RootLock->msfl_Msd = Disk.vollabel.de_Msd;    /* Just for the name and
  433.                              * date */
  434.     WriteFileLock(RootLock);
  435.  
  436.     return DOSTRUE;
  437.     }
  438.     return DOSFALSE;
  439. #endif
  440. }
  441.  
  442. #ifdef HDEBUG
  443.  
  444. _abort()
  445. {
  446.     HanCloseDown();
  447.     RemTask(NULL);
  448. }
  449.  
  450. #endif                /* HDEBUG */
  451.