Module Name:    src
Committed By:   tsutsui
Date:           Sun Dec 25 06:09:10 UTC 2011

Modified Files:
        src/sys/arch/ews4800mips/stand/boot: Makefile
        src/sys/arch/ews4800mips/stand/common: devopen.c diskutil.c
        src/sys/arch/i386/stand/boot: Makefile.boot boot2.c
        src/sys/arch/i386/stand/dosboot: Makefile main.c
        src/sys/arch/i386/stand/libsa: nfs.c
        src/sys/arch/landisk/stand/boot: Makefile.boot boot2.c
        src/sys/arch/x68k/stand/boot: Makefile boot.c
        src/sys/arch/x68k/stand/libsa: Makefile
        src/sys/arch/zaurus/stand/zboot: Makefile boot.c
        src/sys/lib/libsa: Makefile cd9660.c dosfs.c ext2fs.c ffsv1.c ffsv2.c
            lfsv1.c lfsv2.c nfs.c nullfs.c stand.h tftp.c ufs.c ufs.h ustarfs.c
Added Files:
        src/sys/lib/libsa: ls.c
Removed Files:
        src/sys/lib/libsa: ufs_ls.c

Log Message:
Apply the following patch submitted by Evgeniy Ivanov:
http://mail-index.NetBSD.org/tech-kern/2011/12/15/msg012226.html
http://mail-index.NetBSD.org/tech-kern/2011/12/17/msg012229.html

 - add 'ls' op to struct fs_ops to support ls command on each fs,
   enabled by -DLIBSA_ENABLE_LS_OP and SAMISCMAKEFLAGS+="SA_ENABLE_LS_OP=yes"
   in libsa
 - split sys/lib/libsa/ufs_ls.c into UFS specific part and MI part (ls.c)
   that opens the target fs and calls fs-depedent XXX_ls() functions
 - add a ls op for ext2fs
   (all other fs than ufs and ext2fs don't have actual ls ops yet)
 - replace existing MD ufs_ls() calls with this new MI ls()

The original patch was written for i386 and ext2fs.
zaurus zboot has been tested by nonaka@.
ews4800mips and x68k loaders have been tested by me (with several fixes).
landisk might be okay since it was almost copied from i386.

XXX1: "ls" op in fs_ops looks a bit inconsistent, but we will be able to
      replace it with real fs ops like readdir if it's really worth
XXX2: someone might have to check sys/arch/ia64/stand/efi/libefi/efifs_ls.c


To generate a diff of this commit:
cvs rdiff -u -r1.14 -r1.15 src/sys/arch/ews4800mips/stand/boot/Makefile
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/ews4800mips/stand/common/devopen.c \
    src/sys/arch/ews4800mips/stand/common/diskutil.c
cvs rdiff -u -r1.55 -r1.56 src/sys/arch/i386/stand/boot/Makefile.boot
cvs rdiff -u -r1.56 -r1.57 src/sys/arch/i386/stand/boot/boot2.c
cvs rdiff -u -r1.26 -r1.27 src/sys/arch/i386/stand/dosboot/Makefile
cvs rdiff -u -r1.30 -r1.31 src/sys/arch/i386/stand/dosboot/main.c
cvs rdiff -u -r1.18 -r1.19 src/sys/arch/i386/stand/libsa/nfs.c
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/landisk/stand/boot/Makefile.boot
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/landisk/stand/boot/boot2.c
cvs rdiff -u -r1.20 -r1.21 src/sys/arch/x68k/stand/boot/Makefile
cvs rdiff -u -r1.16 -r1.17 src/sys/arch/x68k/stand/boot/boot.c
cvs rdiff -u -r1.27 -r1.28 src/sys/arch/x68k/stand/libsa/Makefile
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/zaurus/stand/zboot/Makefile
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/zaurus/stand/zboot/boot.c
cvs rdiff -u -r1.75 -r1.76 src/sys/lib/libsa/Makefile
cvs rdiff -u -r1.27 -r1.28 src/sys/lib/libsa/cd9660.c
cvs rdiff -u -r1.17 -r1.18 src/sys/lib/libsa/dosfs.c
cvs rdiff -u -r1.10 -r1.11 src/sys/lib/libsa/ext2fs.c \
    src/sys/lib/libsa/nullfs.c
cvs rdiff -u -r1.4 -r1.5 src/sys/lib/libsa/ffsv1.c src/sys/lib/libsa/ffsv2.c
cvs rdiff -u -r1.3 -r1.4 src/sys/lib/libsa/lfsv1.c src/sys/lib/libsa/lfsv2.c
cvs rdiff -u -r0 -r1.3 src/sys/lib/libsa/ls.c
cvs rdiff -u -r1.46 -r1.47 src/sys/lib/libsa/nfs.c
cvs rdiff -u -r1.73 -r1.74 src/sys/lib/libsa/stand.h
cvs rdiff -u -r1.33 -r1.34 src/sys/lib/libsa/tftp.c \
    src/sys/lib/libsa/ustarfs.c
cvs rdiff -u -r1.55 -r1.56 src/sys/lib/libsa/ufs.c
cvs rdiff -u -r1.9 -r1.10 src/sys/lib/libsa/ufs.h
cvs rdiff -u -r1.14 -r0 src/sys/lib/libsa/ufs_ls.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/ews4800mips/stand/boot/Makefile
diff -u src/sys/arch/ews4800mips/stand/boot/Makefile:1.14 src/sys/arch/ews4800mips/stand/boot/Makefile:1.15
--- src/sys/arch/ews4800mips/stand/boot/Makefile:1.14	Sun Jul 10 23:35:12 2011
+++ src/sys/arch/ews4800mips/stand/boot/Makefile	Sun Dec 25 06:09:08 2011
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.14 2011/07/10 23:35:12 matt Exp $
+#	$NetBSD: Makefile,v 1.15 2011/12/25 06:09:08 tsutsui Exp $
 
 WARNS		?= 1
 NOMAN		=
@@ -89,7 +89,8 @@ LIBKERN=	${KERNLIB}
 .include "${S}/lib/libz/Makefile.inc"
 LIBZ=		${ZLIB}
 
-SAMISCMAKEFLAGS= SA_USE_CREAD=yes SA_USE_LOADFILE=yes
+CPPFLAGS+= -DLIBSA_ENABLE_LS_OP
+SAMISCMAKEFLAGS= SA_USE_CREAD=yes SA_USE_LOADFILE=yes SA_ENABLE_LS_OP=yes
 .include "${S}/lib/libsa/Makefile.inc"
 LIBSA=		${SALIB}
 

Index: src/sys/arch/ews4800mips/stand/common/devopen.c
diff -u src/sys/arch/ews4800mips/stand/common/devopen.c:1.4 src/sys/arch/ews4800mips/stand/common/devopen.c:1.5
--- src/sys/arch/ews4800mips/stand/common/devopen.c:1.4	Mon Apr 28 20:23:18 2008
+++ src/sys/arch/ews4800mips/stand/common/devopen.c	Sun Dec 25 06:09:09 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: devopen.c,v 1.4 2008/04/28 20:23:18 martin Exp $	*/
+/*	$NetBSD: devopen.c,v 1.5 2011/12/25 06:09:09 tsutsui Exp $	*/
 
 /*-
  * Copyright (c) 2004 The NetBSD Foundation, Inc.
@@ -46,12 +46,8 @@ extern int kernel_binary_size;
 
 extern struct fs_ops datafs_ops;
 extern struct fs_ops bfs_ops;
-struct fs_ops ufs_ops = {
-	ufs_open, ufs_close, ufs_read, ufs_write, ufs_seek, ufs_stat
-};
-struct fs_ops nfs_ops = {
-	nfs_open, nfs_close, nfs_read, nfs_write, nfs_seek, nfs_stat
-};
+struct fs_ops ufs_ops = FS_OPS(ufs);
+struct fs_ops nfs_ops = FS_OPS(nfs);
 
 extern struct devsw netdevsw;
 extern struct devsw dkdevsw;
Index: src/sys/arch/ews4800mips/stand/common/diskutil.c
diff -u src/sys/arch/ews4800mips/stand/common/diskutil.c:1.4 src/sys/arch/ews4800mips/stand/common/diskutil.c:1.5
--- src/sys/arch/ews4800mips/stand/common/diskutil.c:1.4	Mon Apr 28 20:23:18 2008
+++ src/sys/arch/ews4800mips/stand/common/diskutil.c	Sun Dec 25 06:09:09 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: diskutil.c,v 1.4 2008/04/28 20:23:18 martin Exp $	*/
+/*	$NetBSD: diskutil.c,v 1.5 2011/12/25 06:09:09 tsutsui Exp $	*/
 
 /*-
  * Copyright (c) 2004 The NetBSD Foundation, Inc.
@@ -85,14 +85,12 @@ cmd_ls(int argc, char *argp[], int inter
 	if (!device_attach(-1, -1, i))
 		return 1;
 	switch (fstype(i)) {
-	case FSTYPE_UFS:
-		ufs_ls("/");
-		break;
 	case FSTYPE_BFS:
 		bfs_ls();
 		break;
 	default:
-		return 1;
+		ls("/");
+		break;
 	}
 
 	return 0;

Index: src/sys/arch/i386/stand/boot/Makefile.boot
diff -u src/sys/arch/i386/stand/boot/Makefile.boot:1.55 src/sys/arch/i386/stand/boot/Makefile.boot:1.56
--- src/sys/arch/i386/stand/boot/Makefile.boot:1.55	Mon Aug 22 09:43:08 2011
+++ src/sys/arch/i386/stand/boot/Makefile.boot	Sun Dec 25 06:09:09 2011
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.boot,v 1.55 2011/08/22 09:43:08 mrg Exp $
+# $NetBSD: Makefile.boot,v 1.56 2011/12/25 06:09:09 tsutsui Exp $
 
 S=	${.CURDIR}/../../../../..
 
@@ -76,6 +76,7 @@ CPPFLAGS+= -DPASS_MEMMAP
 CPPFLAGS+= -DEPIA_HACK
 #CPPFLAGS+= -DDEBUG_MEMSIZE
 #CPPFLAGS+= -DBOOT_MSG_COM0
+CPPFLAGS+= -DLIBSA_ENABLE_LS_OP
 
 # The biosboot code is linked to 'virtual' address of zero and is
 # loaded at physical address 0x10000.
@@ -113,6 +114,7 @@ LIBI386= ${I386LIB}
 ### find out what to use for libsa
 SA_AS= library
 SAMISCMAKEFLAGS+="SA_USE_LOADFILE=yes"
+SAMISCMAKEFLAGS+="SA_ENABLE_LS_OP=yes"
 .include "${S}/lib/libsa/Makefile.inc"
 LIBSA= ${SALIB}
 

Index: src/sys/arch/i386/stand/boot/boot2.c
diff -u src/sys/arch/i386/stand/boot/boot2.c:1.56 src/sys/arch/i386/stand/boot/boot2.c:1.57
--- src/sys/arch/i386/stand/boot/boot2.c:1.56	Mon Nov 28 07:56:54 2011
+++ src/sys/arch/i386/stand/boot/boot2.c	Sun Dec 25 06:09:09 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: boot2.c,v 1.56 2011/11/28 07:56:54 tls Exp $	*/
+/*	$NetBSD: boot2.c,v 1.57 2011/12/25 06:09:09 tsutsui Exp $	*/
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -409,7 +409,7 @@ command_ls(char *arg)
 	const char *save = default_filename;
 
 	default_filename = "/";
-	ufs_ls(arg);
+	ls(arg);
 	default_filename = save;
 }
 

