Subject: kern/3711: ibcs2 emulation lacks sysfs()
To: None <gnats-bugs@gnats.netbsd.org>
From: None <arnej@math.ntnu.no>
List: netbsd-bugs
Date: 06/05/1997 15:53:08
>Number:         3711
>Category:       kern
>Synopsis:       ibcs2 emulation lacks sysfs()
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Jun  5 07:05:01 1997
>Last-Modified:
>Originator:     Arne H. Juul
>Organization:
	Norwegian University of Technology and Science
>Release:        NetBSD-current as of Jun 5, 1997
>Environment:
	
System: NetBSD leon.math.ntnu.no 1.2E NetBSD 1.2E (NIKITA) #14: Thu Jun 5 14:39:16 CEST 1997 arnej@leon.math.ntnu.no:/usr/src/sys/arch/i386/compile/NIKITA i386


>Description:
	The IBCS2 emulation environment in NetBSD has stubbed out
	the sysfs() call.  This causes problems for some types of
	programs, in my case AXXiON-NetBackup.

	To implement sysfs() one needs to establish a mapping
	between filesystem-type name and number.  I noticed that
	the FreeBSD emulation already has such a mapping, so I
	extended that emulation a bit and made it common instead
	of making another version.  The mapping should in theory
	be dynamic, but in practice it suffices to add new
	filesystem types as (or preferrably a bit before) they
	are implemented for Net/FreeBSD.

>How-To-Repeat:
	Try to run a SCO (or other ibcs2) program that uses sysfs().
>Fix:
	Apply following patch:

diff -ruN compat.orig/common/Makefile compat/common/Makefile
--- compat.orig/common/Makefile	Sun Jun  1 07:16:22 1997
+++ compat/common/Makefile	Thu Jun  5 14:19:39 1997
@@ -7,7 +7,8 @@
 
 SRCS=	compat_exec.c compat_util.c kern_exit_43.c kern_info_09.c \
 	kern_info_43.c kern_resource_43.c kern_sig_43.c kern_xxx_12.c \
-	tty_43.c uipc_syscalls_43.c vfs_syscalls_43.c vm_43.c
+	tty_43.c uipc_syscalls_43.c vfs_syscalls_43.c vm_43.c \
+	compat_mnttype.c
 
 # really, all machines where sizeof(int) != sizeof(long)
 .if (${MACHINE_ARCH} != "alpha")
diff -ruN compat.orig/common/compat_mnttype.c compat/common/compat_mnttype.c
--- compat.orig/common/compat_mnttype.c	Thu Jan  1 01:00:00 1970
+++ compat/common/compat_mnttype.c	Thu Jun  5 14:08:01 1997
@@ -0,0 +1,66 @@
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mount.h>
+#include <compat/common/compat_mnttype.h>
+
+/*
+ * List of filesystem types.  This needs to be updated whenever
+ * a) somebody adds a filesystem to NetBSD
+ * b) somebody adds a filesystem to FreeBSD
+ * Used for binary compatibility modes, primarily with FreeBSD,
+ * but also for SysV, see ibcs2_sys_sysfs().
+ *
+ * LKM filesystems are not supported.
+ */
+static char *netbsd_mount_type[] = {
+		"(none)", /*  0 = MOUNT_NONE */
+		"ffs",	  /*  1 = "Fast" Filesystem */
+		"nfs",	  /*  2 = Network Filesystem */
+		"mfs",	  /*  3 = Memory Filesystem */
+		"msdos",  /*  4 = MSDOS Filesystem */
+		"lfs",	  /*  5 = Log-based Filesystem */
+		"lofs",	  /*  6 = Loopback filesystem */
+		"fdesc",  /*  7 = File Descriptor Filesystem */
+		"portal", /*  8 = Portal Filesystem */
+		"null",	  /*  9 = Minimal Filesystem Layer */
+		"umap",	  /* 10 = User/Group Identifier Remapping Filesystem */
+		"kernfs", /* 11 = Kernel Information Filesystem */
+		"procfs", /* 12 = /proc Filesystem */
+		"afs",	  /* 13 = Andrew Filesystem */
+		"cd9660", /* 14 = ISO9660 (aka CDROM) Filesystem */
+		"union",  /* 15 = Union (translucent) Filesystem */
+			  /* These filesystems don't exist in NetBSD yet */
+		NULL,     /* 16 = "devfs" - existing device Filesystem */
+		"ext2fs", /* 17 = Linux EXT2FS */
+		"netcon", /* 18 = Netcon Novell filesystem */
+			  /* These filesystems don't exist in FreeBSD */
+		"adosfs", /* 19 = AmigaDOS Filesystem */
+};
+#define NUMFSTYPES 20
+
+int
+convert_mount_type_to_num(const char *name, int *num)
+{
+	int i;
+	for (i=0; i<NUMFSTYPES; i++) {
+		if (!strcmp(name, netbsd_mount_type[i])) {
+			*num = i;
+			return 0;
+		}
+	}
+	return EINVAL;
+}
+
+char *
+convert_mount_type_to_name(int num)
+{
+	if (num>=0 && num<NUMFSTYPES) {
+		return (netbsd_mount_type[num]);
+	}
+	return (NULL);
+}
+
+int get_num_mount_types(void)
+{
+	return NUMFSTYPES;
+}
diff -ruN compat.orig/common/compat_mnttype.h compat/common/compat_mnttype.h
--- compat.orig/common/compat_mnttype.h	Thu Jan  1 01:00:00 1970
+++ compat/common/compat_mnttype.h	Thu Jun  5 10:33:06 1997
@@ -0,0 +1,3 @@
+extern int convert_mount_type_to_num(const char *name, int *num);
+extern char *convert_mount_type_to_name(int num);
+extern int get_num_mount_types(void);
diff -ruN compat.orig/freebsd/freebsd_file.c compat/freebsd/freebsd_file.c
--- compat.orig/freebsd/freebsd_file.c	Fri Jan 31 13:21:23 1997
+++ compat/freebsd/freebsd_file.c	Thu Jun  5 14:19:10 1997
@@ -49,45 +49,12 @@
 
 #include <compat/freebsd/freebsd_syscallargs.h>
 #include <compat/freebsd/freebsd_util.h>
