/*
 *  linux/ibcs/sysfs.c
 *
 *  Copyright (C) 1994  Mike Jagdis (jaggy@purplet.demon.co.uk)
 *
 * $Id: sysfs.c,v 1.13 1997/11/19 19:49:47 jaggy Exp $
 * $Source: /u/CVS/ibcs/iBCSemul/sysfs.c,v $
 */

#include <linux/config.h>

#include <linux/module.h>
#include <linux/version.h>

#include <asm/segment.h>
#ifndef KERNEL_DS
#include <linux/segment.h>
#endif

#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/fcntl.h>

#include <asm/system.h>
#include <linux/fs.h>
#include <linux/sys.h>
#include <linux/string.h>

#include <ibcs/ibcs.h>

/* Kernels prior to 1.1.10 do not have a sysfs() system call and
 * are not supported by iBCS releases after July 1997. Sorry.
 * The kernel sysfs() code is almost all we need but, apparently,
 * the SCO (at least) sysfs() will also accept a "magic number"
 * as an index argument and will return the name of the relevant
 * file system. Since Linux doesn't have any concept of fs magic
 * numbers outside the file system code themselves there is no
 * clean way to do it in the kernel. There isn't a clean way to
 * to it here either but it needs to be done somehow :-(.
 */

#ifdef IBCS_TRACE
#include <ibcs/trace.h>
#endif


#define GETFSIND	1
#define GETFSTYP	2
#define GETNFSTYP	3


int ibcs_sysfs(int cmd, int arg1, int arg2)
{
	if (cmd == GETFSIND)
		return SYS(sysfs)(cmd, (char *)arg1);

	if (cmd == GETNFSTYP)
		return SYS(sysfs)(cmd);

	if (cmd == GETFSTYP) {
		char *buf = (char *)arg2;
		int error;

		if (arg1 & 0x80000000)
			arg1 &= 0x0000ffff;
		if (arg1 >= 0 && arg1 < SYS(sysfs)(GETNFSTYP))
			return SYS(sysfs)(cmd, arg1-1, arg2);

		/* Long enough for the longest fs name. */
		error = verify_area(VERIFY_WRITE, buf, 9);
		if (error)
			return error;

		/* Kludge alert! Hardcoded known magic numbers! */
		switch (arg1) {
			case 0xef53: case 0xffffef53:
			case 0xef51: case 0xffffef51:
				memcpy_tofs(buf, "ext", 5);
				break;
			case 0x137d:
				memcpy_tofs(buf, "ext", 4);
				break;
			case 0x9660: case 0xffff9660:
				memcpy_tofs(buf, "iso9660", 8);
				break;
			case 0x4d44:
				memcpy_tofs(buf, "msdos", 6);
				break;
			case 0x6969:
				memcpy_tofs(buf, "nfs", 4);
				break;
			case 0x9fa0: case 0xffff9fa0:
				memcpy_tofs(buf, "proc", 5);
				break;
			case 0xf995e849:
			case 0xe849: case 0xffffe849:
				memcpy_tofs(buf, "hpfs", 5);
				break;
			case 0x137f: /* original */
			case 0x138f: /* original + 30 char names */
			case 0x2468: /* V2 */
			case 0x2478: /* V2 + 30 char names */
				memcpy_tofs(buf, "minix", 6);
				break;
			case 0x564c:
				memcpy_tofs(buf, "ncpfs", 6);
				break;
			case 0x517b:
				memcpy_tofs(buf, "smbfs", 6);
				break;
			case 0x00011954:
				memcpy_tofs(buf, "ufs", 4);
				break;
			case 0x012fd16d: case 0xffffd16d:
				memcpy_tofs(buf, "xiafs", 6);
				break;
			case 0x012ff7b3+1: case 0xfffff7b3+1:
				memcpy_tofs(buf, "xenix", 6);
				break;
			case 0x012ff7b3+2: case 0xfffff7b3+2:
			case 0x012ff7b3+3: case 0xfffff7b3+3:
				memcpy_tofs(buf, "sysv", 5);
				break;
			case 0x012ff7b3+4: case 0xfffff7b3+4:
				memcpy_tofs(buf, "coherent", 9);
				break;
			default:
				memcpy_tofs(buf, "", 1);
				break;
		}
		return 0;
	}

#ifdef IBCS_TRACE
	if ((ibcs_trace & TRACE_API) || ibcs_func_p->trace) {
		printk(KERN_DEBUG "iBCS2 unsupported sysfs call %d\n", cmd);
	}
#endif
	return -EINVAL;
}
