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
/
__fstat.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-10-01
|
7KB
|
214 lines
/*
* This file is part of ixemul.library for the Amiga.
* Copyright (C) 1991, 1992 Markus M. Wild
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* __fstat.c,v 1.1.1.1 1994/04/04 04:30:08 amiga Exp
*
* __fstat.c,v
* Revision 1.1.1.1 1994/04/04 04:30:08 amiga
* Initial CVS check in.
*
* Revision 1.2 1993/11/05 21:49:59 mw
* "grp/oth-perms,
*
* Revision 1.1 1992/05/14 19:55:40 mwild
* Initial revision
*
*/
#define _KERNEL
#include <string.h>
#include <stdio.h>
#include "ixemul.h"
#include "kprintf.h"
#ifndef ACTION_EXAMINE_FH
#define ACTION_EXAMINE_FH 1034
#endif
/************************************************************************/
/* */
/* fstat() function. */
/* */
/************************************************************************/
int
__fstat(struct file *f)
{
long len, pos;
struct FileInfoBlock *fib;
struct InfoData *info;
int omask;
BPTR lock;
struct stat *st = &f->f_stb;
omask = syscall (SYS_sigsetmask, ~0);
__get_file (f);
st->st_uid = geteuid();
st->st_gid = getegid();
/* take special care of NIL:, /dev/null and friends ;-) */
if (HANDLER_NIL(f))
{
st->st_mode = S_IFCHR | 0777;
st->st_nlink = 1;
st->st_blksize = ix.ix_fs_buf_factor * 512;
st->st_blocks = 0;
goto end;
}
info = alloca (sizeof (*info) + 2);
info = LONG_ALIGN (info);
fib = alloca (sizeof (*fib) + 2);
fib = LONG_ALIGN (fib);
/* reset the error field */
LastError (f) = 0;
/* we now have two possibilities.. either the filesystem understands the
* new ACTION_EXAMINE_FH packet, or we have to do some guesses at fields.. */
SendPacket2 (f, __srwport, ACTION_EXAMINE_FH, f->f_fh->fh_Arg1, CTOBPTR(fib));
__wait_sync_packet (&f->f_sp);
if (LastResult(f))
{
int mode = fill_stat_mode(st, fib); /* see stat.c */
/* read the uid/gid data */
if (muBase)
{
st->st_uid = fib->fib_OwnerUID;
st->st_gid = fib->fib_OwnerGID;
}
/* ARGLLLLL !!!
Some (newer, hi Bill Hawes ;-)) handlers support EXAMINE_FH, but
don't know yet about ST_PIPEFILE. So console windows claim they're
plain files... Until this problem is fixed in a majority of
handlers, do an explicit SEEK here to find those fakers.. */
LastError(f) = 0;
SendPacket3(f, __srwport, ACTION_SEEK, f->f_fh->fh_Arg1, 0, OFFSET_CURRENT);
__wait_sync_packet (&f->f_sp);
if (LastError (f))
mode = (mode & ~S_IFREG) | S_IFCHR;
st->st_mode = mode;
/* support for annotated attributes (cool name ;-)) */
if (! strncmp (fib->fib_Comment, "!SP!", 4))
{
int sp_mode, sp_addr;
if (sscanf (fib->fib_Comment + 4, "%x!%x", &sp_mode, &sp_addr) == 2)
st->st_mode = sp_mode;
}
/* some kind of a default-size for directories... */
st->st_size = fib->fib_DirEntryType < 0 ? fib->fib_Size : 1024;
st->st_handler = (long)f->f_fh->fh_Type;
st->st_dev = (dev_t)st->st_handler; /* trunc to 16 bit */
lock = DupLockFromFH(CTOBPTR(f->f_fh));
if (lock)
{
/* The fl_Key field of the FileLock structure is always unique. This is
also true for filesystems like AFS and AFSFloppy. Thanks to Michiel
Pelt (the AFS author) for helping me with this. */
st->st_ino = (ino_t)((struct FileLock *)(BTOCPTR(lock)))->fl_Key;
UnLock(lock);
}
st->st_atime =
st->st_ctime =
st->st_mtime = (8*365+2)*24*3600 + ix_get_gmt_offset() +
fib->fib_Date.ds_Days * 24 * 60 * 60 +
fib->fib_Date.ds_Minute * 60 +
fib->fib_Date.ds_Tick/TICKS_PER_SECOND;
/* in a try to count the blocks used for filemanagement, we add one for
* the fileheader. Note, that this is wrong for large files, where there
* are some extension-blocks as well */
st->st_blocks = fib->fib_NumBlocks + 1;
}
else
{
/* ATTENTION: see lseek.c for Bugs in Seek() and ACTION_SEEK ! */
/* seek to EOF */
SendPacket3 (f, __srwport, ACTION_SEEK, f->f_fh->fh_Arg1, 0, OFFSET_END);
__wait_sync_packet (&f->f_sp);
pos = LastResult (f);
if (pos >= 0 && LastError (f) != ERROR_ACTION_NOT_KNOWN)
{
SendPacket3 (f, __srwport,ACTION_SEEK, f->f_fh->fh_Arg1,
pos, OFFSET_BEGINNING);
__wait_sync_packet (&f->f_sp);
len = LastError (f) ? -1 : LastResult (f);
}
else
len = 0;
bzero (st, sizeof(struct stat));
st->st_mode = ((len >= 0 && !f->f_fh->fh_Port) ? S_IFREG : S_IFCHR) | 0777;
st->st_handler = (long)f->f_fh->fh_Type;
/* the following is a limited try to support programs, that assume that
* st_dev is always valid */
st->st_dev = (dev_t)(long)(f->f_fh->fh_Type); /* truncate to 16 bit */
/* yet another kludge.. if we call this with different descriptors, we
* should get different inode numbers.. grmpf.. */
st->st_ino = (ino_t)~(long)(f->f_fh);
st->st_nlink = 1; /* for now no problem.. 2.0... */
/* len could be -1, if the device doesn't allow seeking.. */
st->st_size = len >= 0 ? len : 0;
st->st_atime =
st->st_mtime =
st->st_ctime = syscall (SYS_time, 0);
}
/* try to find out block size of device, hey postman, it's packet-time
* again:-)) */
/* clear the info-structure. Since this packet is used by the console
* handler to transmit the window pointer, it actually answers the
* request, but doesn't set the not used fields to 0.. this gives HUGE
* block lengths :-)) */
bzero (info, sizeof(*info));
SendPacket1(f, __srwport, ACTION_DISK_INFO, CTOBPTR(info));
__wait_sync_packet(&f->f_sp);
st->st_blksize = 0;
if (LastResult (f) && info->id_BytesPerBlock)
{
st->st_blksize = info->id_BytesPerBlock;
if (!IsInteractive(CTOBPTR(f->f_fh)) && S_ISREG(st->st_mode))
st->st_blksize *= ix.ix_fs_buf_factor;
if (!st->st_blocks)
st->st_blocks = ((st->st_size + info->id_BytesPerBlock - 1)
/ info->id_BytesPerBlock);
else
st->st_blocks = (st->st_blocks * info->id_BytesPerBlock) / 512;
}
if (!st->st_blksize)
{
st->st_blksize = 512;
st->st_blocks = (st->st_size + 511) >> 9;
}
end:
/* reset error of packet. write() would fail if not */
LastResult(f) = 0;
__release_file (f);
syscall (SYS_sigsetmask, omask);
return 0;
}