home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 3 / CDPDIII.bin / pd / programming / gnuc / library / rcs / open.c,v < prev    next >
Encoding:
Text File  |  1992-07-28  |  8.0 KB  |  326 lines

  1. head    1.2;
  2. access;
  3. symbols
  4.     version39-41:1.1;
  5. locks;
  6. comment    @ *  @;
  7.  
  8.  
  9. 1.2
  10. date    92.07.28.00.32.04;    author mwild;    state Exp;
  11. branches;
  12. next    1.1;
  13.  
  14. 1.1
  15. date    92.05.14.19.55.40;    author mwild;    state Exp;
  16. branches;
  17. next    ;
  18.  
  19.  
  20. desc
  21. @open(2) function
  22. @
  23.  
  24.  
  25. 1.2
  26. log
  27. @pass convert_dir the original signal mask, to check for pending signals
  28. @
  29. text
  30. @/*
  31.  *  This file is part of ixemul.library for the Amiga.
  32.  *  Copyright (C) 1991, 1992  Markus M. Wild
  33.  *
  34.  *  This library is free software; you can redistribute it and/or
  35.  *  modify it under the terms of the GNU Library General Public
  36.  *  License as published by the Free Software Foundation; either
  37.  *  version 2 of the License, or (at your option) any later version.
  38.  *
  39.  *  This library is distributed in the hope that it will be useful,
  40.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  41.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  42.  *  Library General Public License for more details.
  43.  *
  44.  *  You should have received a copy of the GNU Library General Public
  45.  *  License along with this library; if not, write to the Free
  46.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  47.  *
  48.  *  $Id: open.c,v 1.1 1992/05/14 19:55:40 mwild Exp $
  49.  *
  50.  *  $Log: open.c,v $
  51.  *  Revision 1.1  1992/05/14  19:55:40  mwild
  52.  *  Initial revision
  53.  *
  54.  */
  55.  
  56. #define KERNEL
  57. #include "ixemul.h"
  58.  
  59. #undef DEBUG
  60.  
  61. #ifdef DEBUG
  62. #define DP(a) kprintf a
  63. #else
  64. #define DP(a)
  65. #endif
  66.  
  67. /* standard functions.. could get overridden in a network environment */
  68. extern int __ioctl (), __fselect (), __close ();
  69.  
  70. /* "normal" functions, means do half-async writes & sync reads */
  71. extern int __write (), __read ();
  72.  
  73. /* sync-write, waits for completion of write, this gets enabled by
  74.  * O_FSYNC */
  75. extern int __sync_write ();
  76.  
  77. extern void __fasync_handler ();
  78.  
  79. /* incore functions */
  80. extern int __mread (), __mclose ();
  81.  
  82. extern int __ioerr_to_errno ();
  83.  
  84.  
  85. int
  86. open (char *name, int mode, int perms)
  87. {
  88.   int fd;
  89.   struct file *f;
  90.   BPTR fh;
  91.   int len, late_stat;
  92.   int omask, error;
  93.   int amode;
  94.  
  95.   mode = FFLAGS(mode);
  96.  
  97. DP(("open1: write (2,.. %s.\n", write (2, "WR2", 3) == 3 ? "works" : "doesn't work"));
  98.  
  99.   if ((errno = falloc (&f, &fd)) != 0) return -1;
  100.   /* we now got the file, ie. since its count is > 0, no other process
  101.    * will get it with falloc() */
  102.  
  103. DP(("open2: write (2,.. %s.\n", write (2, "WR2", 3) == 3 ? "works" : "doesn't work"));
  104.  
  105. DP(("open3: write (2,.. %s.\n", write (2, "WR2", 3) == 3 ? "works" : "doesn't work"));
  106.   /* init those fields */
  107.   f->f_stb_dirty = 0;
  108.   late_stat = 0;
  109.   if (syscall (SYS_stat, name, &f->f_stb) < 0)
  110.     {
  111.       /* there can mainly be two reasons for stat() to fail. Either the
  112.        * file really doesn't exist (ENOENT), or then the filesystem/handler
  113.        * doesn't support file locks. */
  114.  
  115.       /* if we should get out of here without an error, init the stat
  116.        * buffer after having opened the file with __fstat, this sets some
  117.        * reasonable parameters (see end of function). */
  118.       late_stat = 1;
  119.  
  120. #if 0
  121.       /* GRRR this sounded too good to be true, stat("*") returns
  122.        * ENOENT, so this trick doesn't work */
  123.  
  124.       /* if the file doesn't exist, this is an error if not O_CREAT */
  125.       if ((errno == ENOENT) && !(mode&O_CREAT)) return -1;
  126. #endif
  127.  
  128.       if ((errno == ENOENT) && (mode&O_CREAT))
  129.     {
  130.       /* can't set permissions on an open file, so this has to be done
  131.        * by 'close' */
  132.       f->f_stb.st_mode = perms;
  133.       f->f_stb_dirty = 1;
  134.     }
  135.     }
  136.  
  137. DP(("open4: write (2,.. %s.\n", write (2, "WR2", 3) == 3 ? "works" : "doesn't work"));
  138.   f->f_flags = mode & FMASK;
  139.  
  140.   /* initialise the packet. The only thing needed at this time is its
  141.    * header, filling in of port, action & args will be done when it's
  142.    * used */
  143.   __init_std_packet (&f->f_sp);
  144.  
  145.   /* ok, so lets try to open the file... */
  146.  
  147.   /* since we may obtain a filehandle, that wouldn't be closed if we break
  148.    * too early, inhibit signals */
  149.   omask = syscall (SYS_sigsetmask, ~0);
  150.  
  151.   /* do this *only* if the stat() above was successful !! */
  152.   if (!late_stat && S_ISDIR (f->f_stb.st_mode) && !(mode & FWRITE))
  153.     {
  154.       if (convert_dir (f, name, omask) == 0)
  155.         goto ret_ok;
  156.       else
  157.     goto error;
  158.     }
  159.  
  160. DP(("open5: write (2,.. %s.\n", write (2, "WR2", 3) == 3 ? "works" : "doesn't work"));
  161. #if 0
  162.   fh = __open (name, MODE_OLDFILE);
  163.  
  164.   if (!fh && !(mode & O_CREAT))
  165.     {
  166.       error = __ioerr_to_errno (IoErr ());
  167.       goto error;
  168.     }
  169.   else if (fh && ((mode&(O_EXCL|O_CREAT))==(O_EXCL|O_CREAT)))
  170.     {
  171.       __Close (fh);
  172.       error = EEXIST;
  173.       goto error;
  174.     }
  175.   else if (!fh && (mode & O_CREAT))
  176.     {
  177.       fh = __open (name, MODE_NEWFILE);
  178.     }
  179.   else if (fh && (mode & O_TRUNC))
  180.     {
  181.       __Close (fh);
  182.       fh = __open (name, MODE_NEWFILE);
  183.     }
  184. #else
  185.   if (!(mode & FWRITE))
  186.     amode = MODE_OLDFILE;
  187.   else
  188.     switch (mode & (O_CREAT|O_TRUNC|O_EXCL))
  189.       {
  190.       case 0:
  191.     amode = MODE_OLDFILE;
  192.     break;
  193.  
  194.       case O_EXCL:
  195.       case O_EXCL|O_TRUNC:
  196.         /* can never succeed ! */
  197.         error = EINVAL;
  198.         goto error;
  199.  
  200.       case O_CREAT|O_EXCL:
  201.       case O_CREAT|O_EXCL|O_TRUNC:
  202.     if (! late_stat)
  203.       {
  204.         error = EEXIST;
  205.         goto error;
  206.       }
  207.     /* FALL INTO (O_CREAT|O_TRUNC, O_TRUNC is cheated.. ) */
  208.  
  209.       case O_TRUNC:
  210.     /* in strict Unix terminology, this is an erronous implementation,
  211.        we should call truncate() and then open OLDFILE. Doing it this
  212.        way makes the file lose its protection bits! */
  213.     /* FALL INTO */
  214.  
  215.       case O_CREAT|O_TRUNC:
  216.     amode = MODE_NEWFILE;
  217.     break;
  218.     
  219.       case O_CREAT:
  220.     /* I just hope that all handlers support this correctly.... */
  221.         amode = MODE_READWRITE; /* means: open existing, create if necessary */
  222.         break;
  223.       }
  224.   
  225.   fh = __open (name, amode);
  226. #endif
  227.  
  228.   if (! fh)
  229.     {
  230.       error = __ioerr_to_errno (IoErr ());
  231.       goto error;
  232.     }
  233.  
  234.   /* now.. we're lucky, we actually opened the file! */
  235.   f->f_fh = (struct FileHandle *) BTOCPTR(fh);
  236.  
  237.   if (mode & FWRITE)
  238.     f->f_write  = (mode & O_FSYNC) ? __sync_write : __write;
  239.   if (mode & FREAD)
  240.     f->f_read   = __read;
  241.  
  242. #if 0
  243.   /* won't work that way, I'll think something up later.. */
  244.  
  245.   /* in this case, we have to setup a handler that is called when ever
  246.    * something arrives at the rw-port, and then walk our filetable and
  247.    * decide whether the packet belonged to a file that has FASYNC set */
  248.   if (mode & FASYNC) signal (__rwport->mp_SigBit, __fasync_handler);
  249. #endif
  250.  
  251.   f->f_ioctl  = __ioctl;
  252.   f->f_select = __fselect;
  253.   f->f_close  = __close;
  254.   f->f_type   = DTYPE_FILE;
  255.  
  256. ret_ok:
  257.   /*
  258.    * have to use kmalloc() instead of malloc(), because this is no task-private
  259.    * data, it could (in the future) be shared by other tasks 
  260.    */
  261.   f->f_name = (void *) kmalloc (strlen (name) + 1);
  262.   strcpy (f->f_name, name);
  263.  
  264.   /* ok, we're almost done. If desired, init the stat buffer to the
  265.    * information we can get from an open file descriptor */
  266.   if (late_stat) __fstat (f);
  267.   
  268.   /* if the file qualifies, try to change it into a DTYPE_MEM file */
  269.   if (!late_stat && f->f_stb.st_size < ix.ix_membuf_limit && mode == FREAD)
  270.     {
  271.       void *buf;
  272.       
  273. DP(("open6: write (2,.. %s.\n", write (2, "WR2", 3) == 3 ? "works" : "doesn't work"));
  274.       /* try to obtain the needed memory */
  275.       buf = (void *) kmalloc (f->f_stb.st_size);
  276.       if (buf)
  277.     if (syscall (SYS_read, fd, buf, f->f_stb.st_size) == f->f_stb.st_size)
  278.       {
  279. DP(("open7: write (2,.. %s.\n", write (2, "WR2", 3) == 3 ? "works" : "doesn't work"));
  280.         __Close (CTOBPTR (f->f_fh));
  281. DP(("open8: write (2,.. %s.\n", write (2, "WR2", 3) == 3 ? "works" : "doesn't work"));
  282.         f->f_type         = DTYPE_MEM;
  283.         f->f_mf.mf_offset     = 0;
  284.         f->f_mf.mf_buffer     = buf;
  285.         f->f_read        = __mread;
  286.         f->f_close         = __mclose;
  287.         f->f_ioctl        = 0;
  288.         f->f_select        = 0;
  289.       }
  290.     else
  291.       kfree (buf);
  292.     }
  293.  
  294.   syscall (SYS_sigsetmask, omask);
  295.  
  296.   errno = error;
  297.   /* return the descriptor */
  298.   return fd;
  299.  
  300. error:
  301.   /* free the file */
  302.   u.u_ofile[fd] = 0;
  303.   f->f_count--;
  304.   syscall (SYS_sigsetmask, omask);
  305.   errno = error;
  306.   return -1;
  307. }
  308. @
  309.  
  310.  
  311. 1.1
  312. log
  313. @Initial revision
  314. @
  315. text
  316. @d19 1
  317. a19 1
  318.  *  $Id$
  319. d21 4
  320. a24 1
  321.  *  $Log$
  322. d125 1
  323. a125 1
  324.       if (convert_dir (f, name) == 0)
  325. @
  326.