home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / dev / gcc / ixemulsrc.lha / ixemul / library / open.c < prev    next >
C/C++ Source or Header  |  1996-12-15  |  8KB  |  289 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *  Portions Copyright (C) 1994 Rafael W. Luebbert
  5.  *
  6.  *  This library is free software; you can redistribute it and/or
  7.  *  modify it under the terms of the GNU Library General Public
  8.  *  License as published by the Free Software Foundation; either
  9.  *  version 2 of the License, or (at your option) any later version.
  10.  *
  11.  *  This library is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  *  Library General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU Library General Public
  17.  *  License along with this library; if not, write to the Free
  18.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  *  $Id: open.c,v 1.4 1994/06/19 15:14:07 rluebbert Exp $
  21.  *
  22.  *  $Log: open.c,v $
  23.  *  Revision 1.4  1994/06/19  15:14:07  rluebbert
  24.  *  *** empty log message ***
  25.  *
  26.  *  Revision 1.2  1992/07/28  00:32:04  mwild
  27.  *  pass convert_dir the original signal mask, to check for pending signals
  28.  *
  29.  *  Revision 1.1  1992/05/14  19:55:40  mwild
  30.  *  Initial revision
  31.  *
  32.  */
  33.  
  34. #define _KERNEL
  35. #include "ixemul.h"
  36. #include "kprintf.h"
  37.  
  38. #include <string.h>
  39.  
  40. /* standard functions.. could get overridden in a network environment */
  41. extern int __ioctl(), __fselect(), __close();
  42.  
  43. /* "normal" functions, means do half-async writes & sync reads */
  44. extern int __write(), __read(), __open();
  45.  
  46. /* incore functions */
  47. extern int __mread(), __mclose(), __mselect();
  48.  
  49.  
  50. int
  51. open(char *name, int mode, int perms)
  52. {
  53.   int fd;
  54.   struct file *f;
  55.   BPTR fh;
  56.   int late_stat;
  57.   int omask, error;
  58.   char ptymask = 0;
  59.   int ptyindex = 0;
  60.   int amode = 0, i;
  61.  
  62.   if (name == NULL)     /* sanity check */
  63.     return EACCES;
  64.   mode = FFLAGS(mode);
  65.  
  66.   /* inhibit signals */
  67.   omask = syscall (SYS_sigsetmask, ~0);
  68.  
  69.   error = falloc (&f, &fd);
  70.   if (error)
  71.     {
  72.       syscall (SYS_sigsetmask, omask);
  73.       errno = error;
  74.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  75.       return -1;
  76.     }
  77.   /* we now got the file, ie. since its count is > 0, no other process
  78.    * will get it with falloc() */
  79.  
  80.   /* init those fields */
  81.   f->f_stb_dirty = 0;
  82.   late_stat = 0;
  83.   if (stat(name, &f->f_stb) < 0)
  84.     {
  85.       /* there can mainly be two reasons for stat() to fail. Either the
  86.        * file really doesn't exist (ENOENT), or then the filesystem/handler
  87.        * doesn't support file locks. */
  88.  
  89.       /* if we should get out of here without an error, init the stat
  90.        * buffer after having opened the file with __fstat, this sets some
  91.        * reasonable parameters (see end of function). */
  92.       late_stat = 1;
  93.  
  94.       if ((errno == ENOENT) && (mode & O_CREAT))
  95.     {
  96.       /* can't set permissions on an open file, so this has to be done
  97.        * by 'close' */
  98.       f->f_stb.st_mode = (perms & ~u.u_cmask);
  99.       f->f_stb_dirty |= FSDF_MODE;
  100.  
  101.           if (!muBase)
  102.             {
  103.               f->f_stb.st_uid = geteuid();
  104.               f->f_stb.st_gid = getegid();
  105.               if (f->f_stb.st_uid != (uid_t)(-2) ||
  106.                   f->f_stb.st_gid != (gid_t)(-2))
  107.                 f->f_stb_dirty |= FSDF_OWNER;
  108.             }
  109.     }
  110.     }
  111.  
  112.   f->f_flags = mode & FMASK;
  113.   f->f_ttyflags = IXTTY_ICRNL | IXTTY_OPOST | IXTTY_ONLCR;
  114.  
  115.   /* initialise the packet. The only thing needed at this time is its
  116.    * header, filling in of port, action & args will be done when it's
  117.    * used */
  118.   __init_std_packet (&f->f_sp);
  119.   __init_std_packet (&f->f_select_sp);
  120.  
  121.   /* check for case-sensitive filename */
  122.   if ((mode & O_CASE) && !late_stat && filenamecmp(name))
  123.     {
  124.       error = ENOENT;
  125.       goto error;
  126.     }
  127.  
  128.   /* ok, so lets try to open the file... */
  129.  
  130.   /* do this *only* if the stat() above was successful !! */
  131.   if (!late_stat && S_ISDIR (f->f_stb.st_mode) && !(mode & FWRITE))
  132.     {
  133.       if (convert_dir (f, name, omask))
  134.         goto ret_ok;
  135.       else
  136.     goto error;
  137.     }
  138.  
  139.   /* filter invalid modes */
  140.   switch (mode & (O_CREAT|O_TRUNC|O_EXCL))
  141.     {
  142.     case O_EXCL:
  143.     case O_EXCL|O_TRUNC:
  144.       /* can never succeed ! */
  145.       error = EINVAL;
  146.       goto error;
  147.  
  148.     case O_CREAT|O_EXCL:
  149.     case O_CREAT|O_EXCL|O_TRUNC:
  150.       if (! late_stat)
  151.         {
  152.       error = EEXIST;
  153.       goto error;
  154.     }
  155.       break;
  156.     }
  157.  
  158.   amode = (mode & O_CREAT) ? MODE_READWRITE : MODE_OLDFILE;
  159.  
  160.   if (!strcmp(name, "/dev/tty"))
  161.     name = "*";
  162.   else if ((i = is_pseudoterminal(name)))
  163.     {
  164.       char *orig_name = name;
  165.       char mask;
  166.  
  167.       name = "/fifo/ptyXX/rweksm";
  168.       memcpy(name + 7, orig_name + i + 1, 4);
  169.       name[17] = (orig_name[i] == 'p' ? 'm' : 'c');
  170.       mask = (name[17] == 'm' ? IX_PTY_MASTER : IX_PTY_SLAVE) | IX_PTY_CLOSE;
  171.       ptyindex = (name[9] - 'p') * 16 + name[10] - (name[10] >= 'a' ? 'a' - 10 : '0');
  172.       ix_lock_base();
  173.       if (ix.ix_ptys[ptyindex] & mask)
  174.         {
  175.           ix_unlock_base();
  176.           error = EIO;
  177.           goto error;
  178.         }
  179.       ptymask = mask;
  180.       ix.ix_ptys[ptyindex] |= (mask & IX_PTY_OPEN); /* mark pty in use */
  181.       ix_unlock_base();
  182.     }
  183.   do
  184.   {
  185.     if (!strcmp(name, "*") || !strcasecmp(name, "console:"))
  186.       /* Temporary patch for KingCON 1.3, which seems to have problems with
  187.      ACTION_FINDINPUT of "*"/"console:" when "dp_Port" of the packet is
  188.      not set to sender's "pr_MsgPort" - that's what IXEmul makes on
  189.      clients' startup during initialization of "stderr". */
  190.       fh = Open(name, amode);
  191.     else
  192.       fh = __open (name, amode);
  193.  
  194.     if (! fh)
  195.       {
  196.         int err = IoErr();
  197.  
  198.         /* For those handlers that do not understand MODE_READWRITE (e.g. PAR: ) */
  199.         if (err == ERROR_ACTION_NOT_KNOWN && amode == MODE_READWRITE)
  200.         {
  201.           amode = MODE_NEWFILE;
  202.         }
  203.         else
  204.         {
  205.           error = __ioerr_to_errno (err);
  206.           goto error;
  207.         }
  208.       }
  209.   } while (!fh);
  210.  
  211.   /* now.. we're lucky, we actually opened the file! */
  212.   f->f_fh = (struct FileHandle *) BTOCPTR(fh);
  213.  
  214.   if (mode & FWRITE)
  215.     f->f_write  = __write;
  216.   if (mode & FREAD)
  217.     f->f_read   = __read;
  218.  
  219.   f->f_ioctl  = __ioctl;
  220.   f->f_select = __fselect;
  221.   f->f_close  = __close;
  222.   f->f_type   = DTYPE_FILE;
  223.  
  224.   /*
  225.    * have to use kmalloc() instead of malloc(), because this is no task-private
  226.    * data, it could (in the future) be shared by other tasks 
  227.    */
  228.   f->f_name = (void *) kmalloc (strlen (name) + 1);
  229.   if (f->f_name)
  230.     strcpy (f->f_name, name);
  231.  
  232. ret_ok:
  233.   /* ok, we're almost done. If desired, init the stat buffer to the
  234.    * information we can get from an open file descriptor */
  235.   if (late_stat) __fstat (f);
  236.   
  237.   /* if the file qualifies, try to change it into a DTYPE_MEM file */
  238.   if (!late_stat && f->f_type == DTYPE_FILE 
  239.       && f->f_stb.st_size < ix.ix_membuf_limit && mode == FREAD)
  240.     {
  241.       void *buf;
  242.       
  243.       /* try to obtain the needed memory */
  244.       buf = (void *) kmalloc (f->f_stb.st_size);
  245.       if (buf)
  246.     if (syscall (SYS_read, fd, buf, f->f_stb.st_size) == f->f_stb.st_size)
  247.       {
  248.         __Close (CTOBPTR (f->f_fh));
  249.         f->f_type         = DTYPE_MEM;
  250.         f->f_mf.mf_offset     = 0;
  251.         f->f_mf.mf_buffer     = buf;
  252.         f->f_read        = __mread;
  253.         f->f_close         = __mclose;
  254.         f->f_ioctl        = 0;
  255.         f->f_select        = __mselect;
  256.       }
  257.     else
  258.       kfree (buf);
  259.     }
  260.  
  261.   syscall (SYS_sigsetmask, omask);
  262.  
  263.   if (error)
  264.     {
  265.       errno = error;
  266.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  267.     }
  268.   if (!error && (mode & O_TRUNC) && (amode != MODE_NEWFILE))
  269.     syscall(SYS_ftruncate, fd, 0);
  270.  
  271.   /* return the descriptor */
  272.   return fd;
  273.  
  274. error:
  275.   /* free the file */
  276.   u.u_ofile[fd] = 0;
  277.   if (ptymask)
  278.     {
  279.       ix_lock_base();
  280.       ix.ix_ptys[ptyindex] &= ~(ptymask & IX_PTY_OPEN);
  281.       ix_unlock_base();
  282.     }
  283.   f->f_count--;
  284.   syscall (SYS_sigsetmask, omask);
  285.   errno = error;
  286.   KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  287.   return -1;
  288. }
  289.