Index: src/sys/arch/i386/stand/dosboot/Makefile
diff -u src/sys/arch/i386/stand/dosboot/Makefile:1.26 src/sys/arch/i386/stand/dosboot/Makefile:1.27
--- src/sys/arch/i386/stand/dosboot/Makefile:1.26	Fri May 20 22:29:55 2011
+++ src/sys/arch/i386/stand/dosboot/Makefile	Sun Dec 25 06:09:09 2011
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.26 2011/05/20 22:29:55 joerg Exp $
+#	$NetBSD: Makefile,v 1.27 2011/12/25 06:09:09 tsutsui Exp $
 
 S=	${.CURDIR}/../../../..
 
@@ -17,6 +17,7 @@ SRCS= main.c devopen.c exec.c
 CPPFLAGS+= -DSLOW	# for libz
 CPPFLAGS+= -DCOMPAT_386BSD_MBRPART
 CPPFLAGS+= -DXMS
+CPPFLAGS+= -DLIBSA_ENABLE_LS_OP
 #uncomment if there are problems with memory detection
 #CPPFLAGS+= -DCONSERVATIVE_MEMDETECT
 
@@ -30,7 +31,7 @@ SRCS+= getopt.c
 # XXX these should depend on the size of the image
 CPPFLAGS+= -DSTACK_START=0x10000
 SAMISCCPPFLAGS+= -DHEAP_START=0x20000 -DHEAP_LIMIT=0x50000
-SAMISCMAKEFLAGS= SA_USE_CREAD=yes SA_INCLUDE_NET=no
+SAMISCMAKEFLAGS= SA_USE_CREAD=yes SA_INCLUDE_NET=no SA_ENABLE_LS_OP=yes
 I386MISCMAKEFLAGS= I386_INCLUDE_DOS=yes
 
 VERSIONFILE= ${.CURDIR}/version

