home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff236.lzh / DiskHandler / io.c < prev    next >
C/C++ Source or Header  |  1989-08-09  |  16KB  |  463 lines

  1. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  2. /* |_o_o|\\ Copyright (c) 1987 The Software Distillery.  All Rights Reserved */
  3. /* |. o.| || This program may not be distributed without the permission of   */
  4. /* | .  | || the authors:                                          BBS:      */
  5. /* | o  | ||   John Toebes     Dave Baker                                    */
  6. /* |  . |//                                                                  */
  7. /* ======                                                                    */
  8. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  9. /* File Access:            */
  10. /* ActRead ActWrite ActSeek ActWaitForChar    */
  11. /* ActFindwrite ActFindin ActFindout ActEnd   */
  12.  
  13. #include "handler.h"
  14.  
  15. /*---------------------------------------------------------------------------*/
  16. /*                                                                           */
  17. /*                 ActRead( global, pkt )                                    */
  18. /*                                                                           */
  19. /*---------------------------------------------------------------------------*/
  20.  
  21. void ActRead(global,pkt)
  22. GLOBAL global;
  23. struct DosPacket *pkt;              /* a pointer to the dos packet sent       */
  24. /* Arg1: APTR EFileHandle */
  25. /* Arg2: APTR Buffer      */
  26. /* Arg3: Length           */
  27. {
  28.    EFH efh;
  29.    KEY blkkey;
  30.    long blknum;
  31.    int blkpos;
  32.    char *buffer;
  33.    long len, size, toread;
  34.    char *data;
  35.  
  36.    efh  =    (EFH)pkt->dp_Arg1;
  37.    data = (char *)pkt->dp_Arg2;
  38.    len  =         pkt->dp_Arg3;
  39.  
  40.    blkpos = efh->efh_CurPos;
  41.    blknum = efh->efh_CurBlock;
  42.    blkkey = efh->efh_CurKey;
  43.  
  44.    BUG(("ActRead: efh=%08lx data=%08lx len=%ld\n", efh, data, len));
  45.    BUG(("ActRead: key=%ld pos=%ld #=%ld\n",blkkey,blkpos,blknum));
  46.    /* Make sure we are in a state where we can write to the disk */
  47.    if (unsafe(global, efh, 0))
  48.       return;
  49.  
  50.    /* Make sure we are allowed to read from the file.  Actually we may     */
  51.    /* wish to disable this in some handlers because many AmigaDos programs */
  52.    /* Do not respect the READ/WRITE bits                                   */
  53.    if (efh->efh_Protect & FIBF_READ)
  54.       {
  55.       /* Let them know how much they read */
  56.       pkt->dp_Res2 = ERROR_READ_PROTECTED;
  57.       return;
  58.       }
  59.  
  60.    /* Now if there isn't enough bytes in the file, we need to adjust */
  61.    /* down the number of bytes to read to reflect the current length */
  62.    if ((size = GetFileSize(global, efh)) == -1)
  63.       /* Some problem getting the file size so skip it */
  64.       return;
  65.  
  66.    size -= ((blknum-1)*BLOCKSIZE) + blkpos;
  67.  
  68.    if (len > size) len = size;
  69.    size = len;
  70.  
  71.    BUG(("ActRead: Allowing them to read %ld\n", size));
  72.  
  73.    /* Now fill up as many buffers as we can */
  74.    while(len)
  75.       {
  76.       /* If we don't have a block to write into, get us a new one */
  77.       if ((blkkey == 0) &&
  78.           ((blkkey = BlockKey(global, efh, blknum, 0)) == 0))
  79.          /* Couldn't get the next block for some reason.  Quit trying */
  80.          return;
  81.  
  82.       /* Find the block so we can write to it */
  83.       if ((buffer = GetBlock(global, blkkey)) == NULL)
  84.          return;
  85.  
  86.       /* Figure out how much we can put into the buffer */
  87.       toread = len;
  88.       if (toread > (BLOCKSIZE - blkpos))
  89.          toread = BLOCKSIZE - blkpos;
  90.  
  91.       BUG(("ActRead: toread=%ld len=%ld\n", toread, len));
  92.  
  93.       /* Now fill the block with the appropriate data */
  94.       GETDATA(data, toread, buffer, blkpos);
  95.  
  96.       /* Now update our position in the block */
  97.       if (toread != len)
  98.          {
  99.          blkpos = 0;
  100.          blknum++;
  101.          blkkey = 0;  /* Force us to get a new block next time */
  102.          }
  103.       else
  104.          blkpos += toread;
  105.  
  106.       /* Update our idea of where we are in the file */
  107.       data += toread;
  108.       len -= toread;
  109.       }
  110.   
  111.    BUG(("ActRead: size=%ld pos=%ld #=%ld key=%ld\n", size, blkpos, blknum,blkkey));
  112.  
  113.    /* Successful read.  Now update the EFH to indicate where we are */
  114.    efh->efh_CurPos   = blkpos;
  115.    efh->efh_CurBlock = blknum;
  116.    efh->efh_CurKey   = blkkey;
  117.  
  118.    /* Let them know how much they read */
  119.    pkt->dp_Res1 = size;
  120. }
  121.  
  122. /*---------------------------------------------------------------------------*/
  123. /*                                                                           */
  124. /*                      ActWrite( global, pkt )                              */
  125. /*                                                                           */
  126. /*---------------------------------------------------------------------------*/
  127.  
  128. void ActWrite(global,pkt)
  129. GLOBAL global;
  130. struct DosPacket *pkt;              /* a pointer to the dos packet sent       */
  131. /* Arg1: APTR EFileHandle */
  132. /* Arg2: APTR Buffer */
  133. /* Arg3: Length */
  134. {
  135.    EFH efh;
  136.    KEY blkkey;
  137.    long blknum;
  138.    int blkpos;
  139.    char *buffer;
  140.    int len;
  141.    char *data;
  142.    int towrite;
  143.  
  144.    efh  =    (EFH) pkt->dp_Arg1;
  145.    data = (char *) pkt->dp_Arg2;
  146.    len  =          pkt->dp_Arg3;
  147.  
  148.    blkpos = efh->efh_CurPos;
  149.    blknum = efh->efh_CurBlock;
  150.    blkkey = efh->efh_CurKey;
  151.  
  152.    BUG(("ActWrite:efh=%08lx key=%ld pos=%ld #=%ld\n",efh,blkkey,blkpos,blknum));
  153.  
  154.    /* Make sure we are in a state where we can write to the disk */
  155.    if (unsafe(global, efh, 1))
  156.       return;
  157.  
  158.    /* Make sure we are allowed to write to the file.  Actually we may      */
  159.    /* wish to disable this in some handlers because many AmigaDos programs */
  160.    /* Do not respect the READ/WRITE bits                                   */
  161.    if (efh->efh_Protect & FIBF_WRITE)
  162.       {
  163.       /* Let them know how much they read */
  164.       pkt->dp_Res2 = ERROR_WRITE_PROTECTED;
  165.       return;
  166.       }
  167.  
  168.    /* Now fill up as many buffers as we can */
  169.    while(len)
  170.       {
  171.       /* If we don't have a block to write into, get us a new one */
  172.       if ((blkkey == 0) &&
  173.           ((blkkey = BlockKey(global, efh, blknum, 1)) == 0))
  174.          /* Couldn't get the next block for some reason.  Quit trying */
  175.          return;
  176.  
  177.       /* Find the block so we can write to it */
  178.       if ((buffer = ModBlock(global, blkkey)) == NULL)
  179.          return;
  180.  
  181.       /* Figure out how much we can put into the buffer */
  182.       towrite = len;
  183.       if (towrite > (BLOCKSIZE - blkpos))
  184.          towrite = BLOCKSIZE - blkpos;
  185.  
  186.       /* Now fill the block with the appropriate data */
  187.       PUTDATA(buffer, blkpos, data, towrite);
  188.  
  189.       /* Now update our position in the block */
  190.       if (towrite != len)
  191.          {
  192.          blkpos = 0;
  193.          blkkey = 0;  /* Force us to get a new block next time */
  194.          blknum++;
  195.          }
  196.       else
  197.          blkpos += towrite;
  198.  
  199.       /* Update our idea of where we are in the file */
  200.       len -= towrite;
  201.       data += towrite;
  202.       }
  203.  
  204.    /* Finally update the file header (if we can) to indicate our new length */
  205.    if (!UpdateFile(global, efh, blknum, blkpos))
  206.       /* Something went wrong, they will have to try again */
  207.       return;
  208.  
  209.    BUG(("Done with the Write at %ld for %ld/%ld\n", blkkey, blknum, blkpos));
  210.  
  211.    /* Successful write.  Now update the EFH to indicate what we did */
  212.    efh->efh_CurPos   = blkpos;
  213.    efh->efh_CurBlock = blknum;
  214.    efh->efh_CurKey   = blkkey;
  215.  
  216.    /* Let them know how much we wrote */
  217.    pkt->dp_Res1 = pkt->dp_Arg3;
  218. }
  219.  
  220. /*---------------------------------------------------------------------------*/
  221. /*                                                                           */
  222. /*                       ActSeek( global, pkt )                              */
  223. /*                                                                           */
  224. /*---------------------------------------------------------------------------*/
  225.  
  226. void ActSeek(global,pkt)
  227. GLOBAL global;
  228. struct DosPacket *pkt;              /* a pointer to the dos packet sent      */
  229. /* Arg1: APTR EFileHandle */
  230. /* Arg2: Position */
  231. /* Arg3: Mode */
  232. {
  233.    register EFH efh;
  234.    register long      bytepos;   /* New position relative to begin of file */
  235.    KEY blkkey;
  236.    long blknum;
  237.    int blkpos;
  238.    long size;
  239.  
  240.    efh = (EFH )pkt->dp_Arg1;
  241.    blkpos = efh->efh_CurPos;
  242.    blknum = efh->efh_CurBlock;
  243.    blkkey = efh->efh_CurKey;
  244.  
  245.    BUG(("ActSeek:efh=%08lx key=%ld pos=%ld #=%ld\n",efh,blkkey,blkpos,blknum));
  246.  
  247.    /* Make sure we are in a state where we can write to the disk */
  248.    if (unsafe(global, efh, 0))
  249.       return;
  250.  
  251.    /* Now if there isn't enough bytes in the file, we need to adjust */
  252.    /* down the number of bytes to read to reflect the current length */
  253.    if ((size = GetFileSize(global, efh)) == -1)
  254.       /* Some problem getting the file size so skip it */
  255.       return;
  256.  
  257.    /* Figure out the real byte offset we're seeking to. */
  258.    bytepos = (long)pkt->dp_Arg2;
  259.    /* Calculate the current position to be returned                         */
  260.    pkt->dp_Res1 = (efh->efh_CurBlock * BLOCKSIZE) + efh->efh_CurPos;
  261.  
  262.    switch( (int) pkt->dp_Arg3 ) {
  263.       case OFFSET_BEGINNING:         /* Already a byte position */
  264.          break;
  265.  
  266.       case OFFSET_CURRENT:           /* Add in the current position */
  267.          bytepos += pkt->dp_Res1;    /* Remember we just calculated it above */
  268.          break;
  269.  
  270.       case OFFSET_END:               /* Offset from end of file == filesize */
  271.          bytepos = size - bytepos;
  272.          break;
  273.  
  274.       default:
  275.          BUG(("ActSeek: Invalid seek mode %ld\n", pkt->dp_Arg3));
  276.          /* Note: put an error in the pkt here */
  277.          return;
  278.       }
  279.  
  280.    /* If we're trying to seek past end of file, silently adjust the offset */
  281.    /* so that we do seek to end of file.                                   */
  282.    if (bytepos > size) bytepos = size;
  283.  
  284.    /* Now calculate the offset information */
  285.    /* Note that we don't really have to locate the block because it will be */
  286.    /* Automatically located by the read and write routines.  This is a      */
  287.    /* improvement when the seek is not followed by any I/O but not any      */
  288.    /* penalty in the other case.                                            */
  289.    blknum = (bytepos / BLOCKSIZE)+1;
  290.  
  291.    /* If we are still on the same block we can skip the formality of        */
  292.    /* Refiguring out where the block was.                                   */
  293.    if (blknum != efh->efh_CurBlock)
  294.       efh->efh_CurKey = 0;
  295.  
  296.    efh->efh_CurBlock = blknum;
  297.    efh->efh_CurPos   = bytepos % BLOCKSIZE;
  298.  
  299.    BUG(("ActSeek: Successful to %ld/%ld\n", blknum, efh->efh_CurPos));
  300. }
  301.  
  302. /*---------------------------------------------------------------------------*/
  303. /*                                                                           */
  304. /*                    ActFindwrite( global, pkt )                            */
  305. /*                                                                           */
  306. /*---------------------------------------------------------------------------*/
  307.  
  308. void ActFindwrite(global,pkt)
  309. GLOBAL global;
  310. struct DosPacket *pkt;              /* a pointer to the dos packet sent      */
  311. /* ARG1: FileHandle to fill in */
  312. /* ARG2: Lock for file relative to */
  313. /* Arg3: Name of file */
  314. {
  315.    BUG(("ActFindwrite\n"));
  316.    /* Code 1004 - 
  317.       If file does not exist, open should fail.
  318.       If file does exist, open with an exclusive lock */
  319.  
  320.    pkt->dp_Res1 = initbuf(global, EXCLUSIVE_LOCK, OLDFILE);
  321. }
  322.  
  323. /*---------------------------------------------------------------------------*/
  324. /*                                                                           */
  325. /*                    ActFindin( global, pkt )                               */
  326. /*                                                                           */
  327. /*---------------------------------------------------------------------------*/
  328.  
  329. void ActFindin(global,pkt)
  330. GLOBAL global;
  331. struct DosPacket *pkt;              /* a pointer to the dos packet sent      */
  332. /* ARG1: FileHandle to fill in */
  333. /* ARG2: Lock for file relative to */
  334. /* Arg3: Name of file */
  335. {
  336.    BUG(("ActFindin\n"));
  337.    /* Code 1005 -
  338.       Open existing file to READ/WRITE at beginning
  339.       If file doesn't exist, fail the open */
  340.  
  341.    pkt->dp_Res1 = initbuf(global, SHARED_LOCK, OLDFILE);
  342. }
  343.  
  344. /*---------------------------------------------------------------------------*/
  345. /*                                                                           */
  346. /*                    ActFindout( global, pkt )                              */
  347. /*                                                                           */
  348. /*---------------------------------------------------------------------------*/
  349.  
  350. void ActFindout(global,pkt)
  351. GLOBAL global;
  352. struct DosPacket *pkt;              /* a pointer to the dos packet sent      */
  353. /* ARG1: FileHandle to fill in */
  354. /* ARG2: Lock for file relative to */
  355. /* Arg3: Name of file */
  356. {
  357.    BUG(("ActFindout\n"));
  358.    /* code 1006 -
  359.       Open a new file for read/write.
  360.       If file exists, truncate contents.
  361.       If file does not exist, create a new one
  362.       If case of new name is different then change it in place */
  363.  
  364.    pkt->dp_Res1 = initbuf(global, SHARED_LOCK, NEWFILE);
  365. }
  366.  
  367. /*---------------------------------------------------------------------------*/
  368. /*                                                                           */
  369. /*                       ActEnd( global, pkt )                               */
  370. /*                                                                           */
  371. /*---------------------------------------------------------------------------*/
  372.  
  373. void ActEnd( global, pkt )
  374. GLOBAL global;
  375. struct DosPacket *pkt;              /* a pointer to the dos packet sent      */
  376. {
  377.    EFH efh;
  378.    BUG(("ActEnd\n"));
  379.  
  380.    efh = (EFH )pkt->dp_Arg1;
  381.  
  382.    if (unsafe(global, efh, 0))
  383.       return;
  384.  
  385.    /* empty out anything left in the buffer */
  386.    termbuf(global, efh);
  387.  
  388.    pkt->dp_Res1 = DOS_TRUE;
  389. }
  390.  
  391. /*---------------------------------------------------------------------------*/
  392. /*                                                                           */
  393. /*            unsafe( global, efh, flag )                                    */
  394. /*                                                                           */
  395. /*---------------------------------------------------------------------------*/
  396. int unsafe(global, efh, forwrite)
  397. GLOBAL global;
  398. register EFH efh;
  399. int forwrite;
  400. {
  401.    register EFH lookefh;
  402.  
  403.    for (lookefh = global->AllHandles;
  404.         lookefh && (lookefh != efh);
  405.         lookefh = lookefh->efh_Next);
  406.  
  407.    /* Did we find it as a valid file handle ? */
  408.    if (!lookefh)
  409.       {
  410.       /* Not valid, need to give them an error message and quit */
  411.       BUG(("unsafe: Not find %08lx\n", efh));
  412.       global->pkt->dp_Res1 = DOS_FALSE;
  413.       global->pkt->dp_Res2 = ERROR_INVALID_LOCK;
  414.       return(1);
  415.       }
  416.  
  417.    /* Ok, it is a good EFH, make sure that we have the right disk in the */
  418.    /* drive to work with it                                              */
  419.    if ((global->volume == NULL) ||
  420.        (efh->efh_Lock &&
  421.        (efh->efh_Lock->fl_Volume != MKBADDR(global->volume))))
  422.       {
  423.       /* Sorry, not in the drive */
  424.       BUG(("unsafe: want %08lx vol is %08lx\n", efh->efh_Lock->fl_Volume,MKBADDR(global->volume)));
  425.       global->pkt->dp_Res1 = DOS_FALSE;
  426.       global->pkt->dp_Res2 = ERROR_DEVICE_NOT_MOUNTED;
  427.       return(1);
  428.       }
  429.  
  430.    /* Just to make sure, is this really a good disk to be working with ?     */
  431.    if (global->diskstatus != ID_DOS_DISK)
  432.       {
  433.       BUG(("unsafe: Not a dos disk %08lx\n", global->diskstatus));
  434.       global->pkt->dp_Res1 = DOS_FALSE;
  435.       global->pkt->dp_Res2 = ERROR_NOT_A_DOS_DISK;
  436.       return(1);
  437.       }
  438.  
  439.    /* Perhaps we might be in a bad state (like validating?)                  */
  440.    /* Just to make sure, is this really a good disk to be working with ?     */
  441.    if (global->diskstate != ID_VALIDATED &&
  442.        global->diskstate != ID_WRITE_PROTECTED)
  443.       {
  444.       BUG(("unsafe: bad state %ld\n", global->diskstate));
  445.       global->pkt->dp_Res1 = DOS_FALSE;
  446.       global->pkt->dp_Res2 = ERROR_DISK_NOT_VALIDATED;
  447.       return(1);
  448.       }
  449.  
  450.    /* How about write protected disks when we want to write to them?         */
  451.    if (forwrite && (global->diskstate == ID_WRITE_PROTECTED))
  452.       {
  453.       BUG(("unsafe: disk is write protected\n"));
  454.       global->pkt->dp_Res1 = DOS_FALSE;
  455.       global->pkt->dp_Res2 = ERROR_DISK_WRITE_PROTECTED;
  456.       return(1);
  457.       }
  458.  
  459.    /* Well, it is right and we have the correct volume mounted so it must be */
  460.    /* A good thing to play with.                                             */
  461.    return(0);
  462. }
  463.