This is an automated email from the ASF dual-hosted git repository.

yamamoto pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new b13f321  libc: Implement ftw and nftw function
b13f321 is described below

commit b13f3212ad3311880b0fb5b8503d91858ec99e2e
Author: Xiang Xiao <xiaoxi...@xiaomi.com>
AuthorDate: Tue Jul 28 16:05:02 2020 +0800

    libc: Implement ftw and nftw function
    
    see the reference here:
    https://pubs.opengroup.org/onlinepubs/009695399/basedefs/ftw.h.html
    
    Signed-off-by: Xiang Xiao <xiaoxi...@xiaomi.com>
    Change-Id: I3b368106a56b0e9d4c653f3ae16304b0a9d55fbc
---
 include/ftw.h                     |  15 ++-
 libs/libc/dirent/Make.defs        |   1 +
 libs/libc/dirent/lib_ftw.c        |  39 ++++++
 libs/libc/dirent/lib_nftw.c       | 241 ++++++++++++++++++++++++++++++++++++++
 libs/libc/libc.h                  |   4 +
 libs/libc/unistd/Make.defs        |   2 +-
 libs/libc/unistd/lib_restoredir.c |  59 ++++++++++
 7 files changed, 356 insertions(+), 5 deletions(-)

diff --git a/include/ftw.h b/include/ftw.h
index 34fe454..d8b110a 100644
--- a/include/ftw.h
+++ b/include/ftw.h
@@ -58,8 +58,10 @@
 #define FTW_MOUNT  2  /* The walk does not cross a mount point. */
 #define FTW_DEPTH  4  /* All subdirectories are visited before the directory
                        * itself. */
+#ifndef CONFIG_DISABLE_ENVIRON
 #define FTW_CHDIR  8  /* The walk changes to each directory before reading
                        * it.  */
+#endif
 
 /****************************************************************************
  * Public Types
@@ -67,7 +69,7 @@
 
 /* The fourth argument of the ftw/nftw callback is a pointer to an FTW
  * structure.  The value of base is the offset of the object's filename in
- * the pathname passed as the first argument to the callbaqck.  The value of
+ * the pathname passed as the first argument to the callback.  The value of
  * level indicates depth relative to the root of the walk, where the root
  * level is 0.
  */
@@ -78,10 +80,15 @@ struct FTW
   int level;   /* Depth relative to the root of the walk */
 };
 
-/* This is the type of the ftw/nftw callback */
+/* This is the type of the ftw callback */
 
 typedef int (*ftw_cb_t)(FAR const char *path, FAR const struct stat *buf,
-                        int info, FAR struct FTW *pftw);
+                        int info);
+
+/* This is the type of the nftw callback */
+
+typedef int (*nftw_cb_t)(FAR const char *path, FAR const struct stat *buf,
+                         int info, FAR struct FTW *pftw);
 
 /****************************************************************************
  * Public Function Prototypes
@@ -205,7 +212,7 @@ int ftw(FAR const char *path, ftw_cb_t fn, int fdlimit);
  *
  ****************************************************************************/
 
-int nftw(FAR const char *path, ftw_cb_t fn, int fdlimit, int flags);
+int nftw(FAR const char *path, nftw_cb_t fn, int fdlimit, int flags);
 
 #undef EXTERN
 #ifdef __cplusplus
diff --git a/libs/libc/dirent/Make.defs b/libs/libc/dirent/Make.defs
index 60d7926..3ce3553 100644
--- a/libs/libc/dirent/Make.defs
+++ b/libs/libc/dirent/Make.defs
@@ -36,6 +36,7 @@
 # Add the dirent C files to the build
 
 CSRCS += lib_readdirr.c lib_telldir.c lib_alphasort.c lib_scandir.c
+CSRCS += lib_ftw.c lib_nftw.c
 
 # Add the dirent directory to the build
 
