[BACK]Return to devfs_vnops.c CVS log [TXT][DIR] Up to [local] / prex-old / usr / server / fs / devfs

File: [local] / prex-old / usr / server / fs / devfs / devfs_vnops.c (download)

Revision 1.1, Tue Jun 3 09:38:51 2008 UTC (15 years, 11 months ago) by nbrk
Branch point for: MAIN

Initial revision

/*
 * Copyright (c) 2005-2007, Kohsuke Ohtani
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the author nor the names of any co-contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <prex/prex.h>
#include <sys/stat.h>
#include <sys/vnode.h>
#include <sys/file.h>
#include <sys/mount.h>
#include <sys/syslog.h>

#include <ctype.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <fcntl.h>

#include "devfs.h"


#define devfs_mount	((vfsop_mount_t)vfs_nullop)
#define devfs_unmount	((vfsop_umount_t)vfs_nullop)
#define devfs_sync	((vfsop_sync_t)vfs_nullop)
#define devfs_vget	((vfsop_vget_t)vfs_nullop)
#define devfs_statfs	((vfsop_statfs_t)vfs_nullop)

static int devfs_open(vnode_t, mode_t);
static int devfs_close(vnode_t, file_t);
static int devfs_read(vnode_t, file_t, void *, size_t, size_t *);
static int devfs_write(vnode_t, file_t, void *, size_t, size_t *);
#define devfs_seek	((vnop_seek_t)vop_nullop)
static int devfs_ioctl(vnode_t, file_t, int, u_long);
#define devfs_fsync	((vnop_fsync_t)vop_nullop)
static int devfs_readdir(vnode_t, file_t, struct dirent *);
static int devfs_lookup(vnode_t, char *, vnode_t);
#define devfs_create	((vnop_create_t)vop_einval)
#define devfs_remove	((vnop_remove_t)vop_einval)
#define devfs_rename	((vnop_rename_t)vop_einval)
#define devfs_mkdir	((vnop_mkdir_t)vop_einval)
#define devfs_rmdir	((vnop_rmdir_t)vop_einval)
#define devfs_getattr	((vnop_getattr_t)vop_nullop)
#define devfs_setattr	((vnop_setattr_t)vop_nullop)
#define devfs_inactive	((vnop_inactive_t)vop_nullop)
#define devfs_truncate	((vnop_truncate_t)vop_nullop)

struct vnops devfs_vnops;

/*
 * File system operations
 */
struct vfsops devfs_vfsops = {
	devfs_mount,		/* mount */
	devfs_unmount,		/* unmount */
	devfs_sync,		/* sync */
	devfs_vget,		/* vget */
	devfs_statfs,		/* statfs */
	&devfs_vnops,		/* vnops */
};

/*
 * vnode operations
 */
struct vnops devfs_vnops = {
	devfs_open,		/* open */
	devfs_close,		/* close */
	devfs_read,		/* read */
	devfs_write,		/* write */
	devfs_seek,		/* seek */
	devfs_ioctl,		/* ioctl */
	devfs_fsync,		/* fsync */
	devfs_readdir,		/* readdir */
	devfs_lookup,		/* lookup */
	devfs_create,		/* create */
	devfs_remove,		/* remove */
	devfs_rename,		/* remame */
	devfs_mkdir,		/* mkdir */
	devfs_rmdir,		/* rmdir */
	devfs_getattr,		/* getattr */
	devfs_setattr,		/* setattr */
	devfs_inactive,		/* inactive */
	devfs_truncate,		/* truncate */
};

static int
devfs_open(vnode_t vp, mode_t mode)
{
	char *path;
	device_t dev;
	int err;

	dprintf("devfs_open: path=%s\n", vp->v_path);

	path = vp->v_path;
	if (!strcmp(path, "/"))	/* root ? */
		return 0;

	if (*path == '/')
		path++;
	err = device_open(path, mode & DO_RWMASK, &dev);
	if (err) {
		dprintf("devfs_open: can not open device = %s error=%d\n",
			path, err);
		return err;
	}
	vp->v_data = (void *)dev;	/* Store private data */
	return 0;
}

static int
devfs_close(vnode_t vp, file_t fp)
{

	dprintf("devfs_close: fp=%x\n", fp);

	if (!strcmp(vp->v_path, "/"))	/* root ? */
		return 0;

	return device_close((device_t)vp->v_data);
}

static int
devfs_read(vnode_t vp, file_t fp, void *buf, size_t size, size_t *result)
{
	int err;
	size_t len;

	len = size;
	err = device_read((device_t)vp->v_data, buf, &len, fp->f_offset);
	if (!err)
		*result = len;
	return err;
}

static int
devfs_write(vnode_t vp, file_t fp, void *buf, size_t size, size_t *result)
{
	int err;
	size_t len;

	len = size;
	err = device_write((device_t)vp->v_data, buf, &len, fp->f_offset);
	if (!err)
		*result = len;
	dprintf("devfs_write: err=%d len=%d\n", err, len);
	return err;
}

static int
devfs_ioctl(vnode_t vp, file_t fp, int cmd, u_long arg)
{
	dprintf("devfs_ioctl\n");
	return EINVAL;
}

static int
devfs_lookup(vnode_t dvp, char *name, vnode_t vp)
{
	struct info_device info;
	int err, i;

	dprintf("devfs_lookup:%s\n", name);

	if (*name == '\0')
		return ENOENT;

	i = 0;
	err = 0;
	info.cookie = 0;
	for (;;) {
		err = sys_info(INFO_DEVICE, &info);
		if (err)
			return ENOENT;
		if (!strncmp(info.name, name, MAXDEVNAME))
			break;
		i++;
	}
	vp->v_type = (info.flags & DF_CHR) ? VCHR : VBLK;
	vp->v_mode = (mode_t)(S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP
			      | S_IROTH | S_IWOTH);
	return 0;
}

/*
 * @vp: vnode of the directory.
 */
static int
devfs_readdir(vnode_t vp, file_t fp, struct dirent *dir)
{
	struct info_device info;
	int err, i;

	dprintf("devfs_readdir offset=%d\n", fp->f_offset);

	i = 0;
	err = 0;
	info.cookie = 0;
	do {
		err = sys_info(INFO_DEVICE, &info);
		if (err)
			return ENOENT;
	} while (i++ != fp->f_offset);

	dir->d_type = 0;
	if (info.flags & DF_CHR)
		dir->d_type = DT_CHR;
	else if (info.flags & DF_BLK)
		dir->d_type = DT_BLK;
	strcpy((char *)&dir->d_name, info.name);
	dir->d_fileno = fp->f_offset;
	dir->d_namlen = strlen(dir->d_name);

	dprintf("devfs_readdir: %s\n", dir->d_name);
	fp->f_offset++;
	return 0;
}

int
devfs_init(void)
{
	return 0;
}