Index: src/sys/arch/i386/stand/dosboot/main.c
diff -u src/sys/arch/i386/stand/dosboot/main.c:1.30 src/sys/arch/i386/stand/dosboot/main.c:1.31
--- src/sys/arch/i386/stand/dosboot/main.c:1.30	Mon Dec 20 01:12:44 2010
+++ src/sys/arch/i386/stand/dosboot/main.c	Sun Dec 25 06:09:09 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: main.c,v 1.30 2010/12/20 01:12:44 jakllsch Exp $	 */
+/*	$NetBSD: main.c,v 1.31 2011/12/25 06:09:09 tsutsui Exp $	 */
 
 /*
  * Copyright (c) 1996, 1997
@@ -323,12 +323,8 @@ void
 command_ls(char *arg)
 {
 	char *help = default_filename;
-	if (strcmp(current_fsmode, "ufs")) {
-		printf("UFS only\n");
-		return;
-	}
 	default_filename = "/";
-	ufs_ls(arg);
+	ls(arg);
 	default_filename = help;
 }
 

Index: src/sys/arch/i386/stand/libsa/nfs.c
diff -u src/sys/arch/i386/stand/libsa/nfs.c:1.18 src/sys/arch/i386/stand/libsa/nfs.c:1.19
--- src/sys/arch/i386/stand/libsa/nfs.c:1.18	Thu Jun 16 13:27:59 2011
+++ src/sys/arch/i386/stand/libsa/nfs.c	Sun Dec 25 06:09:09 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: nfs.c,v 1.18 2011/06/16 13:27:59 joerg Exp $	*/
+/*	$NetBSD: nfs.c,v 1.19 2011/12/25 06:09:09 tsutsui Exp $	*/
 
 /*-
  *  Copyright (c) 1993 John Brezak
@@ -630,3 +630,12 @@ nfs_stat(struct open_file *f, struct sta
 
 	return (0);
 }
+
+#if defined(LIBSA_ENABLE_LS_OP)
+__compactcall void
+nfs_ls(struct open_file *f, const char *pattern)
+{
+	printf("Currently ls command is unsupported by nfs\n");
+	return;
+}
+#endif

Index: src/sys/arch/landisk/stand/boot/Makefile.boot
diff -u src/sys/arch/landisk/stand/boot/Makefile.boot:1.4 src/sys/arch/landisk/stand/boot/Makefile.boot:1.5
--- src/sys/arch/landisk/stand/boot/Makefile.boot:1.4	Sat Jan 22 19:19:19 2011
+++ src/sys/arch/landisk/stand/boot/Makefile.boot	Sun Dec 25 06:09:09 2011
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.boot,v 1.4 2011/01/22 19:19:19 joerg Exp $
+# $NetBSD: Makefile.boot,v 1.5 2011/12/25 06:09:09 tsutsui Exp $
 
 PROG?=		boot
 
@@ -22,10 +22,12 @@ CPPFLAGS+=	-DSUPPORT_FFSv2
 CPPFLAGS+=	-DSUPPORT_DOSFS
 CPPFLAGS+=	-DSUPPORT_USTARFS
 CPPFLAGS+=	-DDBMONITOR
+CPPFLAGS+=	-DLIBSA_ENABLE_LS_OP
 #CPPFLAGS+=	-DDEBUG
 
 SAMISCMAKEFLAGS+="SA_USE_CREAD=yes"
 SAMISCMAKEFLAGS+="SA_USE_LOADFILE=yes"
+SAMISCMAKEFLAGS+="SA_ENABLE_LS_OP=yes"
 
 .include "../Makefile.bootprogs"
 

Index: src/sys/arch/landisk/stand/boot/boot2.c
diff -u src/sys/arch/landisk/stand/boot/boot2.c:1.2 src/sys/arch/landisk/stand/boot/boot2.c:1.3
--- src/sys/arch/landisk/stand/boot/boot2.c:1.2	Sat Jan 22 19:19:19 2011
+++ src/sys/arch/landisk/stand/boot/boot2.c	Sun Dec 25 06:09:09 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: boot2.c,v 1.2 2011/01/22 19:19:19 joerg Exp $	*/
+/*	$NetBSD: boot2.c,v 1.3 2011/12/25 06:09:09 tsutsui Exp $	*/
 
 /*
  * Copyright (c) 2003
@@ -329,7 +329,7 @@ bootcmd_ls(char *arg)
 	const char *save = default_filename;
 
 	default_filename = "/";
-	ufs_ls(arg);
+	ls(arg);
 	default_filename = save;
 }
 

Index: src/sys/arch/x68k/stand/boot/Makefile
diff -u src/sys/arch/x68k/stand/boot/Makefile:1.20 src/sys/arch/x68k/stand/boot/Makefile:1.21
--- src/sys/arch/x68k/stand/boot/Makefile:1.20	Tue Apr 12 14:07:35 2011
+++ src/sys/arch/x68k/stand/boot/Makefile	Sun Dec 25 06:09:09 2011
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.20 2011/04/12 14:07:35 tsutsui Exp $
+#	$NetBSD: Makefile,v 1.21 2011/12/25 06:09:09 tsutsui Exp $
 
 NOMAN=		# defined
 
@@ -40,6 +40,7 @@ CPPFLAGS+=	-I$M/stand/libiocs -I${COMMON
 CPPFLAGS+=	-D_STANDALONE -DHEAP_VARIABLE
 CPPFLAGS+=	-DTEXTADDR="0x${TEXT}" 
 CPPFLAGS+=	-DBOOT=\"${BOOT}\" -DBOOT_VERS=\"${VERSION}\"
+CPPFLAGS+=	-DLIBSA_ENABLE_LS_OP
 CFLAGS=		-Wno-main -Os -m68020-60
 LINKFLAGS=	-N -static -T ${.CURDIR}/boot.ldscript
 LIBIOCS!=	cd $M/stand/libiocs && ${PRINTOBJDIR}

Index: src/sys/arch/x68k/stand/boot/boot.c
diff -u src/sys/arch/x68k/stand/boot/boot.c:1.16 src/sys/arch/x68k/stand/boot/boot.c:1.17
--- src/sys/arch/x68k/stand/boot/boot.c:1.16	Sat Jan 22 19:19:24 2011
+++ src/sys/arch/x68k/stand/boot/boot.c	Sun Dec 25 06:09:09 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: boot.c,v 1.16 2011/01/22 19:19:24 joerg Exp $	*/
+/*	$NetBSD: boot.c,v 1.17 2011/12/25 06:09:09 tsutsui Exp $	*/
 
 /*
  * Copyright (c) 2001 Minoura Makoto
@@ -53,7 +53,7 @@ static void help(void);
 static int get_scsi_host_adapter(void);
 static void doboot(const char *, int);
 static void boot(char *);
-static void ls(char *);
+static void cmd_ls(char *);
 int bootmenu(void);
 void bootmain(int);
 extern int detectmpu(void);
@@ -201,7 +201,7 @@ boot(char *arg)
 }
 
 static void
-ls(char *arg)
+cmd_ls(char *arg)
 {
 	char filename[80];
 
@@ -217,7 +217,7 @@ ls(char *arg)
 		if (*(strchr(arg, ':')+1) == 0)
 			strcat(filename, "/");
 	}
-	ufs_ls(filename);
+	ls(filename);
 	devopen_open_dir = 0;
 }
 
@@ -266,7 +266,7 @@ bootmenu(void)
 		else if ((strcmp("halt", p) == 0) ||(strcmp("reboot", p) == 0))
 			exit(0);
 		else if (strcmp("ls", p) == 0)
-			ls(options);
+			cmd_ls(options);
 		else
 			printf("Unknown command %s\n", p);
 	}

Index: src/sys/arch/x68k/stand/libsa/Makefile
diff -u src/sys/arch/x68k/stand/libsa/Makefile:1.27 src/sys/arch/x68k/stand/libsa/Makefile:1.28
--- src/sys/arch/x68k/stand/libsa/Makefile:1.27	Tue Oct 11 13:07:06 2011
+++ src/sys/arch/x68k/stand/libsa/Makefile	Sun Dec 25 06:09:09 2011
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.27 2011/10/11 13:07:06 tsutsui Exp $
+#	$NetBSD: Makefile,v 1.28 2011/12/25 06:09:09 tsutsui Exp $
 
 S=		${.CURDIR}/../../../..
 
@@ -10,6 +10,7 @@ CPPFLAGS+=	-D_STANDALONE
 CPPFLAGS+=	-DHEAP_VARIABLE
 CPPFLAGS+=	-DHAVE_CHANGEDISK_HOOK
 CPPFLAGS+=	-DUSTAR_SECT_PER_CYL=16
+CPPFLAGS+=	-DLIBSA_ENABLE_LS_OP
 #CPPFLAGS+=	-DDEBUG
 
 .PATH:	${LIBSADIR} ${LIBKERNDIR} ${LIBZDIR} ${LIBZDIST}
@@ -33,7 +34,7 @@ LIBZ= ${ZLIB}
 
 ### find out what to use for libsa
 SA_AS= library
-SAMISCMAKEFLAGS= SA_USE_CREAD=yes SA_USE_LOADFILE=yes SA_EXTRADIR=${.CURDIR}
+SAMISCMAKEFLAGS= SA_USE_CREAD=yes SA_USE_LOADFILE=yes SA_ENABLE_LS_OP=yes SA_EXTRADIR=${.CURDIR}
 .include "${S}/lib/libsa/Makefile.inc"
 LIBSA= ${SALIB}
 

Index: src/sys/arch/zaurus/stand/zboot/Makefile
diff -u src/sys/arch/zaurus/stand/zboot/Makefile:1.6 src/sys/arch/zaurus/stand/zboot/Makefile:1.7
--- src/sys/arch/zaurus/stand/zboot/Makefile:1.6	Sun Jan 23 13:17:02 2011
+++ src/sys/arch/zaurus/stand/zboot/Makefile	Sun Dec 25 06:09:10 2011
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.6 2011/01/23 13:17:02 joerg Exp $
+#	$NetBSD: Makefile,v 1.7 2011/12/25 06:09:10 tsutsui Exp $
 
 PROG=		zboot
 
@@ -18,6 +18,7 @@ CFLAGS+=	-Wmissing-prototypes -Wstrict-p
 CFLAGS+=	-fno-stack-protector -fno-builtin -ffreestanding
 CPPFLAGS+=	-nostdinc -I. -I${.CURDIR} -I${.OBJDIR} -I${S}
 CPPFLAGS+=	-D_STANDALONE -DHEAP_VARIABLE
+CPPFLAGS+=	-DLIBSA_ENABLE_LS_OP
 AFLAGS+=	-D_LOCORE
 LDFLAGS+=	-nostdlib -Bstatic
 
@@ -43,7 +44,7 @@ LIBZ=		${ZLIB}
 
 ### find out what to use for libsa
 SA_AS=		library
-SAMISCMAKEFLAGS= SA_USE_CREAD=yes SA_USE_LOADFILE=yes
+SAMISCMAKEFLAGS= SA_USE_CREAD=yes SA_USE_LOADFILE=yes SA_ENABLE_LS_OP=yes
 .include "${S}/lib/libsa/Makefile.inc"
 LIBSA=		${SALIB}
 

Index: src/sys/arch/zaurus/stand/zboot/boot.c
diff -u src/sys/arch/zaurus/stand/zboot/boot.c:1.3 src/sys/arch/zaurus/stand/zboot/boot.c:1.4
--- src/sys/arch/zaurus/stand/zboot/boot.c:1.3	Mon Jun 20 12:39:21 2011
+++ src/sys/arch/zaurus/stand/zboot/boot.c	Sun Dec 25 06:09:10 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: boot.c,v 1.3 2011/06/20 12:39:21 nonaka Exp $	*/
+/*	$NetBSD: boot.c,v 1.4 2011/12/25 06:09:10 tsutsui Exp $	*/
 
 /*
  * Copyright (c) 2009 NONAKA Kimihiro <non...@netbsd.org>
@@ -323,7 +323,7 @@ bootcmd_ls(char *arg)
 	const char *save = default_filename;
 
 	default_filename = "/";
-	ufs_ls(arg);
+	ls(arg);
 	default_filename = save;
 }
 

Index: src/sys/lib/libsa/Makefile
diff -u src/sys/lib/libsa/Makefile:1.75 src/sys/lib/libsa/Makefile:1.76
--- src/sys/lib/libsa/Makefile:1.75	Sun Jul  3 15:29:35 2011
+++ src/sys/lib/libsa/Makefile	Sun Dec 25 06:09:08 2011
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.75 2011/07/03 15:29:35 mrg Exp $
+#	$NetBSD: Makefile,v 1.76 2011/12/25 06:09:08 tsutsui Exp $
 
 LIB=	sa
 NOPIC=	# defined
@@ -7,6 +7,7 @@ NOPROFILE=# defined
 SA_USE_CREAD?= no		# Read compressed kernels
 SA_INCLUDE_NET?= yes		# Netboot via TFTP, NFS
 SA_USE_LOADFILE?= no		# Generic executable loading support
+SA_ENABLE_LS_OP?= no		# Filesystems ls operation
 
 #DEBUGCPPFLAGS= -DBOOTP_DEBUG -DNETIF_DEBUG -DETHER_DEBUG -DNFS_DEBUG -DRPC_DEBUG -DRARP_DEBUG -DARP_DEBUG -DNET_DEBUG -DDEBUG -DPARANOID
 CPPFLAGS=	-I${SADIR} ${SACPPFLAGS} ${SAMISCCPPFLAGS} \
@@ -45,6 +46,9 @@ SRCS+=	close.c lseek.c open.c read.c wri
 CPPFLAGS+= -D__INTERNAL_LIBSA_CREAD
 SRCS+=	cread.c
 .endif
+.if (${SA_ENABLE_LS_OP} == "yes")
+SRCS+= ls.c
+.endif
 
 .if (${SA_USE_LOADFILE} == "yes")
 SRCS+=	loadfile.c loadfile_ecoff.c loadfile_elf32.c lookup_elf32.c \
@@ -65,7 +69,7 @@ SRCS+=	bootp.c rarp.c bootparam.c
 SRCS+=	nfs.c tftp.c
 .endif
 
-SRCS+=	ffsv1.c ffsv2.c ufs_ls.c
+SRCS+=	ffsv1.c ffsv2.c
 SRCS+=	lfsv1.c lfsv2.c
 SRCS+=	cd9660.c
 SRCS+=	ustarfs.c

Index: src/sys/lib/libsa/cd9660.c
diff -u src/sys/lib/libsa/cd9660.c:1.27 src/sys/lib/libsa/cd9660.c:1.28
--- src/sys/lib/libsa/cd9660.c:1.27	Thu Jun 16 13:27:58 2011
+++ src/sys/lib/libsa/cd9660.c	Sun Dec 25 06:09:08 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: cd9660.c,v 1.27 2011/06/16 13:27:58 joerg Exp $	*/
+/*	$NetBSD: cd9660.c,v 1.28 2011/12/25 06:09:08 tsutsui Exp $	*/
 
 /*
  * Copyright (C) 1996 Wolfgang Solfrank.
@@ -396,3 +396,12 @@ cd9660_stat(struct open_file *f, struct 
 	sb->st_size = fp->size;
 	return 0;
 }
+
+#if defined(LIBSA_ENABLE_LS_OP)
+__compactcall void
+cd9660_ls(struct open_file *f, const char *pattern)
+{
+	printf("Currently ls command is unsupported by cd9660\n");
+	return;
+}
+#endif

Index: src/sys/lib/libsa/dosfs.c
diff -u src/sys/lib/libsa/dosfs.c:1.17 src/sys/lib/libsa/dosfs.c:1.18
--- src/sys/lib/libsa/dosfs.c:1.17	Thu Jun 16 13:27:58 2011
+++ src/sys/lib/libsa/dosfs.c	Sun Dec 25 06:09:08 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: dosfs.c,v 1.17 2011/06/16 13:27:58 joerg Exp $	*/
+/*	$NetBSD: dosfs.c,v 1.18 2011/12/25 06:09:08 tsutsui Exp $	*/
 
 /*
  * Copyright (c) 1996, 1998 Robert Nordier
@@ -405,6 +405,15 @@ dosfs_stat(struct open_file *fd, struct 
 	return 0;
 }
 
+#if defined(LIBSA_ENABLE_LS_OP)
+__compactcall void
+dosfs_ls(struct open_file *f, const char *pattern)
+{
+	printf("Currently ls command is unsupported by dosfs\n");
+	return;
+}
+#endif
+
 /*
  * Parse DOS boot sector
  */