diff --git a/libs/libc/dirent/lib_ftw.c b/libs/libc/dirent/lib_ftw.c
new file mode 100644
index 0000000..4356c83
--- /dev/null
+++ b/libs/libc/dirent/lib_ftw.c
@@ -0,0 +1,39 @@
+/****************************************************************************
+ * libs/libc/dirent/lib_ftw.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <ftw.h>
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int ftw(FAR const char *path, ftw_cb_t fn, int fdlimit)
+{
+  /* The following cast assumes that calling a function with one
+   * argument more than it needs behaves as expected. This is
+   * actually undefined, but works on all real-world machines.
+   */
+
+  return nftw(path, (nftw_cb_t)fn, fdlimit, FTW_PHYS);
+}
diff --git a/libs/libc/dirent/lib_nftw.c b/libs/libc/dirent/lib_nftw.c
new file mode 100644
index 0000000..34e5677
--- /dev/null
+++ b/libs/libc/dirent/lib_nftw.c
@@ -0,0 +1,241 @@
+/****************************************************************************
+ * libs/libc/dirent/lib_nftw.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <ftw.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+
+#include "libc.h"
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int
+call_nftw(FAR char *path, nftw_cb_t fn, int flags, int base,
+          int level, FAR const struct stat *buf, int info)
+{
+  struct FTW ftw =
+  {
+    base, level
+  };
+
+  int r;
+
+#ifndef CONFIG_DISABLE_ENVIRON
+  if (flags & FTW_CHDIR)
+    {
+      if (base > 1)
+        {
+          path[base - 1] = '\0';
+          r = chdir(path);
+          path[base - 1] = '/';
+        }
+      else
+        {
+          r = chdir("/");
+        }
+
+      if (r < 0)
+        {
+          return r;
+        }
+    }
+#endif
+
+  r = fn(path, buf, info, &ftw);
+
+#ifndef CONFIG_DISABLE_ENVIRON
+  if (flags & FTW_CHDIR)
+    {
+      lib_restoredir();
+    }
+#endif
+
+  return r;
+}
+
+static int
+do_nftw(FAR char *path, nftw_cb_t fn, int fdlimit, int flags, int level)
+{
+  FAR DIR *dir = NULL;
+  struct stat buf;
+  size_t base;
+  size_t j;
+  int info;
+  int r;
+
+  j = strlen(path);
+  while (j > 1 && path[j - 1] == '/')
+    {
+      path[--j] = '\0';
+    }
+
+  base = j - 1;
+  while (base > 0 && path[base - 1] != '/')
+    {
+      --base;
+    }
+
+  r = flags & FTW_PHYS ? lstat(path, &buf) : stat(path, &buf);
+  if (r < 0)
+    {
+      if (!(flags & FTW_PHYS) &&
+          get_errno() == ENOENT && !lstat(path, &buf))
+        {
+          info = FTW_SLN;
+        }
+      else if (get_errno() == EACCES)
+        {
+          info = FTW_NS;
+        }
+      else
+        {
+          return -1;
+        }
+    }
+  else if (S_ISDIR(buf.st_mode))
+    {
+      if (flags & FTW_DEPTH)
+        {
+          info = FTW_DP;
+        }
+      else
+        {
+          info = FTW_D;
+        }
+    }
+  else if (S_ISLNK(buf.st_mode))
+    {
+      if (flags & FTW_PHYS)
+        {
+          info = FTW_SL;
+        }
+      else
+        {
+          info = FTW_SLN;
+        }
+    }
+  else
+    {
+      info = FTW_F;
+    }
+
+  if (info == FTW_D || info == FTW_DP)
+    {
+      dir = opendir(path);
+      if (dir)
+        {
+          if (fdlimit <= 0)
+            {
+              closedir(dir);
+              dir = NULL;
+            }
+        }
+      else if (get_errno() == EACCES)
+        {
+          info = FTW_DNR;
+        }
+      else
+        {
+          return -1;
+        }
+    }
+
+  if (!(flags & FTW_DEPTH))
+    {
+      r = call_nftw(path, fn, flags, base, level, &buf, info);
+      if (r)
+        {
+          return r;
+        }
+    }
+
+  if (dir)
+    {
+      FAR struct dirent *de;
+      size_t l = j;
+
+      if (path[j - 1] != '/')
+        {
+          path[j++] = '/';
+        }
+
+      while ((de = readdir(dir)))
+        {
+          if (de->d_name[0] == '.' && (!de->d_name[1] ||
+              (de->d_name[1] == '.' && !de->d_name[2])))
+            {
+              continue;
+            }
+
+          if (strlen(de->d_name) > PATH_MAX - j)
+            {
+              set_errno(ENAMETOOLONG);
+              closedir(dir);
+              return -1;
+            }
+
+          strcpy(path + j, de->d_name);
+          r = do_nftw(path, fn, fdlimit - 1, flags, level + 1);
+          if (r)
+            {
+              closedir(dir);
+              return r;
+            }
+        }
+
+      path[l] = '\0';
+      closedir(dir);
+    }
+
+  if (flags & FTW_DEPTH)
+    {
+      r = call_nftw(path, fn, flags, base, level, &buf, info);
+      if (r)
+        {
+          return r;
+        }
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int nftw(FAR const char *path, nftw_cb_t fn, int fdlimit, int flags)
+{
+  char pathbuf[PATH_MAX + 1];
+
+  strncpy(pathbuf, path, PATH_MAX);
+  pathbuf[PATH_MAX] = '\0';
+
+  return do_nftw(pathbuf, fn, fdlimit, flags, 0);
+}
diff --git a/libs/libc/libc.h b/libs/libc/libc.h
index 49a9b07..d8fe9c6 100644
--- a/libs/libc/libc.h
+++ b/libs/libc/libc.h
@@ -217,6 +217,10 @@ ssize_t lib_parse_hostfile(FAR FILE *stream, FAR struct 
hostent *host,
                            FAR char *buf, size_t buflen);
 #endif
 
+#ifndef CONFIG_DISABLE_ENVIRON
+int lib_restoredir(void);
+#endif
+
 #undef EXTERN
 #if defined(__cplusplus)
 }
diff --git a/libs/libc/unistd/Make.defs b/libs/libc/unistd/Make.defs
index 60527c3..1b9f04f 100644
--- a/libs/libc/unistd/Make.defs
+++ b/libs/libc/unistd/Make.defs
@@ -47,7 +47,7 @@ CSRCS += lib_setuid.c lib_setgid.c lib_getuid.c lib_getgid.c
 endif
 
 ifneq ($(CONFIG_DISABLE_ENVIRON),y)
-CSRCS += lib_chdir.c lib_getcwd.c
+CSRCS += lib_chdir.c lib_getcwd.c lib_restoredir.c
 endif
 
 ifeq ($(CONFIG_LIBC_EXECFUNCS),y)
diff --git a/libs/libc/unistd/lib_restoredir.c 
b/libs/libc/unistd/lib_restoredir.c
new file mode 100644
index 0000000..13fa3b6
--- /dev/null
+++ b/libs/libc/unistd/lib_restoredir.c
@@ -0,0 +1,59 @@
+/****************************************************************************
+ * libs/libc/unistd/lib_restoredir.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "libc.h"
+
+#ifndef CONFIG_DISABLE_ENVIRON
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lib_restoredir
+ ****************************************************************************/
+
+int lib_restoredir(void)
+{
+  char *oldpwd;
+  int ret = OK;
+
+  oldpwd = getenv("OLDPWD");
+  if (oldpwd)
+    {
+      oldpwd = strdup(oldpwd);  /* kludge needed because environment is 
realloc'ed */
+      ret = setenv("PWD", oldpwd, TRUE);
+      lib_free(oldpwd);
+    }
+
+  return ret;
+}
+
+#endif /* !CONFIG_DISABLE_ENVIRON */

Reply via email to