Sync with upstream OpenBSD fts.c.
authorElliott Hughes <enh@google.com>
Sat, 22 Nov 2014 03:25:27 +0000 (19:25 -0800)
committerElliott Hughes <enh@google.com>
Sat, 22 Nov 2014 03:27:28 +0000 (19:27 -0800)
Change-Id: Ia7e26b603f6461095b5a8d7e8a6cdf4f8279fa84

libc/Android.mk
libc/bionic/fts.c
libc/upstream-openbsd/android/include/openbsd-compat.h
libc/upstream-openbsd/lib/libc/stdlib/reallocarray.c [new file with mode: 0644]

index 3e37ca7ec3464b47d5ca3919e5c2fbe1e4a5c854..ef1fb9be6e65dc49d244b5bfccc4059b732d9817 100644 (file)
@@ -479,6 +479,7 @@ libc_upstream_openbsd_src_files := \
     upstream-openbsd/lib/libc/stdlib/getenv.c \
     upstream-openbsd/lib/libc/stdlib/insque.c \
     upstream-openbsd/lib/libc/stdlib/lsearch.c \
+    upstream-openbsd/lib/libc/stdlib/reallocarray.c \
     upstream-openbsd/lib/libc/stdlib/remque.c \
     upstream-openbsd/lib/libc/stdlib/setenv.c \
     upstream-openbsd/lib/libc/stdlib/strtoimax.c \
index c491b6a0bd97cfd75c4fe3fa03c5c20eaf3d6403..31a4b2ff504a7653ac3120a30d36fd36f82bb9ce 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: fts.c,v 1.46 2014/05/25 17:47:04 tedu Exp $   */
+/*     $OpenBSD: fts.c,v 1.48 2014/11/20 04:14:15 guenther Exp $       */
 
 /*-
  * Copyright (c) 1990, 1993, 1994
@@ -49,11 +49,12 @@ static size_t        fts_maxarglen(char * const *);
 static void     fts_padjust(FTS *, FTSENT *);
 static int      fts_palloc(FTS *, size_t);
 static FTSENT  *fts_sort(FTS *, FTSENT *, int);
-static u_short  fts_stat(FTS *, FTSENT *, int);
+static u_short  fts_stat(FTS *, FTSENT *, int, int);
 static int      fts_safe_changedir(FTS *, FTSENT *, int, char *);
 
 #define ALIGNBYTES (sizeof(uintptr_t) - 1)
 #define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) &~ ALIGNBYTES)
+void* reallocarray(void*, size_t, size_t);
 
 #define        ISDOT(a)        (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
 
@@ -119,7 +120,7 @@ fts_open(char * const *argv, int options,
                p->fts_level = FTS_ROOTLEVEL;
                p->fts_parent = parent;
                p->fts_accpath = p->fts_name;
-               p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW));
+               p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW), -1);
 
                /* Command-line "." and ".." are real directories. */
                if (p->fts_info == FTS_DOT)
@@ -273,7 +274,7 @@ fts_read(FTS *sp)
 
        /* Any type of file may be re-visited; re-stat and re-turn. */
        if (instr == FTS_AGAIN) {
-               p->fts_info = fts_stat(sp, p, 0);
+               p->fts_info = fts_stat(sp, p, 0, -1);
                return (p);
        }
 