Index: src/sys/lib/libsa/ext2fs.c
diff -u src/sys/lib/libsa/ext2fs.c:1.10 src/sys/lib/libsa/ext2fs.c:1.11
--- src/sys/lib/libsa/ext2fs.c:1.10	Thu Jun 16 13:27:58 2011
+++ src/sys/lib/libsa/ext2fs.c	Sun Dec 25 06:09:08 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: ext2fs.c,v 1.10 2011/06/16 13:27:58 joerg Exp $	*/
+/*	$NetBSD: ext2fs.c,v 1.11 2011/12/25 06:09:08 tsutsui Exp $	*/
 
 /*
  * Copyright (c) 1997 Manuel Bouyer.
@@ -146,6 +146,59 @@ struct file {
 	daddr_t		f_buf_blkno;	/* block number of data block */
 };
 
+#if defined(LIBSA_ENABLE_LS_OP)
+
+#define NELEM(x) (sizeof (x) / sizeof(*x))
+
+typedef struct entry_t entry_t;
+struct entry_t {
+	entry_t	*e_next;
+	ino32_t	e_ino;
+	uint8_t	e_type;
+	char	e_name[1];
+};
+
+static const char    *const typestr[] = {
+	"unknown",
+	"REG",
+	"DIR",
+	"CHR",
+	"BLK",
+	"FIFO",
+	"SOCK",
+	"LNK"
+};
+
+static int
+fn_match(const char *fname, const char *pattern)
+{
+	char fc, pc;
+
+	do {
+		fc = *fname++;
+		pc = *pattern++;
+		if (!fc && !pc)
+			return 1;
+		if (pc == '?' && fc)
+			pc = fc;
+	} while (fc == pc);
+
+	if (pc != '*')
+		return 0;
+	/*
+	 * Too hard (and unnecessary really) too check for "*?name" etc....
+	 * "**" will look for a '*' and "*?" a '?'
+	 */
+	pc = *pattern++;
+	if (!pc)
+		return 1;
+	while ((fname = strchr(fname, pc)))
+		if (fn_match(++fname, pattern))
+			return 1;
+	return 0;
+}
+#endif /* LIBSA_ENABLE_LS_OP */
+
 static int read_inode(ino32_t, struct open_file *);
 static int block_map(struct open_file *, indp_t, indp_t *);
 static int buf_read_file(struct open_file *, char **, size_t *);
