home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / ixemul-45.0-src.tgz / tar.out / contrib / ixemul / library / statfs.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  10KB  |  369 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.  *  statfs.c,v 1.1.1.1 1994/04/04 04:31:00 amiga Exp
  20.  *
  21.  *  statfs.c,v
  22.  * Revision 1.1.1.1  1994/04/04  04:31:00  amiga
  23.  * Initial CVS check in.
  24.  *
  25.  *  Revision 1.2  1992/08/09  21:00:32  amiga
  26.  *  add alternate fs id's...
  27.  *
  28.  *  Revision 1.1  1992/05/22  01:50:27  mwild
  29.  *  Initial revision
  30.  *
  31.  */
  32.  
  33. #define _KERNEL
  34. #include "ixemul.h"
  35. #include "kprintf.h"
  36. #include <sys/mount.h>
  37. #include <string.h>
  38.  
  39. #ifndef ID_FFS_DISK
  40. #define ID_FFS_DISK        (0x444F5301L)    /* 'DOS\1' */
  41. #define ID_INTER_DOS_DISK    (0x444F5302L)    /* 'DOS\2' */
  42. #define ID_INTER_FFS_DISK    (0x444F5303L)    /* 'DOS\3' */
  43. #define ID_MSDOS_DISK        (0x4d534400L)    /* 'MSD\0' */
  44. #endif
  45.  
  46. /* no comments here ;-) */
  47. #define ID_ALT_OFS_DISK        (0x444F5304L)    /* 'DOS\4' */
  48. #define ID_ALT_FFS_DISK        (0x444F5305L)    /* 'DOS\5' */
  49. #define ID_ALT_INTER_DOS_DISK    (0x444F5306L)    /* 'DOS\6' */
  50. #define ID_ALT_INTER_FFS_DISK    (0x444F5307L)    /* 'DOS\7' */
  51.  
  52. /* dunno, would be logical ;-)) */
  53. #define ID_NFS_DISK        (0x4E465300)    /* 'NFS\0' */    
  54. /* did somebody already do this ??? */
  55. #define ID_UFS_DISK        (0x55465300)    /* 'UFS\0' */    
  56.  
  57.  
  58. /* this function fills in InfoData information from a statfs structure
  59.    that has at least its f_fsid field set to the handler */
  60.  
  61. static void
  62. internal_statfs (struct statfs *buf, struct InfoData *info, struct StandardPacket *sp)
  63. {
  64.   sp->sp_Pkt.dp_Port = u.u_sync_mp;
  65.   sp->sp_Pkt.dp_Type = ACTION_DISK_INFO;
  66.   sp->sp_Pkt.dp_Arg1 = CTOBPTR (info);
  67.   PutPacket ((struct MsgPort *) buf->f_fsid.val[0], sp);
  68.   __wait_sync_packet (sp);
  69.       
  70.   /* if packet is implemented on handler side */
  71.   if (sp->sp_Pkt.dp_Res1 == -1)
  72.     {
  73.       struct DeviceList *dl = BTOCPTR (info->id_VolumeNode);
  74.  
  75.       if (dl)
  76.     {
  77.           char *name = BTOCPTR (dl->dl_Name);
  78.       int len = (MNAMELEN - 2 < name[0]) ? MNAMELEN - 2 : name[0];
  79.  
  80.       /* use this field to represent the volume name */
  81.           bcopy (name + 1, buf->f_mntfromname + 1, len);
  82.           buf->f_mntfromname[0] = '/';
  83.           buf->f_mntfromname[len + 1] = 0;
  84.         }
  85.       else
  86.     /* for stuff like FIFO that doesn't have an associated volume */
  87.     strcpy (buf->f_mntfromname, buf->f_mntonname);
  88.  
  89.       switch (info->id_DiskType)
  90.         {
  91.         case ID_DOS_DISK:
  92.         case ID_ALT_OFS_DISK:
  93.           buf->f_type = MOUNT_ADOS_OFS;
  94.       break;
  95.           
  96.     case ID_FFS_DISK:
  97.     case ID_ALT_FFS_DISK:
  98.       buf->f_type = MOUNT_ADOS_FFS;
  99.       break;
  100.  
  101.     case ID_INTER_DOS_DISK:
  102.     case ID_ALT_INTER_DOS_DISK:
  103.       buf->f_type = MOUNT_ADOS_IOFS;
  104.       break;
  105.  
  106.     case ID_INTER_FFS_DISK:
  107.     case ID_ALT_INTER_FFS_DISK:
  108.       buf->f_type = MOUNT_ADOS_IFFS;
  109.       break;
  110.  
  111.     case ID_MSDOS_DISK:
  112.       buf->f_type = MOUNT_PC;
  113.       break;
  114.       
  115.     case ID_NFS_DISK:
  116.       buf->f_type = MOUNT_NFS;
  117.       break;
  118.       
  119.     case ID_UFS_DISK:
  120.       buf->f_type = MOUNT_UFS;
  121.       break;
  122.  
  123.     default:          
  124.       buf->f_type = MOUNT_NONE;
  125.       break;
  126.     }
  127.         
  128.       buf->f_flags  = MNT_NOSUID | MNT_NODEV;
  129.       if (info->id_DiskState != ID_VALIDATED)
  130.         /* can be ID_WRITE_PROTECTED or ID_VALIDATING */
  131.     buf->f_flags |= MNT_RDONLY;
  132.         
  133.       buf->f_fsize  = info->id_BytesPerBlock;
  134.       buf->f_bsize  = info->id_BytesPerBlock * ix.ix_fs_buf_factor;
  135.       buf->f_blocks = info->id_NumBlocks;
  136.       buf->f_bfree =
  137.         buf->f_bavail = info->id_NumBlocks - info->id_NumBlocksUsed;
  138.       /* no inode information available, thus set to -1 */
  139.       buf->f_files =
  140.       buf->f_ffree = -1;
  141.    }
  142. }
  143.  
  144.  
  145.  
  146. int
  147. getfsstat (struct statfs *buf, long bufsize, int flags)
  148. {
  149.   int num_devs = 0;
  150.   struct statfs *orig_buf = buf;
  151.   long orig_bufsize = bufsize;
  152.   
  153.   struct DosLibrary *dl;
  154.   struct RootNode *rn;
  155.   struct DosInfo *di;
  156.   struct DevInfo *dv;
  157.   
  158.   struct InfoData *info;
  159.   struct StandardPacket *sp;
  160.  
  161.   /* could probably use less drastic measures under 2.0... */
  162.   Forbid ();
  163.   dl = DOSBase;
  164.   rn = (struct RootNode *) dl->dl_Root;
  165.   di = BTOCPTR (rn->rn_Info);
  166.   for (dv = BTOCPTR (di->di_DevInfo); dv; dv = BTOCPTR (dv->dvi_Next))
  167.     {
  168.       if (dv->dvi_Type == DLT_DEVICE && dv->dvi_Task && dv->dvi_Name)
  169.     {
  170.       num_devs ++;
  171.       if (buf && bufsize >= sizeof (*buf))
  172.         {
  173.           char *name = BTOCPTR (dv->dvi_Name);
  174.           int len = (MNAMELEN - 2 < name[0]) ? MNAMELEN - 2 : name[0];
  175.  
  176.           /* only remember the name and the address of the
  177.              handler so that we can later send INFO packets there */
  178.           bzero (buf, sizeof (*buf));
  179.           bcopy (name + 1, buf->f_mntonname + 1, len);
  180.           buf->f_mntonname[0] = '/';
  181.           buf->f_mntonname[len + 1] = 0;
  182.           buf->f_fsid.val[1] = 0;
  183.           buf->f_fsid.val[0] = (long) dv->dvi_Task;
  184.           
  185.           buf++;
  186.           bufsize -= sizeof (struct statfs);
  187.         }
  188.     }
  189.     }
  190.   Permit ();
  191.  
  192.   if (! orig_buf || orig_bufsize < sizeof (struct statfs))
  193.     return num_devs;
  194.  
  195.   info = alloca (sizeof (*info) + 2);
  196.   info = LONG_ALIGN (info);
  197.  
  198.   sp = alloca (sizeof (*sp) + 2);
  199.   sp = LONG_ALIGN (sp);
  200.   __init_std_packet (sp);
  201.  
  202.   /* have a second run, and inquire more data from the associated volumes */
  203.   while (orig_buf < buf)
  204.     {
  205.       internal_statfs (orig_buf, info, sp);
  206.       orig_buf++;
  207.     }
  208.  
  209.   return num_devs;
  210. }
  211.  
  212. int
  213. fstatfs (int fd, struct statfs *buf)
  214. {
  215.   struct file *f = u.u_ofile[fd];
  216.   struct DosLibrary *dl;
  217.   struct RootNode *rn;
  218.   struct DosInfo *di;
  219.   struct DevInfo *dv;
  220.   
  221.   struct InfoData *info;
  222.   struct StandardPacket *sp;
  223.  
  224.   if ((unsigned)fd < NOFILE && f)
  225.     {
  226.       if (! buf)
  227.         {
  228.           errno = EFAULT;
  229.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  230.           return -1;
  231.         }
  232.  
  233.       if (HANDLER_NIL (f) || f->f_type != DTYPE_FILE)
  234.         {
  235.           errno = EOPNOTSUPP;
  236.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  237.       return -1;
  238.     }
  239.  
  240.       bzero (buf, sizeof (struct statfs));
  241.       buf->f_fsid.val[1] = 0;
  242.       buf->f_fsid.val[0] = (long) f->f_fh->fh_Type;
  243.       /* could probably use less drastic measures under 2.0... */
  244.       Forbid ();
  245.       dl = DOSBase;
  246.       rn = (struct RootNode *) dl->dl_Root;
  247.       di = BTOCPTR (rn->rn_Info);
  248.       for (dv = BTOCPTR (di->di_DevInfo); dv; dv = BTOCPTR (dv->dvi_Next))
  249.         {
  250.           if (dv->dvi_Type == DLT_DEVICE && 
  251.           (struct MsgPort *) dv->dvi_Task == f->f_fh->fh_Type)
  252.         {
  253.           char *name = BTOCPTR (dv->dvi_Name);
  254.           int len = (MNAMELEN - 2 < name[0]) ? MNAMELEN - 2 : name[0];
  255.  
  256.           bcopy (name + 1, buf->f_mntonname + 1, len);
  257.           buf->f_mntonname[0] = '/';
  258.           buf->f_mntonname[len + 1] = 0;
  259.           break;
  260.         }
  261.     }
  262.       Permit ();
  263.  
  264.       if (! dv)
  265.     {
  266.       errno = EOPNOTSUPP;
  267.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  268.           return -1;
  269.         }
  270.  
  271.       info = alloca (sizeof (*info) + 2);
  272.       info = LONG_ALIGN (info);
  273.  
  274.       sp = alloca (sizeof (*sp) + 2);
  275.       sp = LONG_ALIGN (sp);
  276.       __init_std_packet (sp);
  277.  
  278.       internal_statfs (buf, info, sp);
  279.  
  280.       return 0;
  281.     }
  282.     
  283.   errno = EBADF;  
  284.   KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  285.   return -1;
  286. }
  287.  
  288.  
  289. int
  290. statfs (const char *path, struct statfs *buf)
  291. {
  292.   struct MsgPort *handler;
  293.   BPTR lock;
  294.   int omask, err;
  295.   struct DosLibrary *dl;
  296.   struct RootNode *rn;
  297.   struct DosInfo *di;
  298.   struct DevInfo *dv;
  299.   
  300.   struct InfoData *info;
  301.   struct StandardPacket *sp;
  302.  
  303.   omask = syscall (SYS_sigsetmask, ~0);
  304.   lock = __lock ((char *)path, ACCESS_READ);
  305.   handler = lock ? ((struct FileLock *) BTOCPTR (lock))->fl_Task : 0;
  306.   err = __ioerr_to_errno (IoErr ());
  307.   if (lock)
  308.     __unlock (lock);
  309.   syscall (SYS_sigsetmask, omask);
  310.   
  311.   if (! handler)
  312.     {
  313.       errno = err;
  314.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  315.       return -1;
  316.     }
  317.   else
  318.     {
  319.       if (! buf)
  320.         {
  321.           errno = EFAULT;
  322.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  323.           return -1;
  324.         }
  325.  
  326.       bzero (buf, sizeof (struct statfs));
  327.       buf->f_fsid.val[1] = 0;
  328.       buf->f_fsid.val[0] = (long) handler;
  329.       /* could probably use less drastic measures under 2.0... */
  330.       Forbid ();
  331.       dl = DOSBase;
  332.       rn = (struct RootNode *) dl->dl_Root;
  333.       di = BTOCPTR (rn->rn_Info);
  334.       for (dv = BTOCPTR (di->di_DevInfo); dv; dv = BTOCPTR (dv->dvi_Next))
  335.         {
  336.           if (dv->dvi_Type == DLT_DEVICE && 
  337.           (struct MsgPort *) dv->dvi_Task == handler)
  338.         {
  339.           char *name = BTOCPTR (dv->dvi_Name);
  340.           int len = (MNAMELEN - 2 < name[0]) ? MNAMELEN - 2 : name[0];
  341.  
  342.           bcopy (name + 1, buf->f_mntonname + 1, len);
  343.           buf->f_mntonname[0] = '/';
  344.           buf->f_mntonname[len + 1] = 0;
  345.           break;
  346.         }
  347.     }
  348.       Permit ();
  349.  
  350.       if (! dv)
  351.     {
  352.       errno = EOPNOTSUPP;
  353.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  354.           return -1;
  355.         }
  356.  
  357.       info = alloca (sizeof (*info) + 2);
  358.       info = LONG_ALIGN (info);
  359.  
  360.       sp = alloca (sizeof (*sp) + 2);
  361.       sp = LONG_ALIGN (sp);
  362.       __init_std_packet (sp);
  363.  
  364.       internal_statfs (buf, info, sp);
  365.  
  366.       return 0;
  367.     }
  368. }
  369.