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

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *
  5.  *  This library is free software; you can redistribute it and/or
  6.  *  modify it under the terms of the GNU Library General Public
  7.  *  License as published by the Free Software Foundation; either
  8.  *  version 2 of the License, or (at your option) any later version.
  9.  *
  10.  *  This library is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  *  Library General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU Library General Public
  16.  *  License along with this library; if not, write to the Free
  17.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *  __fstat.c,v 1.1.1.1 1994/04/04 04:30:08 amiga Exp
  20.  *
  21.  *  __fstat.c,v
  22.  * Revision 1.1.1.1  1994/04/04  04:30:08  amiga
  23.  * Initial CVS check in.
  24.  *
  25.  *  Revision 1.2  1993/11/05  21:49:59  mw
  26.  *  "grp/oth-perms,
  27.  *
  28.  *  Revision 1.1  1992/05/14  19:55:40  mwild
  29.  *  Initial revision
  30.  *
  31.  */
  32.  
  33. #define _KERNEL
  34. #include <string.h>
  35. #include <stdio.h>
  36. #include "ixemul.h"
  37. #include "kprintf.h"
  38.  
  39. #ifndef ACTION_EXAMINE_FH
  40. #define ACTION_EXAMINE_FH 1034
  41. #endif
  42.  
  43. /************************************************************************/
  44. /*                                                                      */
  45. /*    fstat() function.                                                 */
  46. /*                                                                      */
  47. /************************************************************************/
  48.  
  49. int
  50. __fstat(struct file *f)
  51. {
  52.   long len, pos;
  53.   struct FileInfoBlock *fib;
  54.   struct InfoData *info;
  55.   int omask;
  56.   BPTR lock;
  57.   struct stat *st = &f->f_stb;
  58.  
  59.   omask = syscall (SYS_sigsetmask, ~0);
  60.   __get_file (f);
  61.   if (!(f->f_stb_dirty & FSDF_OWNER))
  62.     {
  63.       st->st_uid = -2;
  64.       st->st_gid = -2;
  65.     }
  66.  
  67.   /* take special care of NIL:, /dev/null and friends ;-) */
  68.   if (HANDLER_NIL(f))
  69.     {
  70.       st->st_mode = S_IFCHR | 0777;
  71.       st->st_nlink = 1;
  72.       st->st_blksize = ix.ix_fs_buf_factor * 512;
  73.       st->st_blocks = 0;
  74.       goto end;
  75.     }
  76.  
  77.   info = alloca (sizeof (*info) + 2);
  78.   info = LONG_ALIGN (info);
  79.   fib  = alloca (sizeof (*fib) + 2);
  80.   fib  = LONG_ALIGN (fib);
  81.   fib->fib_OwnerUID = fib->fib_OwnerGID = 0;
  82.  
  83.   /* reset the error field */
  84.   LastError (f) = 0;
  85.  
  86.   /* we now have two possibilities.. either the filesystem understands the
  87.    * new ACTION_EXAMINE_FH packet, or we have to do some guesses at fields.. */
  88.   SendPacket2 (f, __srwport, ACTION_EXAMINE_FH, f->f_fh->fh_Arg1, CTOBPTR(fib));
  89.   __wait_sync_packet (&f->f_sp);
  90.   if (LastResult(f))
  91.     {
  92.       int mode = fill_stat_mode(st, fib);    /* see stat.c */
  93.  
  94.       /* read the uid/gid data */
  95.       if (!(f->f_stb_dirty & FSDF_OWNER))
  96.         {
  97.           st->st_uid = __amiga2unixid(fib->fib_OwnerUID);
  98.           st->st_gid = __amiga2unixid(fib->fib_OwnerGID);
  99.         }
  100.  
  101.       if (!(f->f_stb_dirty & FSDF_MODE))
  102.         st->st_mode = mode;
  103.       else
  104.         st->st_mode |= (mode & 0170000);
  105.   
  106.       /* ARGLLLLL !!!
  107.          Some (newer, hi Bill Hawes ;-)) handlers support EXAMINE_FH, but
  108.          don't know yet about ST_PIPEFILE. So console windows claim they're
  109.          plain files... Until this problem is fixed in a majority of
  110.          handlers, do an explicit SEEK here to find those fakers.. */
  111.       LastError(f) = 0;
  112.       SendPacket3(f, __srwport, ACTION_SEEK, f->f_fh->fh_Arg1, 0, OFFSET_CURRENT);
  113.       __wait_sync_packet (&f->f_sp);
  114.       if (LastError (f))
  115.         st->st_mode = (st->st_mode & ~S_IFREG) | S_IFCHR;
  116.  
  117.       /* some kind of a default-size for directories... */
  118.       st->st_size = fib->fib_DirEntryType < 0 ? fib->fib_Size : 1024; 
  119.       st->st_handler = (long)f->f_fh->fh_Type;
  120.       st->st_dev = (dev_t)st->st_handler; /* trunc to 16 bit */
  121.       lock = DupLockFromFH(CTOBPTR(f->f_fh));
  122.       if (lock)
  123.         {
  124.       /* The fl_Key field of the FileLock structure is always unique. This is
  125.          also true for filesystems like AFS and AFSFloppy. Thanks to Michiel
  126.          Pelt (the AFS author) for helping me with this. */
  127.       st->st_ino = (ino_t)((struct FileLock *)(BTOCPTR(lock)))->fl_Key;
  128.           UnLock(lock);
  129.         }
  130.       st->st_atime =
  131.       st->st_ctime =
  132.       st->st_mtime = (8*365+2)*24*3600 + ix_get_gmt_offset() +
  133.                   fib->fib_Date.ds_Days * 24 * 60 * 60 +
  134.                   fib->fib_Date.ds_Minute * 60 +
  135.                   fib->fib_Date.ds_Tick/TICKS_PER_SECOND;
  136.       /* in a try to count the blocks used for filemanagement, we add one for
  137.        * the fileheader. Note, that this is wrong for large files, where there
  138.        * are some extension-blocks as well */
  139.       st->st_blocks = fib->fib_NumBlocks + 1;
  140.     }
  141.   else
  142.     {
  143.       /* ATTENTION: see lseek.c for Bugs in Seek() and ACTION_SEEK ! */
  144.       /* seek to EOF */
  145.       SendPacket3 (f, __srwport, ACTION_SEEK, f->f_fh->fh_Arg1, 0, OFFSET_END);
  146.       __wait_sync_packet (&f->f_sp);
  147.       pos = LastResult (f);
  148.       if (pos >= 0 && LastError (f) != ERROR_ACTION_NOT_KNOWN)
  149.         {
  150.           SendPacket3 (f, __srwport,ACTION_SEEK, f->f_fh->fh_Arg1, 
  151.                    pos, OFFSET_BEGINNING);
  152.           __wait_sync_packet (&f->f_sp);
  153.           len = LastError (f) ? -1 : LastResult (f);
  154.         }
  155.       else
  156.         len = 0;
  157.  
  158.       bzero (st, sizeof(struct stat));
  159.  
  160.       if (!(f->f_stb_dirty & FSDF_OWNER))
  161.         {
  162.           st->st_uid = syscall(SYS_geteuid);
  163.           st->st_gid = syscall(SYS_getegid);
  164.         }
  165.  
  166.       if (!(f->f_stb_dirty & FSDF_MODE))
  167.         {
  168.           st->st_mode = (len >= 0 && !f->f_fh->fh_Port) ?
  169.                         S_IFREG | (0666 & ~u.u_cmask) : S_IFCHR | 0777;
  170.         }
  171.  
  172.       st->st_handler = (long)f->f_fh->fh_Type;
  173.       /* the following is a limited try to support programs, that assume that
  174.        * st_dev is always valid */
  175.       st->st_dev = (dev_t)(long)(f->f_fh->fh_Type); /* truncate to 16 bit */
  176.       /* yet another kludge.. if we call this with different descriptors, we
  177.        * should get different inode numbers.. grmpf.. */
  178.       st->st_ino = (ino_t)~(long)(f->f_fh);
  179.       st->st_nlink = 1; /* for now no problem.. 2.0... */
  180.       /* len could be -1, if the device doesn't allow seeking.. */
  181.       st->st_size = len >= 0 ? len : 0;
  182.       st->st_atime =  
  183.       st->st_mtime =
  184.       st->st_ctime = syscall (SYS_time, 0);
  185.     }
  186.  
  187.   /* try to find out block size of device, hey postman, it's packet-time
  188.    * again:-)) */
  189.  
  190.   /* clear the info-structure. Since this packet is used by the console
  191.    * handler to transmit the window pointer, it actually answers the
  192.    * request, but doesn't set the not used fields to 0.. this gives HUGE
  193.    * block lengths :-)) */
  194.   bzero (info, sizeof(*info));
  195.   SendPacket1(f, __srwport, ACTION_DISK_INFO, CTOBPTR(info));
  196.   __wait_sync_packet(&f->f_sp);
  197.  
  198.   st->st_blksize = 0;
  199.   if (LastResult (f) && info->id_BytesPerBlock)
  200.     {
  201.       st->st_blksize = info->id_BytesPerBlock;
  202.       if (!IsInteractive(CTOBPTR(f->f_fh)) && S_ISREG(st->st_mode))
  203.     st->st_blksize *= ix.ix_fs_buf_factor;
  204.       if (!st->st_blocks) 
  205.     st->st_blocks = ((st->st_size + info->id_BytesPerBlock - 1) 
  206.                     / info->id_BytesPerBlock);
  207.       else
  208.         st->st_blocks = (st->st_blocks * info->id_BytesPerBlock) / 512;
  209.     }
  210.   if (!st->st_blksize) 
  211.     {
  212.       st->st_blksize = 512;
  213.       st->st_blocks = (st->st_size + 511) >> 9;
  214.     }
  215.  
  216. end:
  217.   /* reset error of packet. write() would fail if not */
  218.   LastResult(f) = 0;
  219.  
  220.   __release_file (f);
  221.   syscall (SYS_sigsetmask, omask);
  222.   return 0;
  223. }
  224.