@@ -803,6 +856,97 @@ ext2fs_stat(struct open_file *f, struct 
 	return 0;
 }
 
+#if defined(LIBSA_ENABLE_LS_OP)
+__compactcall void
+ext2fs_ls(struct open_file *f, const char *pattern)
+{
+	struct file *fp = (struct file *)f->f_fsdata;
+	size_t block_size = fp->f_fs->e2fs_bsize;
+	char *buf;
+	size_t buf_size;
+	entry_t	*names = 0, *n, **np;
+
+	fp->f_seekp = 0;
+	while (fp->f_seekp < (off_t)fp->f_di.e2di_size) {
+		struct ext2fs_direct  *dp, *edp;
+		int rc = buf_read_file(f, &buf, &buf_size);
+		if (rc)
+			goto out;
+		if (buf_size != block_size || buf_size == 0)
+			goto out;
+
+		dp = (struct ext2fs_direct *)buf;
+		edp = (struct ext2fs_direct *)(buf + buf_size);
+
+		for (; dp < edp;
+		     dp = (void *)((char *)dp + fs2h16(dp->e2d_reclen))) {
+			const char *t;
+
+			if (fs2h16(dp->e2d_reclen) <= 0)
+				goto out;
+
+			if (fs2h32(dp->e2d_ino) == 0)
+				continue;
+
+			if (dp->e2d_type >= NELEM(typestr) ||
+			    !(t = typestr[dp->e2d_type])) {
+				/*
+				 * This does not handle "old"
+				 * filesystems properly. On little
+				 * endian machines, we get a bogus
+				 * type name if the namlen matches a
+				 * valid type identifier. We could
+				 * check if we read namlen "0" and
+				 * handle this case specially, if
+				 * there were a pressing need...
+				 */
+				printf("bad dir entry\n");
+				goto out;
+			}
+			if (pattern && !fn_match(dp->e2d_name, pattern))
+				continue;
+			n = alloc(sizeof *n + strlen(dp->e2d_name));
+			if (!n) {
+				printf("%d: %s (%s)\n",
+					fs2h32(dp->e2d_ino), dp->e2d_name, t);
+				continue;
+			}
+			n->e_ino = fs2h32(dp->e2d_ino);
+			n->e_type = dp->e2d_type;
+			strcpy(n->e_name, dp->e2d_name);
+			for (np = &names; *np; np = &(*np)->e_next) {
+				if (strcmp(n->e_name, (*np)->e_name) < 0)
+					break;
+			}
+			n->e_next = *np;
+			*np = n;
+		}
+		fp->f_seekp += buf_size;
+	}
+
+	if (names) {
+		entry_t *p_names = names;
+		do {
+			n = p_names;
+			printf("%d: %s (%s)\n",
+				n->e_ino, n->e_name, typestr[n->e_type]);
+			p_names = n->e_next;
+		} while (p_names);
+	} else {
+		printf("not found\n");
+	}
+out:
+	if (names) {
+		do {
+			n = names;
+			names = n->e_next;
+			dealloc(n, 0);
+		} while (names);
+	}
+	return;
+}
+#endif
+
 /*
  * byte swap functions for big endian machines
  * (ext2fs is always little endian)
Index: src/sys/lib/libsa/nullfs.c
diff -u src/sys/lib/libsa/nullfs.c:1.10 src/sys/lib/libsa/nullfs.c:1.11
--- src/sys/lib/libsa/nullfs.c:1.10	Thu Jun 16 13:27:58 2011
+++ src/sys/lib/libsa/nullfs.c	Sun Dec 25 06:09:08 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: nullfs.c,v 1.10 2011/06/16 13:27:58 joerg Exp $	*/
+/*	$NetBSD: nullfs.c,v 1.11 2011/12/25 06:09:08 tsutsui Exp $	*/
 
 /*-
  * Copyright (c) 1993
@@ -113,3 +113,12 @@ null_stat(struct open_file *f, struct st
 
 	return EIO;
 }
+
+#if defined(LIBSA_ENABLE_LS_OP)
+__compactcall void
+null_ls(struct open_file *f, const char *pattern)
+{
+	printf("Currently ls command is unsupported by nullfs\n");
+	return;
+}
+#endif

Index: src/sys/lib/libsa/ffsv1.c
diff -u src/sys/lib/libsa/ffsv1.c:1.4 src/sys/lib/libsa/ffsv1.c:1.5
--- src/sys/lib/libsa/ffsv1.c:1.4	Wed Nov 19 12:36:41 2008
+++ src/sys/lib/libsa/ffsv1.c	Sun Dec 25 06:09:08 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: ffsv1.c,v 1.4 2008/11/19 12:36:41 ad Exp $ */
+/* $NetBSD: ffsv1.c,v 1.5 2011/12/25 06:09:08 tsutsui Exp $ */
 
 #define LIBSA_FFSv1
 
