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

  1. head    1.1;
  2. access;
  3. symbols
  4.     version39-41:1.1;
  5. locks;
  6. comment    @ *  @;
  7.  
  8.  
  9. 1.1
  10. date    92.05.14.19.55.40;    author mwild;    state Exp;
  11. branches;
  12. next    ;
  13.  
  14.  
  15. desc
  16. @try to find out information about an open file
  17. @
  18.  
  19.  
  20. 1.1
  21. log
  22. @Initial revision
  23. @
  24. text
  25. @/*
  26.  *  This file is part of ixemul.library for the Amiga.
  27.  *  Copyright (C) 1991, 1992  Markus M. Wild
  28.  *
  29.  *  This library is free software; you can redistribute it and/or
  30.  *  modify it under the terms of the GNU Library General Public
  31.  *  License as published by the Free Software Foundation; either
  32.  *  version 2 of the License, or (at your option) any later version.
  33.  *
  34.  *  This library is distributed in the hope that it will be useful,
  35.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  36.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  37.  *  Library General Public License for more details.
  38.  *
  39.  *  You should have received a copy of the GNU Library General Public
  40.  *  License along with this library; if not, write to the Free
  41.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  42.  *
  43.  *  $Id$
  44.  *
  45.  *  $Log$
  46.  */
  47.  
  48. #define KERNEL
  49. #include "ixemul.h"
  50.  
  51. #ifdef DEBUG
  52. #define DP(a) kprintf a
  53. #else
  54. #define DP(a)
  55. #endif
  56.  
  57. #if __GNUC__ != 2
  58. #define alloca __builtin_alloca
  59. #endif
  60.  
  61. #ifndef ACTION_EXAMINE_FH
  62. #define ACTION_EXAMINE_FH 1034
  63. #endif
  64.  
  65. #ifndef ST_LINKDIR
  66. #define ST_ROOT        1
  67. #define ST_USERDIR    2
  68. #define ST_SOFTLINK    3    /* looks like dir, but may point to a file! */
  69. #define ST_LINKDIR    4    /* hard link to dir */
  70. #define ST_FILE        -3    /* must be negative for FIB! */
  71. #define ST_LINKFILE    -4    /* hard link to file */
  72. #define ST_PIPEFILE    -5    /* for pipes that support ExamineFH */
  73. #endif
  74.  
  75. extern void *alloca ();
  76.  
  77. /************************************************************************/
  78. /*                                                                      */
  79. /*    fstat() function.                                                 */
  80. /*                                                                      */
  81. /************************************************************************/
  82.  
  83. int
  84. __fstat(struct file *f)
  85. {
  86.   long len, pos;
  87.   struct FileInfoBlock *fib;
  88.   struct InfoData *info;
  89.   int omask;
  90.  
  91.   omask = syscall (SYS_sigsetmask, ~0);
  92.   __get_file (f);
  93.  
  94.   /* take special care of NIL:, /dev/null and friends ;-) */
  95.   if (HANDLER_NIL(f))
  96.     {
  97.       f->f_stb.st_mode = S_IFCHR | 0777;
  98.       f->f_stb.st_nlink = 1;
  99.       f->f_stb.st_blksize = ix.ix_fs_buf_factor * 512;
  100.       f->f_stb.st_blocks = 0;
  101.       goto end;
  102.     }
  103.  
  104.   info = alloca (sizeof (*info) + 2);
  105.   info = LONG_ALIGN (info);
  106.   fib  = alloca (sizeof (*fib) + 2);
  107.   fib  = LONG_ALIGN (fib);
  108.     
  109.   __wait_packet (&f->f_sp);
  110.   /* reset the error field */
  111.   LastError (f) = 0;
  112.  
  113.   /* we now have two possibilities.. either the filesystem understands the
  114.    * new ACTION_EXAMINE_FH packet, or we have to do some guesses at fields.. */
  115. /*  SendPacket2 (f, __rwport, ACTION_EXAMINE_FH, CTOBPTR(f->f_fh), CTOBPTR(fib));*/
  116.   SendPacket2 (f, __rwport, ACTION_EXAMINE_FH, f->f_fh->fh_Arg1, CTOBPTR(fib));
  117.   __wait_packet (&f->f_sp);
  118.   if (LastResult(f))
  119.     {
  120.       int mode;
  121.  
  122.       f->f_stb.st_nlink = 1; /* always one link entry per file, unless... */
  123.       f->f_stb.st_amode = fib->fib_Protection;
  124.  
  125.       mode = 0;
  126.       if (!(fib->fib_Protection & FIBF_EXECUTE))
  127.         mode |= S_IXUSR | S_IXGRP | S_IXOTH;
  128.       if (!(fib->fib_Protection & FIBF_WRITE))
  129.         mode |= S_IWUSR | S_IWGRP | S_IWOTH;
  130. #if 0
  131.       if (fib->fib_Protection & FIBF_DELETE)
  132.         mode |= S_ISVTX;
  133. #endif
  134.       if (!(fib->fib_Protection & FIBF_READ))
  135.         mode |= S_IRUSR | S_IRGRP | S_IROTH;
  136.  
  137.       switch (fib->fib_DirEntryType)
  138.         {
  139.         case ST_LINKDIR:
  140.           f->f_stb.st_nlink ++;  /* we never get more than a link count of two.. */
  141.         case ST_ROOT:
  142.         case ST_USERDIR:
  143.           mode |= S_IFDIR;
  144.           break;
  145.  
  146.         /* at the moment, we NEVER get this entry, since we can't get a lock
  147.          * on a symlink */
  148.         case ST_SOFTLINK:
  149.           mode |= S_IFLNK;
  150.           break;
  151.  
  152.     case ST_PIPEFILE:
  153.       /* don't use S_IFIFO, we don't have a mkfifo() call ! */
  154.       mode |= S_IFCHR;
  155.       break;
  156.  
  157.         case ST_LINKFILE:
  158.           f->f_stb.st_nlink ++;
  159.         case ST_FILE:
  160.         default:
  161.           mode |= S_IFREG;
  162.         }
  163.  
  164.       /* ARGLLLLL !!!
  165.          Some (newer, hi Bill Hawes ;-)) handlers support EXAMINE_FH, but
  166.          don't know yet about ST_PIPEFILE. So console windows claim they're
  167.          plain files... Until this problem is fixed in a majority of
  168.          handlers, do an explicit SEEK here to find those fakers.. */
  169.       LastError(f) = 0;
  170.       SendPacket3(f,__rwport,ACTION_SEEK,f->f_fh->fh_Arg1,0,OFFSET_CURRENT);
  171.       __wait_packet (&f->f_sp);
  172.       if (LastError (f))
  173.         mode = (mode & ~S_IFREG) | S_IFCHR;
  174.  
  175.       f->f_stb.st_mode = mode;
  176.       /* some kind of a default-size for directories... */
  177.       f->f_stb.st_size = fib->fib_DirEntryType<0 ? fib->fib_Size : 1024; 
  178.       f->f_stb.st_handler = (long)f->f_fh->fh_Type;
  179.       f->f_stb.st_dev = (dev_t)f->f_stb.st_handler; /* trunc to 16 bit */
  180.       f->f_stb.st_ino = fib->fib_DiskKey; 
  181.       f->f_stb.st_atime =
  182.       f->f_stb.st_ctime =
  183.       f->f_stb.st_mtime = (8*365+2)*24*3600 + /* offset to unix-timesystem */
  184.                   fib->fib_Date.ds_Days * 24 * 60 * 60 +
  185.                   fib->fib_Date.ds_Minute * 60 +
  186.                   fib->fib_Date.ds_Tick/TICKS_PER_SECOND;
  187.       /* in a try to count the blocks used for filemanagement, we add one for
  188.        * the fileheader. Note, that this is wrong for large files, where there
  189.        * are some extension-blocks as well */
  190.       f->f_stb.st_blocks = fib->fib_NumBlocks + 1;
  191.     }
  192.   else
  193.     {
  194.       /* ATTENTION: see lseek.c for Bugs in Seek() and ACTION_SEEK ! */
  195.       /* seek to EOF */
  196.       SendPacket3 (f, __rwport, ACTION_SEEK, f->f_fh->fh_Arg1, 0, OFFSET_END);
  197.       __wait_packet (&f->f_sp);
  198.       pos = LastResult (f);
  199.       if (pos >= 0 && LastError (f) != ERROR_ACTION_NOT_KNOWN)
  200.         {
  201.           SendPacket3 (f, __rwport,ACTION_SEEK, f->f_fh->fh_Arg1, 
  202.                    pos, OFFSET_BEGINNING);
  203.           __wait_packet (&f->f_sp);
  204.           len = LastError (f) ? -1 : LastResult (f);
  205.         }
  206.       else
  207.         len = 0;
  208.  
  209.       bzero (&f->f_stb, sizeof(struct stat));
  210.  
  211.       f->f_stb.st_mode = ((len >= 0 && 
  212.                      /* !IsInteractive(CTOBPTR(f->f_fh)) */! f->f_fh->fh_Port)
  213.                      ? S_IFREG : S_IFCHR) | 0777;
  214.       f->f_stb.st_handler = (long)f->f_fh->fh_Type;
  215.       /* the following is a limited try to support programs, that assume that
  216.        * st_dev is allways valid */
  217.       f->f_stb.st_dev = (dev_t)f->f_fh->fh_Type; /* truncate to 16 bit */
  218.       /* yet another kludge.. if we call this with different descriptors, we
  219.        * should get different inode numbers.. grmpf.. */
  220.       f->f_stb.st_ino = (ino_t)~(long)(f->f_fh);
  221.       f->f_stb.st_nlink = 1; /* for now no problem.. 2.0... */
  222.       /* len could be -1, if the device doesn't allow seeking.. */
  223.       f->f_stb.st_size = len >= 0 ? len : 0;
  224.       f->f_stb.st_atime =  
  225.       f->f_stb.st_mtime =
  226.       f->f_stb.st_ctime = syscall (SYS_time, 0);
  227.     }
  228.  
  229.   /* try to find out block size of device, hey postman, it's packet-time
  230.    * again:-)) */
  231.   /* make sure, the packet is not in use anymore */
  232.   __wait_packet(&f->f_sp);
  233.  
  234.   /* clear the info-structure. Since this packet is used by the console
  235.    * handler to transmit the window pointer, it actually answers the
  236.    * request, but doesn't set the not used fields to 0.. this gives HUGE
  237.    * block lengths :-)) */
  238.   bzero (info, sizeof(*info));
  239.   SendPacket1(f,__rwport,ACTION_DISK_INFO,CTOBPTR(info));
  240.   __wait_packet(&f->f_sp);
  241.  
  242.   f->f_stb.st_blksize = 0;
  243.   if (LastResult (f) && info->id_BytesPerBlock)
  244.     {
  245.       f->f_stb.st_blksize = info->id_BytesPerBlock;
  246.       if (!IsInteractive(CTOBPTR(f->f_fh)) && S_ISREG(f->f_stb.st_mode))
  247.     f->f_stb.st_blksize *= ix.ix_fs_buf_factor;
  248.       if (! f->f_stb.st_blocks) 
  249.     f->f_stb.st_blocks = ((f->f_stb.st_size + info->id_BytesPerBlock - 1) 
  250.                     / info->id_BytesPerBlock);
  251.     }
  252.  
  253.   if (! f->f_stb.st_blksize) 
  254.     {
  255.       f->f_stb.st_blksize = 512;
  256.       f->f_stb.st_blocks = (f->f_stb.st_size + 511) >> 9;
  257.     }
  258.  
  259. end:
  260.   /* reset error of packet. write() would fail if not */
  261.   LastResult(f) = 0;
  262.  
  263.   __release_file (f);
  264.   syscall (SYS_sigsetmask, omask);
  265.   return 0;
  266. }
  267. @
  268.