@@ -285,7 +286,7 @@ fts_read(FTS *sp)
         */
        if (instr == FTS_FOLLOW &&
            (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
-               p->fts_info = fts_stat(sp, p, 1);
+               p->fts_info = fts_stat(sp, p, 1, -1);
                if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
                        if ((p->fts_symfd = open(".", O_RDONLY, 0)) < 0) {
                                p->fts_errno = errno;
@@ -374,7 +375,7 @@ next:       tmp = p;
                if (p->fts_instr == FTS_SKIP)
                        goto next;
                if (p->fts_instr == FTS_FOLLOW) {
-                       p->fts_info = fts_stat(sp, p, 1);
+                       p->fts_info = fts_stat(sp, p, 1, -1);
                        if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
                                if ((p->fts_symfd =
                                    open(".", O_RDONLY, 0)) < 0) {
@@ -719,10 +720,11 @@ mem1:                             saved_errno = errno;
                        if (ISSET(FTS_NOCHDIR)) {
                                p->fts_accpath = p->fts_path;
                                memmove(cp, p->fts_name, p->fts_namelen + 1);
-                       } else
+                               p->fts_info = fts_stat(sp, p, 0, dirfd(dirp));
+                       } else {
                                p->fts_accpath = p->fts_name;
-                       /* Stat it. */
-                       p->fts_info = fts_stat(sp, p, 0);
+                               p->fts_info = fts_stat(sp, p, 0, -1);
+                       }
 
                        /* Decrement link count if applicable. */
                        if (nlinks > 0 && (p->fts_info == FTS_D ||
@@ -789,13 +791,20 @@ mem1:                             saved_errno = errno;
 }
 
 static u_short
-fts_stat(FTS *sp, FTSENT *p, int follow)
+fts_stat(FTS *sp, FTSENT *p, int follow, int dfd)
 {
        FTSENT *t;
        dev_t dev;
        ino_t ino;
        struct stat *sbp, sb;
        int saved_errno;
+       const char *path;
+
+       if (dfd == -1) {
+               path = p->fts_accpath;
+               dfd = AT_FDCWD;
+       } else
+               path = p->fts_name;
 
        /* If user needs stat info, stat buffer already allocated. */
        sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
@@ -806,16 +815,16 @@ fts_stat(FTS *sp, FTSENT *p, int follow)
         * fail, set the errno from the stat call.
         */
        if (ISSET(FTS_LOGICAL) || follow) {
-               if (stat(p->fts_accpath, sbp)) {
+               if (fstatat(dfd, path, sbp, 0)) {
                        saved_errno = errno;
-                       if (!lstat(p->fts_accpath, sbp)) {
+                       if (!fstatat(dfd, path, sbp, AT_SYMLINK_NOFOLLOW)) {
                                errno = 0;
                                return (FTS_SLNONE);
                        }
                        p->fts_errno = saved_errno;
                        goto err;
                }
-       } else if (lstat(p->fts_accpath, sbp)) {
+       } else if (fstatat(dfd, path, sbp, AT_SYMLINK_NOFOLLOW)) {
                p->fts_errno = errno;
 err:           memset(sbp, 0, sizeof(struct stat));
                return (FTS_NS);
@@ -873,8 +882,8 @@ fts_sort(FTS *sp, FTSENT *head, int nitems)
                struct _ftsent **a;
 
                sp->fts_nitems = nitems + 40;
-               if ((a = realloc(sp->fts_array,
-                   sp->fts_nitems * sizeof(FTSENT *))) == NULL) {
+               if ((a = reallocarray(sp->fts_array,
+                   sp->fts_nitems, sizeof(FTSENT *))) == NULL) {
                        if (sp->fts_array)
                                free(sp->fts_array);
                        sp->fts_array = NULL;
index 268b3b63a452d589054da7fe42cc58e90b63dc31..8386ba5fcb8401f162991fee669e9cab7e179f72 100644 (file)
@@ -59,6 +59,9 @@
 /* We have OpenBSD's getentropy_linux.c, but we don't mention getentropy in any header. */
 __LIBC_HIDDEN__ extern int getentropy(void*, size_t);
 
+/* OpenBSD has this as API, but we just use it internally. */
+__LIBC_HIDDEN__ void* reallocarray(void*, size_t, size_t);
+
 /* LP32 NDK ctype.h contained references to these. */
 __LIBC64_HIDDEN__ extern const short* _tolower_tab_;
 __LIBC64_HIDDEN__ extern const short* _toupper_tab_;
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/reallocarray.c b/libc/upstream-openbsd/lib/libc/stdlib/reallocarray.c
new file mode 100644 (file)
index 0000000..7accd99
--- /dev/null
@@ -0,0 +1,38 @@
+/*     $OpenBSD: reallocarray.c,v 1.1 2014/05/08 21:43:49 deraadt Exp $        */
+/*
+ * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+/*
+ * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
+ * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
+ */
+#define MUL_NO_OVERFLOW        (1UL << (sizeof(size_t) * 4))
+
+void *
+reallocarray(void *optr, size_t nmemb, size_t size)
+{
+       if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+           nmemb > 0 && SIZE_MAX / nmemb < size) {
+               errno = ENOMEM;
+               return NULL;
+       }
+       return realloc(optr, size * nmemb);
+}