@@ -8,6 +8,9 @@
 #define ufs_write	ffsv1_write
 #define ufs_seek	ffsv1_seek
 #define ufs_stat	ffsv1_stat
+#if defined(LIBSA_ENABLE_LS_OP)
+#define ufs_ls		ffsv1_ls
+#endif
 
 #define ufs_dinode	ufs1_dinode
 #define indp_t		int32_t
Index: src/sys/lib/libsa/ffsv2.c
diff -u src/sys/lib/libsa/ffsv2.c:1.4 src/sys/lib/libsa/ffsv2.c:1.5
--- src/sys/lib/libsa/ffsv2.c:1.4	Wed Nov 19 12:36:41 2008
+++ src/sys/lib/libsa/ffsv2.c	Sun Dec 25 06:09:08 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: ffsv2.c,v 1.4 2008/11/19 12:36:41 ad Exp $ */
+/* $NetBSD: ffsv2.c,v 1.5 2011/12/25 06:09:08 tsutsui Exp $ */
 
 #define LIBSA_FFSv2
 
@@ -8,6 +8,9 @@
 #define ufs_write	ffsv2_write
 #define ufs_seek	ffsv2_seek
 #define ufs_stat	ffsv2_stat
+#if defined(LIBSA_ENABLE_LS_OP)
+#define ufs_ls		ffsv2_ls
+#endif
 
 #define ufs_dinode	ufs2_dinode
 #define indp_t		int64_t

Index: src/sys/lib/libsa/lfsv1.c
diff -u src/sys/lib/libsa/lfsv1.c:1.3 src/sys/lib/libsa/lfsv1.c:1.4
--- src/sys/lib/libsa/lfsv1.c:1.3	Wed Nov 19 12:36:41 2008
+++ src/sys/lib/libsa/lfsv1.c	Sun Dec 25 06:09:08 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: lfsv1.c,v 1.3 2008/11/19 12:36:41 ad Exp $ */
+/* $NetBSD: lfsv1.c,v 1.4 2011/12/25 06:09:08 tsutsui Exp $ */
 
 #define	LIBSA_LFS
 #define	REQUIRED_LFS_VERSION	1
@@ -9,6 +9,9 @@
 #define	ufs_write		lfsv1_write
 #define	ufs_seek		lfsv1_seek
 #define	ufs_stat		lfsv1_stat
+#if defined(LIBSA_ENABLE_LS_OP)
+#define	ufs_ls			lfsv1_ls
+#endif
 
 #define	fs_bsize		lfs_ibsize
 #define	IFILE_Vx		IFILE_V1
Index: src/sys/lib/libsa/lfsv2.c
diff -u src/sys/lib/libsa/lfsv2.c:1.3 src/sys/lib/libsa/lfsv2.c:1.4
--- src/sys/lib/libsa/lfsv2.c:1.3	Wed Nov 19 12:36:41 2008
+++ src/sys/lib/libsa/lfsv2.c	Sun Dec 25 06:09:08 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: lfsv2.c,v 1.3 2008/11/19 12:36:41 ad Exp $ */
+/* $NetBSD: lfsv2.c,v 1.4 2011/12/25 06:09:08 tsutsui Exp $ */
 
 #define	LIBSA_LFS
 #define	REQUIRED_LFS_VERSION	2
@@ -9,6 +9,9 @@
 #define	ufs_write		lfsv2_write
 #define	ufs_seek		lfsv2_seek
 #define	ufs_stat		lfsv2_stat
+#if defined(LIBSA_ENABLE_LS_OP)
+#define	ufs_ls			lfsv2_ls
+#endif
 
 #define	fs_bsize		lfs_bsize
 #define	IFILE_Vx		IFILE