+#include <compat/common/compat_mnttype.h>
 
 #define	ARRAY_LENGTH(array)	(sizeof(array)/sizeof(array[0]))
 
 const char freebsd_emul_path[] = "/emul/freebsd";
 
-static char * convert_from_freebsd_mount_type __P((int));
-
-static char *
-convert_from_freebsd_mount_type(type)
-	int type;
-{
-	static char *netbsd_mount_type[] = {
-		NULL,     /*  0 = MOUNT_NONE */
-		"ffs",	  /*  1 = "Fast" Filesystem */
-		"nfs",	  /*  2 = Network Filesystem */
-		"mfs",	  /*  3 = Memory Filesystem */
-		"msdos",  /*  4 = MSDOS Filesystem */
-		"lfs",	  /*  5 = Log-based Filesystem */
-		"lofs",	  /*  6 = Loopback filesystem */
-		"fdesc",  /*  7 = File Descriptor Filesystem */
-		"portal", /*  8 = Portal Filesystem */
-		"null",	  /*  9 = Minimal Filesystem Layer */
-		"umap",	  /* 10 = User/Group Identifier Remapping Filesystem */
-		"kernfs", /* 11 = Kernel Information Filesystem */
-		"procfs", /* 12 = /proc Filesystem */
-		"afs",	  /* 13 = Andrew Filesystem */
-		"cd9660", /* 14 = ISO9660 (aka CDROM) Filesystem */
-		"union",  /* 15 = Union (translucent) Filesystem */
-		NULL,     /* 16 = "devfs" - existing device Filesystem */
-#if 0 /* These filesystems don't exist in FreeBSD */
-		"adosfs", /* ?? = AmigaDOS Filesystem */
-#endif
-	};
-
-	if (type < 0 || type >= ARRAY_LENGTH(netbsd_mount_type))
-		return (NULL);
-	return (netbsd_mount_type[type]);
-}
-
 int
 freebsd_sys_mount(p, v, retval)
 	struct proc *p;
@@ -105,7 +72,7 @@
 	caddr_t sg = stackgap_init(p->p_emul);
 	struct sys_mount_args bma;
 
-	if ((type = convert_from_freebsd_mount_type(SCARG(uap, type))) == NULL)
+	if ((type = convert_mount_type_to_name(SCARG(uap, type))) == NULL)
 		return ENODEV;
 	s = stackgap_alloc(&sg, MFSNAMELEN + 1);
 	if ((error = copyout(type, s, strlen(type) + 1)) != 0)
