Plan 9 from Bell Labs’s /usr/web/sources/contrib/cinap_lenrek/old/linuxemu.old/sysstat.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#include <u.h>
#include <libc.h>
#include <ureg.h>
#include "linuxsys.h"
#include "linux.h"

struct __old_kernel_stat {
	ushort st_dev;
	ushort st_ino;
	ushort st_mode;
	ushort st_nlink;
	ushort st_uid;
	ushort st_gid;
	ushort st_rdev;
	ulong  st_size;
	ulong  st_atime;
	ulong  st_mtime;
	ulong  st_ctime;
};

struct stat {
	ushort st_dev;
	ushort __pad1;
	ulong st_ino;
	ushort st_mode;
	ushort st_nlink;
	ushort st_uid;
	ushort st_gid;
	ushort st_rdev;
	ushort __pad2;
	ulong  st_size;
	ulong  st_blksize;
	ulong  st_blocks;
	ulong  st_atime;
	ulong  __unused1;
	ulong  st_mtime;
	ulong  __unused2;
	ulong  st_ctime;
	ulong  __unused3;
	ulong  __unused4;
	ulong  __unused5;
};

struct stat64 {
	uvlong	lst_dev;
	uint		__pad1;
	uint		__lst_ino;
	uint		lst_mode;
	uint		lst_nlink;
	uint		lst_uid;
	uint		lst_gid;
	uvlong	lst_rdev;
	uint		__pad2;
	vlong	lst_size;
	uint		lst_blksize;
	uvlong	lst_blocks;
	uint		lst_atime;
	uint		lst_atime_nsec;
	uint		lst_mtime;
	uint		lst_mtime_nsec;
	uint		lst_ctime;
	uint		lst_ctime_nsec;
	uvlong	lst_ino;
};

struct dirent {
	long		d_ino;
	long		d_off;
	ushort	d_reclen;
	char		d_name[];
};

#define S_IFMT	0170000
#define S_IFSOCK	0140000
#define S_IFLNK	0120000
#define S_IFREG	0100000
#define S_IFBLK	0060000
#define S_IFDIR	0040000
#define S_IFCHR	0020000
#define S_IFIFO	0010000
#define S_ISUID	0004000
#define S_ISGID	0002000
#define S_ISVTX	0001000

static void
dir2nstat(struct stat *st, Dir *d)
{
	st->st_dev = d->type;
	st->st_ino = d->qid.path;
	st->st_mode = d->mode & 0777;

	/* BUG handle more file types. */
	//print("stat on #%C: %s\n", d->type, d->name);
	if(d->mode & DMDIR)
		st->st_mode |= S_IFDIR;
	else if(strcmp(d->name, "cons") == 0)	// bug, surely.
		st->st_mode |= S_IFCHR;
	else if(d->type == '|') 
		st->st_mode |= S_IFIFO;
	else if(d->type == 'H')
		st->st_mode |= S_IFBLK;
	else if(d->type == 'M')
		st->st_mode |= S_IFREG;

	st->st_nlink = 1;
	st->st_uid = 0; // BUG get uid
	st->st_gid = 0; // BUG get gid
	st->st_size = d->length;
	st->st_rdev = 0;
	st->st_blksize = 4096; // good as any
	st->st_blocks = (d->length+st->st_blksize-1) / st->st_blksize;
	st->st_atime = d->atime;
	st->st_mtime = d->mtime;
	st->st_ctime = d->mtime;	
}

static void
dir2nstat64(struct stat64 *st, Dir *d)
{
	memset(st, 0, sizeof(*st));

	st->lst_dev = d->type;
	st->lst_ino = d->qid.path;
	st->__lst_ino = d->qid.path & 0xFFFFFF;
	st->lst_mode = d->mode & 0777;

	/* BUG handle more file types. */
	//print("stat on #%C: %s\n", d->type, d->name);
	if(d->mode & DMDIR)
		st->lst_mode |= S_IFDIR;
	else if(strcmp(d->name, "cons") == 0)	// bug, surely.
		st->lst_mode |= S_IFCHR;
	else if(d->type == '|') 
		st->lst_mode |= S_IFIFO;
	else if(d->type == 'H')
		st->lst_mode |= S_IFBLK;
	else if(d->type == 'M')
		st->lst_mode |= S_IFREG;
	
	st->lst_nlink = 1;
	st->lst_uid = 0; // BUG get uid
	st->lst_gid = 0; // BUG get gid
	st->lst_size = d->length;
	st->lst_rdev = 0;
	st->lst_blksize = 4096; // good as any
	st->lst_blocks = (d->length+512-1) / 512;
	st->lst_atime = d->atime;
	st->lst_mtime = d->mtime;
	st->lst_ctime = d->mtime;	
}


SYSCALL(sys_newfstat)
{
	ulong fd = ARG1;
	struct stat *sbuf = (struct stat *) ARG2;
	Dir *d;

	DPRINT("newfstat(%lud, %p)...", fd, sbuf);
	if((d = dirfstat(fd)) == nil)
		RETURN(-EBADF);
	dir2nstat(sbuf, d);
	free(d);
	RETURN(0);
}

SYSCALL(sys_fstat64)
{
	ulong fd = ARG1;
	struct stat64 *sbuf = (struct stat64*)ARG2;
	Dir *d;

	DPRINT("fstat64(%lud, %p)...", fd, sbuf);
	if((d = dirfstat(fd)) == nil)
		RETURN(-EBADF);
	dir2nstat64(sbuf, d);
	free(d);
	RETURN(0);
}

SYSCALL(sys_newstat)
{
	char *file = (char*) ARG1;
	struct stat *sbuf = (struct stat *) ARG2;
	Dir *d;

	DPRINT("newstat(%s, %p)...", file, sbuf);
	if((d = dirstat(file)) == nil)
		RETURN(mkerror());
	dir2nstat(sbuf, d);
	free(d);
	RETURN(0);
}

SYSCALL(sys_newstat64)
{
	char *file = (char*)ARG1;
	struct stat64 *sbuf = (struct stat64*)ARG2;
	Dir *d;

	DPRINT("newstat64(%s, %p)...", file, sbuf);
	if((d = dirstat(file)) == nil)
		RETURN(mkerror());
	dir2nstat64(sbuf, d);
	free(d);
	RETURN(0);
}

/*
 * same as stat except when called on a 
 * link, which we don't support.
 */
SYSCALL(sys_newlstat)
{
	char *file = (char*) ARG1;
	struct stat *sbuf = (struct stat *) ARG2;
	Dir *d;

	DPRINT("newlstat(%s, %p)...", file, sbuf);
	if((d = dirstat(file)) == nil)
		RETURN(mkerror());
	dir2nstat(sbuf, d);
	free(d);
	RETURN(0);
}

SYSCALL(sys_newlstat64)
{
	char *file = (char*) ARG1;
	struct stat64 *sbuf = (struct stat64 *) ARG2;
	Dir *d;

	DPRINT("newlstat64(%s, %p)...", file, sbuf);
	if((d = dirstat(file)) == nil)
		RETURN(mkerror());
	dir2nstat64(sbuf, d);
	free(d);
	RETURN(0);
}

struct utimbuf {
	long	actime;
	long modtime;
};

SYSCALL(sys_utime)
{
	char *file = (char*)ARG1;
	struct utimbuf *times = (struct utimbuf*)ARG2;
	Dir *d;

	if((d = dirstat(file)) == nil)
		RETURN(mkerror());

	times->actime = d->atime;
	times->modtime = d->mtime;

	free(d);
	RETURN(0);
}

SYSCALL(sys_newfchown)
{
	// BUG
	RETURN(0);
}

SYSCALL(sys_fchmod)
{
	int fd = ARG1;
	uint mod = ARG2;
	Dir *d;

	DPRINT("fchmod(%d, %o)...", fd, mod);
	if((d = dirfstat(fd)) == nil)
		RETURN(mkerror());

	d->mode = mod & 0777;
	if(dirfwstat(fd, d) < 0){
		free(d);
		RETURN(mkerror());
	}
	free(d);
	RETURN(0);
}

typedef struct dirent64 dirent64;
struct dirent64 {
	uvlong	d_ino;
	vlong	d_off;
	ushort	d_reclen;
	uchar	d_type;
	char		d_name[];
};

typedef struct DirReader DirReader;
struct DirReader
{
	int	i;	/* current dir */
	int	n;	/* count of dirs */
	Dir	*dir;
};

static void
destroydirreadertag(void *tag)
{
	DirReader *dr;

	DPRINT("destroydirreadertag()...");

	dr = *fdtagp(tag);
	*fdtagp(tag) = nil;

	if(dr->dir)
		free(dr->dir);
	free(dr);
}

SYSCALL(sys_getdents64)
{
	int fd = ARG1;
	ulong buf = ARG2;
	int  nbuf = ARG3;
	DirReader *dr;
	ulong off;
	dirent64 *prev;
	void *tag;

	DPRINT("sys_getdents64(%d, %p, %d)...", fd, (void*)buf, nbuf);

	tag = openfdtag(fd, TAG_READDIR, 1);
	if((dr = (DirReader*)*fdtagp(tag)) == nil){
		dr = malloc(sizeof(DirReader));
		*fdtagp(tag) = dr;
		atdestroyfdtag(tag, destroydirreadertag);
		dr->i = 0;
		dr->n = 0;
		dr->dir = nil;

		if((dr->n = dirreadall(fd, &dr->dir)) < 0){
			destroyfdtag(tag);
			closefdtag(tag);
			RETURN(mkerror());
		}
	}

	off = 0;
	prev = nil;
	for(;dr->i < dr->n; dr->i++){
		int l;
		dirent64 *e;
		Dir *d;
		d = &(dr->dir[dr->i]);
		l = sizeof(dirent64) + strlen(d->name) + 1;
		if(off + l > nbuf) {
			closefdtag(tag);
			RETURN(off);
		}
		e = (dirent64*)(buf + off);
		e->d_ino = d->qid.path;
		e->d_off = 0;
		e->d_reclen = l;
		e->d_type = d->type;
		strcpy(e->d_name, d->name);
		if(prev) prev->d_off = off;
		prev = e;
		off += l;
	}
	destroyfdtag(tag);
	RETURN(off);
}

SYSCALL(sys_getxattr)
{
	RETURN(-ENOATTR);
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].