Index: src/sys/lib/libsa/nfs.c
diff -u src/sys/lib/libsa/nfs.c:1.46 src/sys/lib/libsa/nfs.c:1.47
--- src/sys/lib/libsa/nfs.c:1.46	Thu Jun 16 13:27:58 2011
+++ src/sys/lib/libsa/nfs.c	Sun Dec 25 06:09:08 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: nfs.c,v 1.46 2011/06/16 13:27:58 joerg Exp $	*/
+/*	$NetBSD: nfs.c,v 1.47 2011/12/25 06:09:08 tsutsui Exp $	*/
 
 /*-
  *  Copyright (c) 1993 John Brezak
@@ -655,3 +655,12 @@ nfs_stat(struct open_file *f, struct sta
 
 	return 0;
 }
+
+#if defined(LIBSA_ENABLE_LS_OP)
+__compactcall void
+nfs_ls(struct open_file *f, const char *pattern)
+{
+	printf("Currently ls command is unsupported by nfs\n");
+	return;
+}
+#endif

Index: src/sys/lib/libsa/stand.h
diff -u src/sys/lib/libsa/stand.h:1.73 src/sys/lib/libsa/stand.h:1.74
--- src/sys/lib/libsa/stand.h:1.73	Sun Jul 17 20:54:52 2011
+++ src/sys/lib/libsa/stand.h	Sun Dec 25 06:09:08 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: stand.h,v 1.73 2011/07/17 20:54:52 joerg Exp $	*/
+/*	$NetBSD: stand.h,v 1.74 2011/12/25 06:09:08 tsutsui Exp $	*/
 
 /*
  * Copyright (c) 1999 Christopher G. Demetriou.  All rights reserved.
@@ -87,7 +87,7 @@
 
 struct open_file;
 
-#define FS_DEF(fs) \
+#define FS_DEF_BASE(fs) \
 	extern __compactcall int	__CONCAT(fs,_open)(const char *, struct open_file *); \
 	extern __compactcall int	__CONCAT(fs,_close)(struct open_file *); \
 	extern __compactcall int	__CONCAT(fs,_read)(struct open_file *, void *, \
@@ -97,6 +97,15 @@ struct open_file;
 	extern __compactcall off_t	__CONCAT(fs,_seek)(struct open_file *, off_t, int); \
 	extern __compactcall int	__CONCAT(fs,_stat)(struct open_file *, struct stat *)
 
+#if defined(LIBSA_ENABLE_LS_OP)
+#define FS_DEF(fs) \
+	FS_DEF_BASE(fs);\
+	extern __compactcall void	__CONCAT(fs,_ls)(struct open_file *, const char *)
+#else
+#define FS_DEF(fs) FS_DEF_BASE(fs)
+#endif
+
+
 /*
  * This structure is used to define file system operations in a file system
  * independent way.
@@ -112,11 +121,24 @@ struct fs_ops {
 	__compactcall int	(*write)(struct open_file *, void *, size_t size, size_t *);
 	__compactcall off_t	(*seek)(struct open_file *, off_t, int);
 	__compactcall int	(*stat)(struct open_file *, struct stat *);
+#if defined(LIBSA_ENABLE_LS_OP)
+	__compactcall void	(*ls)(struct open_file *, const char *);
+#endif
 };
 
 extern struct fs_ops file_system[];
 extern int nfsys;
 
+#if defined(LIBSA_ENABLE_LS_OP)
+#define FS_OPS(fs) { \
+	__CONCAT(fs,_open), \
+	__CONCAT(fs,_close), \
+	__CONCAT(fs,_read), \
+	__CONCAT(fs,_write), \
+	__CONCAT(fs,_seek), \
+	__CONCAT(fs,_stat), \
+	__CONCAT(fs,_ls) }
+#else
 #define FS_OPS(fs) { \
 	__CONCAT(fs,_open), \
 	__CONCAT(fs,_close), \
@@ -124,6 +146,7 @@ extern int nfsys;
 	__CONCAT(fs,_write), \
 	__CONCAT(fs,_seek), \
 	__CONCAT(fs,_stat) }
+#endif
 
 #define	FS_OPEN(fs)		((fs)->open)
 #define	FS_CLOSE(fs)		((fs)->close)
@@ -131,6 +154,9 @@ extern int nfsys;
 #define	FS_WRITE(fs)		((fs)->write)
 #define	FS_SEEK(fs)		((fs)->seek)
 #define	FS_STAT(fs)		((fs)->stat)
+#if defined(LIBSA_ENABLE_LS_OP)
+#define	FS_LS(fs)		((fs)->ls)
+#endif
 
 #else
 
@@ -140,6 +166,9 @@ extern int nfsys;
 #define	FS_WRITE(fs)		___CONCAT(LIBSA_SINGLE_FILESYSTEM,_write)
 #define	FS_SEEK(fs)		___CONCAT(LIBSA_SINGLE_FILESYSTEM,_seek)
 #define	FS_STAT(fs)		___CONCAT(LIBSA_SINGLE_FILESYSTEM,_stat)
+#if defined(LIBSA_ENABLE_LS_OP)
+#define	FS_LS(fs)		___CONCAT(LIBSA_SINGLE_FILESYSTEM,_ls)
+#endif
 
 FS_DEF(LIBSA_SINGLE_FILESYSTEM);
 
@@ -256,6 +285,9 @@ off_t	lseek(int, off_t, int);
 int	ioctl(int, u_long, char *);
 int	stat(const char *, struct stat *);
 int	fstat(int, struct stat *);
+#if defined(LIBSA_ENABLE_LS_OP)
+void	ls(const char *);
+#endif
 
 typedef int cmp_t(const void *, const void *);
 void	qsort(void *, size_t, size_t, cmp_t *);

Index: src/sys/lib/libsa/tftp.c
diff -u src/sys/lib/libsa/tftp.c:1.33 src/sys/lib/libsa/tftp.c:1.34
--- src/sys/lib/libsa/tftp.c:1.33	Sat Jul 30 03:43:20 2011
+++ src/sys/lib/libsa/tftp.c	Sun Dec 25 06:09:08 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: tftp.c,v 1.33 2011/07/30 03:43:20 jakllsch Exp $	 */
+/*	$NetBSD: tftp.c,v 1.34 2011/12/25 06:09:08 tsutsui Exp $	 */
 
 /*
  * Copyright (c) 1996
@@ -429,6 +429,15 @@ tftp_stat(struct open_file *f, struct st
 	return 0;
 }
 
+#if defined(LIBSA_ENABLE_LS_OP)
+__compactcall void
+tftp_ls(struct open_file *f, const char *pattern)
+{
+	printf("Currently ls command is unsupported by tftp\n");
+	return;
+}
+#endif
+
 __compactcall off_t
 tftp_seek(struct open_file *f, off_t offset, int where)
 {
Index: src/sys/lib/libsa/ustarfs.c
diff -u src/sys/lib/libsa/ustarfs.c:1.33 src/sys/lib/libsa/ustarfs.c:1.34
--- src/sys/lib/libsa/ustarfs.c:1.33	Thu Jun 16 13:27:58 2011
+++ src/sys/lib/libsa/ustarfs.c	Sun Dec 25 06:09:08 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: ustarfs.c,v 1.33 2011/06/16 13:27:58 joerg Exp $	*/
+/*	$NetBSD: ustarfs.c,v 1.34 2011/12/25 06:09:08 tsutsui Exp $	*/
 
 /* [Notice revision 2.2]
  * Copyright (c) 1997, 1998 Avalon Computer Systems, Inc.
@@ -537,6 +537,16 @@ ustarfs_stat(struct open_file *f, struct
 	return 0;
 }
 
+
+#if defined(LIBSA_ENABLE_LS_OP)
+__compactcall void
+ustarfs_ls(struct open_file *f, const char *pattern)
+{
+	printf("Currently ls command is unsupported by ustarfs\n");
+	return;
+}
+#endif
+
 #ifndef LIBSA_NO_FS_CLOSE
 __compactcall int
 ustarfs_close(struct open_file *f)

Index: src/sys/lib/libsa/ufs.c
diff -u src/sys/lib/libsa/ufs.c:1.55 src/sys/lib/libsa/ufs.c:1.56
--- src/sys/lib/libsa/ufs.c:1.55	Thu Jun 16 13:27:58 2011
+++ src/sys/lib/libsa/ufs.c	Sun Dec 25 06:09:08 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: ufs.c,v 1.55 2011/06/16 13:27:58 joerg Exp $	*/
+/*	$NetBSD: ufs.c,v 1.56 2011/12/25 06:09:08 tsutsui Exp $	*/
 
 /*-
  * Copyright (c) 1993
@@ -179,6 +179,66 @@ static void ffs_oldfscompat(struct fs *)
 static int ffs_find_superblock(struct open_file *, struct fs *);
 #endif
 
+#if defined(LIBSA_ENABLE_LS_OP)
+
+#define NELEM(x) (sizeof (x) / sizeof(*x))
+
+typedef struct entry_t entry_t;
+struct entry_t {
+	entry_t	*e_next;
+	ino32_t	e_ino;
+	uint8_t	e_type;
+	char	e_name[1];
+};
+
+static const char    *const typestr[] = {
+	"unknown",
+	"FIFO",
+	"CHR",
+	0,
+	"DIR",
+	0,
+	"BLK",
+	0,
+	"REG",
+	0,
+	"LNK",
+	0,
+	"SOCK",
+	0,
+	"WHT"
+};
+
+static int
+fn_match(const char *fname, const char *pattern)
+{
+	char fc, pc;
+
+	do {
+		fc = *fname++;
+		pc = *pattern++;
+		if (!fc && !pc)
+			return 1;
+		if (pc == '?' && fc)
+			pc = fc;
+	} while (fc == pc);
+
+	if (pc != '*')
+		return 0;
+	/*
+	 * Too hard (and unnecessary really) too check for "*?name" etc....
+	 * "**" will look for a '*' and "*?" a '?'
+	 */
+	pc = *pattern++;
+	if (!pc)
+		return 1;
+	while ((fname = strchr(fname, pc)))
+		if (fn_match(++fname, pattern))
+			return 1;
+	return 0;
+}
+#endif /* LIBSA_ENABLE_LS_OP */
+
 #ifdef LIBSA_LFS
 /*
  * Find an inode's block.  Look it up in the ifile.  Whee!
@@ -852,6 +912,91 @@ ufs_stat(struct open_file *f, struct sta
 	return 0;
 }
 
+#if defined(LIBSA_ENABLE_LS_OP)
+__compactcall void
+ufs_ls(struct open_file *f, const char *pattern)
+{
+	struct file *fp = (struct file *)f->f_fsdata;
+	char *buf;
+	size_t buf_size;
+	entry_t	*names = 0, *n, **np;
+
+	fp->f_seekp = 0;
+	while (fp->f_seekp < (off_t)fp->f_di.di_size) {
+		struct direct  *dp, *edp;
+		int rc = buf_read_file(f, &buf, &buf_size);
+		if (rc)
+			goto out;
+		/* some firmware might use block size larger than DEV_BSIZE */
+		if (buf_size < DIRBLKSIZ)
+			goto out;
+
+		dp = (struct direct *)buf;
+		edp = (struct direct *)(buf + buf_size);
+
+		for (; dp < edp; dp = (void *)((char *)dp + dp->d_reclen)) {
+			const char *t;
+			if (dp->d_ino ==  0)
+				continue;
+
+			if (dp->d_type >= NELEM(typestr) ||
+			    !(t = typestr[dp->d_type])) {
+				/*
+				 * This does not handle "old"
+				 * filesystems properly. On little
+				 * endian machines, we get a bogus
+				 * type name if the namlen matches a
+				 * valid type identifier. We could
+				 * check if we read namlen "0" and
+				 * handle this case specially, if
+				 * there were a pressing need...
+				 */
+				printf("bad dir entry\n");
+				goto out;
+			}
+			if (pattern && !fn_match(dp->d_name, pattern))
+				continue;
+			n = alloc(sizeof *n + strlen(dp->d_name));
+			if (!n) {
+				printf("%d: %s (%s)\n",
+					dp->d_ino, dp->d_name, t);
+				continue;
+			}
+			n->e_ino = dp->d_ino;
+			n->e_type = dp->d_type;
+			strcpy(n->e_name, dp->d_name);
+			for (np = &names; *np; np = &(*np)->e_next) {
+				if (strcmp(n->e_name, (*np)->e_name) < 0)
+					break;
+			}
+			n->e_next = *np;
+			*np = n;
+		}
+		fp->f_seekp += buf_size;
+	}
+
+	if (names) {
+		entry_t *p_names = names;
+		do {
+			n = p_names;
+			printf("%d: %s (%s)\n",
+				n->e_ino, n->e_name, typestr[n->e_type]);
+			p_names = n->e_next;
+		} while (p_names);
+	} else {
+		printf("not found\n");
+	}
+out:
+	if (names) {
+		do {
+			n = names;
+			names = n->e_next;
+			dealloc(n, 0);
+		} while (names);
+	}
+}
+#endif /* LIBSA_ENABLE_LS_OP */
+
 #ifdef LIBSA_FFSv1
 /*
  * Sanity checks for old file systems.

Index: src/sys/lib/libsa/ufs.h
diff -u src/sys/lib/libsa/ufs.h:1.9 src/sys/lib/libsa/ufs.h:1.10
--- src/sys/lib/libsa/ufs.h:1.9	Sun Dec 11 12:24:46 2005
+++ src/sys/lib/libsa/ufs.h	Sun Dec 25 06:09:08 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: ufs.h,v 1.9 2005/12/11 12:24:46 christos Exp $	*/
+/*	$NetBSD: ufs.h,v 1.10 2011/12/25 06:09:08 tsutsui Exp $	*/
 
 /*-
  * Copyright (c) 1993
@@ -34,5 +34,3 @@
 FS_DEF(ufs);
 FS_DEF(ffsv1);
 FS_DEF(ffsv2);
-
-void ufs_ls(const char *);

Added files:

Index: src/sys/lib/libsa/ls.c
diff -u /dev/null src/sys/lib/libsa/ls.c:1.3
--- /dev/null	Sun Dec 25 06:09:10 2011
+++ src/sys/lib/libsa/ls.c	Sun Dec 25 06:09:08 2011
@@ -0,0 +1,161 @@
+/* $NetBSD: ls.c,v 1.3 2011/12/25 06:09:08 tsutsui Exp $ */
+
+/*-
+ * Copyright (c) 2011
+ *      The NetBSD Foundation, Inc. All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Martin Husemann.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  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 University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * Copyright (c) 1996
+ *	Matthias Drochner.  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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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 "stand.h"
+#include <sys/stat.h>
+#include <lib/libkern/libkern.h>
+
+void
+ls(const char *path)
+{
+	int             fd;
+	struct stat     sb;
+	size_t          size;
+	const char	*fname = 0;
+	char		*p;
+	struct open_file *f;
+
+	if ((fd = open(path, 0)) < 0
+	    || fstat(fd, &sb) < 0
+	    || (sb.st_mode & S_IFMT) != S_IFDIR) {
+		/* Path supplied isn't a directory, open parent
+		   directory and list matching files. */
+		if (fd >= 0)
+			close(fd);
+		fname = strrchr(path, '/');
+		if (fname) {
+			size = fname - path;
+			p = alloc(size + 1);
+			if (!p)
+				goto out;
+			memcpy(p, path, size);
+			p[size] = 0;
+			fd = open(p, 0);
+			dealloc(p, size + 1);
+		} else {
+			fd = open("", 0);
+			fname = path;
+		}
+
+		if (fd < 0) {
+			printf("ls: %s\n", strerror(errno));
+			return;
+		}
+		if (fstat(fd, &sb) < 0) {
+			printf("stat: %s\n", strerror(errno));
+			goto out;
+		}
+		if ((sb.st_mode & S_IFMT) != S_IFDIR) {
+			printf("%s: %s\n", path, strerror(ENOTDIR));
+			goto out;
+		}
+	}
+
+	f = &files[fd];
+
+#if !defined(LIBSA_NO_FD_CHECKING)
+	if ((unsigned int)fd >= SOPEN_MAX || f->f_flags == 0) {
+		errno = EBADF;
+		goto out;
+	}
+#endif
+
+#if !defined(LIBSA_NO_RAW_ACCESS)
+	/* operation not defined on raw devices */
+	if (f->f_flags & F_RAW) {
+		errno = EOPNOTSUPP;
+		goto out;
+	}
+#endif
+
+	if (FS_LS(f->f_ops) != NULL)
+		FS_LS(f->f_ops)(f, fname);
+	else
+		printf("no ls support for this file system\n");
+
+out:
+	close(fd);
+}

Reply via email to