diff -ruN compat.orig/ibcs2/ibcs2_misc.c compat/ibcs2/ibcs2_misc.c
--- compat.orig/ibcs2/ibcs2_misc.c	Thu Mar 27 13:20:43 1997
+++ compat/ibcs2/ibcs2_misc.c	Thu Jun  5 14:17:15 1997
@@ -103,6 +103,8 @@
 #include <compat/ibcs2/ibcs2_syscallargs.h>
 #include <compat/ibcs2/ibcs2_sysi86.h>
 
+#include <compat/common/compat_mnttype.h>
+
 
 int
 ibcs2_sys_ulimit(p, v, retval)
@@ -1173,6 +1175,10 @@
 	return EINVAL;
 }
 
+/*
+ * This call takes one, two, or three parameters,
+ * and the types differ.  Yeuch.
+ */
 int
 ibcs2_sys_sysfs(p, v, retval)
 	struct proc *p;
@@ -1184,17 +1190,47 @@
 		syscallarg(caddr_t) d1;
 		syscallarg(char *) buf;
 	} */ *uap = v;
+	int error, i;
+	char fstype[MFSNAMELEN];
+	char *fst;
 
 #define IBCS2_GETFSIND        1
 #define IBCS2_GETFSTYP        2
 #define IBCS2_GETNFSTYP       3
 
+extern int convert_mount_type_to_num(const char *name, int *num);
+extern char *convert_mount_type_to_name(int num);
+
 	switch(SCARG(uap, cmd)) {
 	case IBCS2_GETFSIND:
+		if ((error = copyinstr(SCARG(uap, d1), fstype,
+				 sizeof fstype, (u_int *)0)))
+			return (error);
+		/* special case nfs. */
+		if (!strcmp(fstype, "NFS")) strcpy(fstype, "nfs");
+		error = convert_mount_type_to_num(fstype, retval);
+		return (error);
 	case IBCS2_GETFSTYP:
+		i = (int)SCARG(uap, d1);
+		fst = convert_mount_type_to_name(i);
+		if (fst) {
+			/* special case nfs AGAIN. */
+			if (!strcmp(fst, "nfs"))
+				strcpy(fstype, "NFS");
+			else
+				strcpy(fstype, fst);
+			if ((error = copyout(fstype, SCARG(uap, buf),
+						strlen(fstype)+1)))
+				return (error);
+			*retval = 0;
+			return 0;
+		}
+		return EINVAL;
 	case IBCS2_GETNFSTYP:
+		*retval = get_num_mount_types();
+		return 0;
 	}
-	return EINVAL;		/* XXX - TODO */
+	return EINVAL;
 }
 
 int
diff -ruN compat.orig/ibcs2/ibcs2_stat.c compat/ibcs2/ibcs2_stat.c
--- compat.orig/ibcs2/ibcs2_stat.c	Sat May  4 13:50:20 1996
+++ compat/ibcs2/ibcs2_stat.c	Thu Jun  5 14:17:29 1997
@@ -39,6 +39,7 @@
 #include <sys/malloc.h>
 #include <sys/vnode.h>
 #include <sys/syscallargs.h>
+#include <sys/syslog.h>
 
 #include <vm/vm.h>
 
@@ -52,6 +53,8 @@
 #include <compat/ibcs2/ibcs2_util.h>
 #include <compat/ibcs2/ibcs2_utsname.h>
 
+#include <compat/common/compat_mnttype.h>
+
 static void bsd_stat2ibcs_stat __P((struct ostat *, struct ibcs2_stat *));
 static int cvt_statfs __P((struct statfs *, caddr_t, int));
 
@@ -81,9 +84,16 @@
 	int len;
 {
 	struct ibcs2_statfs ssfs;
+	int fstyp;
 
 	bzero(&ssfs, sizeof ssfs);
-	ssfs.f_fstyp = 0;
+	if (convert_mount_type_to_num(sp->f_fstypename, &fstyp)) {
+		log(LOG_WARNING, "Unknown fstypename %s in ibcs2 cvt_statfs\n",
+			sp->f_fstypename);
+		ssfs.f_fstyp = 0;
+	} else {
+		ssfs.f_fstyp = fstyp;
+	}
 	ssfs.f_bsize = sp->f_bsize;
 	ssfs.f_frsize = 0;
 	ssfs.f_blocks = sp->f_blocks;
>Audit-Trail:
>Unformatted: