home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / mag&info / msjv7_4.zip / OPEN.ARJ / OPEN.C < prev    next >
Text File  |  1992-07-01  |  11KB  |  381 lines

  1. /*
  2.       Copyright 1991 by David Thielen, All Rights Reserved.
  3.  
  4.       This code example is from a commercial product and has restricted
  5.       rights.  This code, or any code derived from this code may be
  6.       incorporated into any programs with the following restrictions;
  7.       1) It cannot be sold as source code, and 2) It cannot be sold in a
  8.       product which provides this code as an API.
  9. */
  10.  
  11.  
  12. // If we create a R/O file & we want to write to it - we use the create
  13. // and live with bad sharing.
  14.  
  15.  
  16. #include "file_io.h"
  17. #include "stdlib.h"
  18. #include "string.h"
  19.  
  20. union U_TIME
  21.       {
  22.       char     sTime[4];
  23.       long     lTime;
  24.       };
  25.  
  26. int FileOpen (BYTE *pFile,unsigned uMode,unsigned short uAtr,
  27.               unsigned *puErr)
  28. {
  29. int iRtn, iTries, fRO;
  30. unsigned uFileMode, uOpenMode, uErr;
  31. BYTE *pName, *pErr;
  32. union U_TIME uTime;
  33.  
  34. #ifdef   DEBUG
  35.    if ((! pFile) || (! *pFile) || (! puErr) ||
  36.       (! (uMode & (O_READ | O_WRITE))) ||
  37.       (! (uMode & (O_OPEN | O_CREATE | O_TEMP))))
  38.       DebugPrintf ("OpenName (%s, %X, %X, %X)\n", pFile, uMode, uAtr, puErr);
  39. #endif
  40.  
  41.    // We do some simple parameter checking.  This stops us from passing
  42.    // bad params to DOS & saves us the time of an open if we know it will
  43.    // fail.
  44.    if ((! (uMode & (O_OPEN | O_CREATE | O_TEMP))) || (! *pFile))
  45.       {
  46.       *puErr = 0x57;
  47.       return (-1);
  48.       }
  49.  
  50.    // Check to see if we may be creating a R/O file that we want
  51.    // to write to
  52.    if ((uAtr & A_READ_ONLY) && (uMode & (O_CREATE | O_TEMP)) &&
  53.       (uMode & O_WRITE))
  54.       fRO = -1;
  55.    else
  56.       fRO = 0;
  57.  
  58.    // First, lets set up the mode word - we still use the low byte of
  59.    // it in pre-DOS 4.
  60.    uFileMode = 0;
  61.    switch (uMode & (O_READ | O_WRITE))
  62.       {
  63.       case O_READ | O_WRITE :
  64.          uFileMode |= 0x02;
  65.          break;
  66.       case O_WRITE :
  67.          uFileMode |= 0x01;
  68.          break;
  69.  
  70.       // O_READ is 0 - if neither set -> default to this
  71.       }
  72.  
  73.    switch (uMode & (S_DENY_READ | S_DENY_WRITE))
  74.       {
  75.       case S_DENY_READ | S_DENY_WRITE :
  76.          uFileMode |= 0x10;
  77.          break;
  78.       case S_DENY_READ :
  79.          uFileMode |= 0x30;
  80.          break;
  81.       case S_DENY_WRITE :
  82.          uFileMode |= 0x20;
  83.          break;
  84.  
  85.       // Set to DENY_NONE, not compatibility mode
  86.       default :
  87.          uFileMode |= 0x40;
  88.          break;
  89.       }
  90.  
  91.    if (uMode & S_DENY_CHILD)
  92.       uFileMode |= 0x80;
  93.  
  94.    // If temp - ignore OPEN & CREATE
  95.    if (uMode & O_TEMP)
  96.       {
  97.       uMode |= O_OPEN;            // set O_OPEN for below
  98.  
  99.       // make sure path ends with '\', point to end of path
  100.       pName = pErr = pFile + strlen (pFile);
  101.       if (*(pName-1) != '\\')
  102.          *pName++ = '\\';
  103.  
  104. #ifdef   DEBUG
  105.       memset (pName, '$', 12);        // make sure big enough buffer
  106. #endif
  107.  
  108.       // lets create it
  109.       if (DosMajVer >= 3)
  110.          {
  111.          *pName = 0;              // In case added '\'
  112.          _asm
  113.             {
  114.             mov      ax, 5A00h
  115.             mov      cx, [uAtr]
  116.             mov      dx, [pFile]
  117.             int      21h              // Create temp file
  118.             mov      [iRtn], ax
  119.             mov      [uErr], 0
  120.             jnc      dne1
  121.             mov      [uErr], ax
  122. dne1:
  123.             }
  124.  
  125.          if ((*puErr = uErr) != 0)       // Create failed
  126.             {
  127.             *pErr = 0;             // Set to passed in string
  128.             return (-1);            // Return the error
  129.             }
  130.  
  131.          // If set to R/O, O_WRITE - use this handle
  132.          if (fRO)
  133.             return (iRtn);
  134.  
  135.          // close file, drop to below to open with share
  136.          FileClose (iRtn);
  137.          }
  138.       else
  139.  
  140.          // < DOS 3.0
  141.          // We need to create a temp file - we use the time to build a
  142.          // name & find-first to see if it exists.  We only try 5 times
  143.          // because we are time based - using the system clock.
  144.          {
  145.          *puErr = 0x12;
  146.  
  147.          for (iTries=0; iTries<5; iTries++)
  148.             {
  149.             // get a name
  150.             _asm
  151.                {
  152.                mov    ah, 2Ch
  153.                int    21h             // System time
  154.                mov    word ptr [uTime], dx
  155.                mov    word ptr [uTime+2], cx
  156.                }
  157.             uTime.sTime[0] -= (char) iTries;  // Subtract try - clock frozen
  158.             ltoa (uTime.lTime, pName, 36);   // Convert to 7 digit string
  159.  
  160.             // does it exist?
  161.             _asm
  162.                {
  163.                mov    ah, 4Eh
  164.                mov    cx, 27h
  165.                mov    dx, [pFile]
  166.                int    21h             // Find First
  167.                mov    [uErr], 0
  168.                jnc    dne2
  169.                mov    [uErr], ax
  170. dne2:
  171.                }
  172.  
  173.  
  174.             // An error other than ! file
  175.             if ((uErr) && (uErr != 0x12))
  176.                {
  177.                *puErr = uErr;
  178.                *pErr = 0;
  179.                return (-1);
  180.                }
  181.  
  182.             // If it doesn't exist - create it
  183.             if (uErr == 0x12)
  184.                {
  185.                _asm
  186.                   {
  187.                   mov  ah, 3Ch
  188.                   mov  cx, [uAtr]
  189.                   mov  dx, [pFile]
  190.                   int  21h            // Create
  191.                   mov  [iRtn], ax
  192.                   mov  [uErr], 0
  193.                   jnc  dne3
  194.                   mov  [uErr], ax
  195. dne3:
  196.                   }
  197.  
  198.                // Since share doesn't exist in DOS 2 - we return the CREATE
  199.                // handle - no point in doing an open for sharing.
  200.                if (! (*puErr = uErr))
  201.                   return (iRtn);
  202.                }
  203.             }
  204.  
  205.          // Couldn't create a temp file.  Return the passed in string
  206.          *pErr = 0;
  207.          return (-1);
  208.          }
  209.       }
  210.  
  211.  
  212.    // OPEN/CREATE - either from temp or O_OPEN/O_CREATE
  213.  
  214.    // If DOS >= 4.0 - use func 6Ch
  215.    // OS/2 is DOS version 10 - we treat that like DOS 3.3
  216.    if ((DosMajVer >= 4) && (DosMajVer != 10))
  217.       {
  218.  
  219.       // We set the critical error handling to always go to int 24 for 2
  220.       // reasons.  First, we want to be version independent and since we
  221.       // can't skip int 24 for all versions, we need to hit int 24 in all
  222.       // versions on critical errors.  Second, ignoring int 24 is not
  223.       // handled consistently by DOS on all file handle calls and int 24
  224.       // will still be called in some erro cases even if the bit is set.
  225.       uOpenMode = 0;
  226.  
  227.       // func 6C - can cause all writes to be a commit.  ONLY use this if
  228.       // you TRUELY need all writes to be committed - this is EXPENSIVE.
  229.       // If even 1 write out of 10 does not need to be committed, don't
  230.       // use this bit and call FileCommit the other 9 times.
  231.       if (uMode & O_COMMIT)
  232.          uFileMode |= 0x4000;
  233.  
  234.       // These bits decide what to do if the file does/doesn't exist.
  235.       if (uMode & O_OPEN)
  236.          {
  237.          if (uMode & O_TRUNC)
  238.             uOpenMode |= 0x02;         // Replace if exists
  239.          else
  240.             uOpenMode |= 0x01;         // Open if exists
  241.          }
  242.  
  243.       if (uMode & O_CREATE)
  244.          uOpenMode |= 0x10;          // Create if ! exists
  245.  
  246.       // lets open it
  247.       _asm
  248.          {
  249.          mov      ax, 6C00h
  250.          mov      bx, [uFileMode]
  251.          mov      cx, [uAtr]
  252.          mov      dx, [uOpenMode]
  253.          mov      si, [pFile]
  254.          int      21h               // extended open
  255.          mov      [iRtn], ax
  256.          mov      [uErr], 0
  257.          jnc      dne4
  258.          mov      [uErr], ax
  259. dne4:
  260.          }
  261.  
  262.       // We got it - lets return it
  263.       if ((*puErr = uErr) != 0)
  264.          return (-1);
  265.       }
  266.    else
  267.  
  268.       // OK - we don't have the DOS 4+ super-duper one size fits all open,
  269.       // we have to use (create &) open.
  270.       {
  271.       // first we try an open - if we are on an exclusive create, we need
  272.       // to know if we need to fail, otherwise, we are in business.
  273.       uErr = 0;
  274.       _asm
  275.          {
  276.          mov      ah, 3Dh
  277.          mov      al, byte ptr [uFileMode]
  278.          mov      dx, [pFile]
  279.          int      21h               // Open
  280.          mov      [iRtn], ax
  281.          jnc      dne5
  282.          mov      [uErr], ax
  283. dne5:
  284.          }
  285.       *puErr = uErr;
  286.  
  287.       // We now use the following logic:
  288.       // 1) If O_OPEN & we were successful - we've got it
  289.       // else 2) If ! O_CREATE & we failed - we return -1
  290.       //      else 3) if O_CREATE & we were successful - we return -1
  291.  
  292.       // 1) If O_OPEN & we were successful - we've got it
  293.       if ((uMode & O_OPEN) && (! uErr))
  294.          goto Finish;             // Opened file
  295.  
  296.       // 2) If ! O_CREATE & we failed - we return -1
  297.       if ((! (uMode & O_CREATE)) && (uErr))
  298.          return (-1);
  299.  
  300.       // 3) if O_CREATE & we were successful - we return -1
  301.       // Since O_CREATE must be true here - we don't test for it
  302.       if (! uErr)
  303.          {
  304.          FileClose (iRtn);
  305.          *puErr = 0x50;            // File already exists
  306.          return (-1);             // Return error
  307.          }
  308.  
  309.       // We know the file doesn't exist AND O_CREATE is set
  310.       // So its time to create it.  For 3.0+ we use the newer create
  311.       // in case we are in Windows & someone else creates it right now.
  312.       uErr = 0;
  313.       if (DosMajVer >= 3)
  314.          _asm
  315.             {
  316.             mov      ah, 5Bh
  317.             mov      cx, [uAtr]
  318.             mov      dx, [pFile]
  319.             int      21h              // Create - can't exist
  320.             mov      [iRtn], ax
  321.             jnc      dne6
  322.             mov      [uErr], ax
  323. dne6:
  324.             }
  325.       else
  326.          _asm
  327.             {
  328.             mov      ah, 3Ch
  329.             mov      cx, [uAtr]
  330.             mov      dx, [pFile]
  331.             int      21h              // Create - may exist
  332.             mov      [iRtn], ax
  333.             jnc      dne7
  334.             mov      [uErr], ax
  335. dne7:
  336.             }
  337.  
  338.       // If we hit an error here - we're out of luck - return an error.
  339.       // NOTE: this includes erroring out if another app created a file
  340.       // between our open (O_TEMP or O_CREATE) above & our create - the
  341.       // odds are so low we live with this - we don't screw anything up,
  342.       // we just don't get the file.
  343.       if ((*puErr = uErr) != 0)
  344.          return (-1);
  345.  
  346.       // If set to R/O, O_WRITE - use this handle
  347.       if (fRO)
  348.          return (iRtn);
  349.  
  350.       // OK - we have the file - close it & re-open it with sharing
  351.       FileClose (iRtn);
  352.  
  353.       _asm
  354.          {
  355.          mov      ah, 3Dh
  356.          mov      al, byte ptr [uFileMode]
  357.          mov      dx, [pFile]
  358.          int      21h               // Open
  359.          mov      [iRtn], ax
  360.          jnc      dne8
  361.          mov      [uErr], ax
  362. dne8:
  363.          }
  364.  
  365.       // if we have an error - error out, otherwise we have it
  366.       if ((*puErr = uErr) != 0)
  367.          return (-1);
  368.       }
  369.  
  370. Finish:
  371.    // Do we have a trunc or append?
  372.    if (uMode & O_TRUNC)
  373.       FileSetSize (iRtn, 0L);
  374.  
  375.    if (uMode & O_APPEND)
  376.       FileSeek (iRtn, FileGetSize (iRtn));
  377.  
  378.    *puErr = 0;
  379.    return (iRtn);
  380. }
  381.