minix/servers/ext2/stadir.c
Evgeniy Ivanov ef0a265086 New stat structure.
* VFS and installed MFSes must be in sync before and after this change *

Use struct stat from NetBSD. It requires adding new STAT, FSTAT and LSTAT
syscalls. Libc modification is both backward and forward compatible.

Also new struct stat uses modern field sizes to avoid ABI
incompatibility, when we update uid_t, gid_t and company.
Exceptions are ino_t and off_t in old libc (though paddings added).
2011-07-12 16:39:55 +02:00

130 lines
3.7 KiB
C

/* Created (MFS based):
* February 2010 (Evgeniy Ivanov)
*/
#include "fs.h"
#include <string.h>
#include <sys/stat.h>
#include <sys/statfs.h>
#include <sys/statvfs.h>
#include "inode.h"
#include "super.h"
#include <minix/vfsif.h>
/*===========================================================================*
* stat_inode *
*===========================================================================*/
PRIVATE int stat_inode(
register struct inode *rip, /* pointer to inode to stat */
endpoint_t who_e, /* Caller endpoint */
cp_grant_id_t gid /* grant for the stat buf */
)
{
/* Common code for stat and fstat system calls. */
struct stat statbuf;
mode_t mo;
int r, s;
/* Update the atime, ctime, and mtime fields in the inode, if need be. */
if (rip->i_update) update_times(rip);
/* Fill in the statbuf struct. */
mo = rip->i_mode & I_TYPE;
/* true iff special */
s = (mo == I_CHAR_SPECIAL || mo == I_BLOCK_SPECIAL);
memset(&statbuf, 0, sizeof(struct stat));
statbuf.st_dev = rip->i_dev;
statbuf.st_ino = rip->i_num;
statbuf.st_mode = rip->i_mode;
statbuf.st_nlink = rip->i_links_count;
statbuf.st_uid = rip->i_uid;
statbuf.st_gid = rip->i_gid;
statbuf.st_rdev = (s ? rip->i_block[0] : NO_DEV);
statbuf.st_size = rip->i_size;
statbuf.st_atime = rip->i_atime;
statbuf.st_mtime = rip->i_mtime;
statbuf.st_ctime = rip->i_ctime;
statbuf.st_blksize = rip->i_sp->s_block_size;
statbuf.st_blocks = rip->i_blocks;
/* Copy the struct to user space. */
r = sys_safecopyto(who_e, gid, (vir_bytes) 0, (vir_bytes) &statbuf,
(size_t) sizeof(statbuf), D);
return(r);
}
/*===========================================================================*
* fs_fstatfs *
*===========================================================================*/
PUBLIC int fs_fstatfs()
{
struct statfs st;
struct inode *rip;
int r;
if((rip = find_inode(fs_dev, ROOT_INODE)) == NULL)
return(EINVAL);
st.f_bsize = rip->i_sp->s_block_size;
/* Copy the struct to user space. */
r = sys_safecopyto(fs_m_in.m_source, (cp_grant_id_t) fs_m_in.REQ_GRANT,
(vir_bytes) 0, (vir_bytes) &st, (size_t) sizeof(st), D);
return(r);
}
/*===========================================================================*
* fs_stat *
*===========================================================================*/
PUBLIC int fs_stat()
{
register int r; /* return value */
register struct inode *rip; /* target inode */
if ((rip = get_inode(fs_dev, (ino_t) fs_m_in.REQ_INODE_NR)) == NULL)
return(EINVAL);
r = stat_inode(rip, fs_m_in.m_source, (cp_grant_id_t) fs_m_in.REQ_GRANT);
put_inode(rip); /* release the inode */
return(r);
}
/*===========================================================================*
* fs_statvfs *
*===========================================================================*/
PUBLIC int fs_statvfs()
{
struct statvfs st;
struct super_block *sp;
int r;
sp = get_super(fs_dev);
st.f_bsize = sp->s_block_size;
st.f_frsize = sp->s_block_size;
st.f_blocks = sp->s_blocks_count;
st.f_bfree = sp->s_free_blocks_count;
st.f_bavail = sp->s_free_blocks_count - sp->s_r_blocks_count;
st.f_files = sp->s_inodes_count;
st.f_ffree = sp->s_free_inodes_count;
st.f_favail = sp->s_free_inodes_count;
st.f_fsid = fs_dev;
st.f_flag = (sp->s_rd_only == 1 ? ST_RDONLY : 0);
st.f_flag |= ST_NOTRUNC;
st.f_namemax = NAME_MAX;
/* Copy the struct to user space. */
r = sys_safecopyto(fs_m_in.m_source, fs_m_in.REQ_GRANT, 0, (vir_bytes) &st,
(phys_bytes) sizeof(st), D);
return(r);
}