Added the 'rm' command to examples/loadables.

It accepts -r and -f.
Enable it with 'enable -f <path-to-bash>/examples/loadables/rm rm'.
Tested on wget configure script where it increases overall execution time by
6-7%.

Tim
From 5f1a18e570e63c9f010c48aca3a3484f56045fd5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tim Rühsen?= <tim.rueh...@gmx.de>
Date: Mon, 31 Oct 2016 12:44:20 +0100
Subject: [PATCH 2/2] Add rm [-rf] as examples/loadables/rm.c

---
 MANIFEST                       |   1 +
 examples/loadables/Makefile.in |   5 +-
 examples/loadables/README      |   1 +
 examples/loadables/rm.c        | 153 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 159 insertions(+), 1 deletion(-)
 create mode 100644 examples/loadables/rm.c

diff --git a/MANIFEST b/MANIFEST
index a306b6f..c352811 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -681,6 +681,7 @@ examples/loadables/dirname.c	f
 examples/loadables/tty.c	f
 examples/loadables/pathchk.c	f
 examples/loadables/tee.c	f
+examples/loadables/rm.c		f
 examples/loadables/rmdir.c	f
 examples/loadables/head.c	f
 examples/loadables/printenv.c	f
diff --git a/examples/loadables/Makefile.in b/examples/loadables/Makefile.in
index ec305cd..da0f595 100644
--- a/examples/loadables/Makefile.in
+++ b/examples/loadables/Makefile.in
@@ -103,7 +103,7 @@ INC = -I. -I.. -I$(topdir) -I$(topdir)/lib -I$(topdir)/builtins -I${srcdir} \
 ALLPROG = print truefalse sleep finfo logname basename dirname \
 	  tty pathchk tee head mkdir rmdir printenv id whoami \
 	  uname sync push ln unlink realpath strftime mypid setpgid
-OTHERPROG = necho hello cat pushd
+OTHERPROG = necho hello cat pushd rm

 all:	$(SHOBJ_STATUS)

@@ -142,6 +142,9 @@ finfo:	finfo.o
 cat:	cat.o
 	$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ cat.o $(SHOBJ_LIBS)

+rm:	rm.o
+	$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ rm.o $(SHOBJ_LIBS)
+
 logname:	logname.o
 	$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ logname.o $(SHOBJ_LIBS)

diff --git a/examples/loadables/README b/examples/loadables/README
index 2eae9cc..3d4e641 100644
--- a/examples/loadables/README
+++ b/examples/loadables/README
@@ -52,6 +52,7 @@ printenv.c	Minimal builtin clone of BSD printenv(1).
 push.c		Anyone remember TOPS-20?
 README		README
 realpath.c	Canonicalize pathnames, resolving symlinks.
+rm.c		Remove files, and directories with -r.
 rmdir.c		Remove directory.
 sleep.c		sleep for fractions of a second.
 strftime.c	Loadable builtin interface to strftime(3).
diff --git a/examples/loadables/rm.c b/examples/loadables/rm.c
new file mode 100644
index 0000000..b10e4d9
--- /dev/null
+++ b/examples/loadables/rm.c
@@ -0,0 +1,153 @@
+/* rm - remove files */
+
+/* See Makefile for compilation details. */
+
+/*
+   Copyright (C) 2016 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash.
+   Bash is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   Bash is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "config.h"
+
+#include <stdio.h>
+#include <errno.h>
+#include <dirent.h>
+#include "builtins.h"
+#include "shell.h"
+#include "common.h"
+
+#if !defined (errno)
+extern int errno;
+#endif
+
+static int
+_rm_file(const char *fname);
+
+static int force, recursive;
+
+static int
+_remove_directory(const char *dirname)
+{
+  DIR *dir;
+  struct dirent *dp;
+  size_t dirlen = strlen(dirname);
+  int err = 0;
+
+  if ((dir = opendir(dirname)))
+    {
+      while ((dp = readdir(dir)))
+        {
+          if (*dp->d_name == '.' && (dp->d_name[1] == 0 || (dp->d_name[1] == '.' && dp->d_name[2] == 0)))
+            continue;
+
+           char fname[dirlen + 1 + strlen(dp->d_name) + 1];
+           snprintf(fname, sizeof(fname), "%s/%s", dirname, dp->d_name);
+
+           if (_rm_file (fname) && !force)
+             err = 1;
+        }
+
+      closedir(dir);
+
+      if (!err && rmdir(dirname) && !force)
+        err = 1;
+    }
+  else if (!force)
+    err = 1;
+
+  if (err)
+    builtin_error ("%s: %s", dirname, strerror (errno));
+
+  return err;
+}
+
+static int
+_rm_file(const char *fname)
+{
+  if (unlink (fname) == 0)
+    return 0;
+
+  /* in case name is a directory glibc returns EISDIR but correct POSIX value would be EPERM */
+  if ((errno == EISDIR || errno == EPERM) && recursive)
+    return _remove_directory(fname);
+  else if (force)
+    return 0;
+
+  builtin_error ("%s: %s", fname, strerror (errno));
+  return 1;
+}
+
+int
+rm_builtin (list)
+     WORD_LIST *list;
+{
+  const char *name;
+  WORD_LIST *l;
+  int force_name, it;
+  int rval = EXECUTION_SUCCESS;
+
+  recursive = force = force_name = 0;
+
+  for (l = list; l; l = l->next)
+    {
+      name = l->word->word;
+
+		if (!force_name && (*name == '-' && name[1]))
+        {
+          if (name[1] == '-')
+            {
+              force_name = 1;
+              continue;
+            }
+          for (it = 1; name[it]; it++)
+            {
+              if (name[it] == 'r')
+                recursive = 1;
+              else if (name[it] == 'f')
+                force = 1;
+              else
+                {
+                  builtin_error ("%s: Unknown option", l->word->word);
+                  return EX_USAGE;
+                }
+            }
+          continue;
+        }
+
+      if (_rm_file(name) && !force)
+        rval = EXECUTION_FAILURE;
+	 }
+
+  return rval;
+}
+
+char *rm_doc[] = {
+	"Remove files.",
+	"",
+	"rm removes the files specified as arguments.",
+	(char *)NULL
+};
+
+/* The standard structure describing a builtin command.  bash keeps an array
+   of these structures. */
+struct builtin rm_struct = {
+	"rm",		/* builtin name */
+	rm_builtin,		/* function implementing the builtin */
+	BUILTIN_ENABLED,	/* initial flags for builtin */
+	rm_doc,		/* array of long documentation strings. */
+	"rm [-rf] file ...",	/* usage synopsis; becomes short_doc */
+	0			/* reserved for internal use */
+};
--
2.10.2

Attachment: signature.asc
Description: This is a digitally signed message part.

Reply via email to