From d4934a70e69365c97b1378820152e134a0089b5e Mon Sep 17 00:00:00 2001 From: Calin Juravle Date: Mon, 24 Feb 2014 16:13:50 +0000 Subject: [PATCH] Added ftw64, nftw64 Bug: 13076637 Change-Id: I5b926526f935b00bba14c2807b61d85f95089c33 --- libc/bionic/lfs64_support.cpp | 15 +++++++ libc/include/ftw.h | 3 ++ tests/Android.mk | 1 + tests/TemporaryFile.h | 46 ++++++++++++++----- tests/ftw_test.cpp | 85 +++++++++++++++++++++++++++++++++++ 5 files changed, 140 insertions(+), 10 deletions(-) create mode 100644 tests/ftw_test.cpp diff --git a/libc/bionic/lfs64_support.cpp b/libc/bionic/lfs64_support.cpp index 138094e14..ab795f5c5 100644 --- a/libc/bionic/lfs64_support.cpp +++ b/libc/bionic/lfs64_support.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include int mkstemp64(char* filename) { @@ -22,3 +23,17 @@ int mkstemp64(char* filename) { // open (our open is actually open64) and stat and stat64 are the same. return mkstemp(filename); } + +typedef int (*ftw_fn)(const char*, const struct stat*, int); +typedef int (*nftw_fn)(const char*, const struct stat*, int, struct FTW*); + +int ftw64(const char *dirpath, + int (*fn)(const char*, const struct stat64*, int), int nopenfd) { + return ftw(dirpath, reinterpret_cast(fn), nopenfd); +} + +int nftw64(const char * dirpath, + int (*fn)(const char*, const struct stat64*, int, struct FTW*), + int nopenfd, int flags) { + return nftw(dirpath, reinterpret_cast(fn), nopenfd, flags); +} diff --git a/libc/include/ftw.h b/libc/include/ftw.h index 3bebea3c3..af524d0af 100644 --- a/libc/include/ftw.h +++ b/libc/include/ftw.h @@ -57,6 +57,9 @@ __BEGIN_DECLS int ftw(const char *, int (*)(const char *, const struct stat *, int), int); int nftw(const char *, int (*)(const char *, const struct stat *, int, struct FTW *), int, int); +int ftw64(const char *, int (*)(const char *, const struct stat64 *, int), int); +int nftw64(const char *, int (*)(const char *, const struct stat64 *, int, + struct FTW *), int, int); __END_DECLS #endif /* !_FTW_H */ diff --git a/tests/Android.mk b/tests/Android.mk index 4879e523b..5fafba6b0 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -44,6 +44,7 @@ libBionicStandardTests_src_files := \ eventfd_test.cpp \ fcntl_test.cpp \ fenv_test.cpp \ + ftw_test.cpp \ getauxval_test.cpp \ getcwd_test.cpp \ inttypes_test.cpp \ diff --git a/tests/TemporaryFile.h b/tests/TemporaryFile.h index 2c6fb1c32..a7b13b09c 100644 --- a/tests/TemporaryFile.h +++ b/tests/TemporaryFile.h @@ -16,17 +16,21 @@ #include -template +template class GenericTemporaryFile { public: - GenericTemporaryFile() { - // Since we might be running on the host or the target, and if we're - // running on the host we might be running under bionic or glibc, - // let's just try both possible temporary directories and take the - // first one that works. - init("/data/local/tmp"); - if (fd == -1) { - init("/tmp"); + GenericTemporaryFile(const char* dirpath = NULL) { + if (dirpath != NULL) { + init(dirpath); + } else { + // Since we might be running on the host or the target, and if we're + // running on the host we might be running under bionic or glibc, + // let's just try both possible temporary directories and take the + // first one that works. + init("/data/local/tmp"); + if (fd == -1) { + init("/tmp"); + } } } @@ -41,8 +45,30 @@ class GenericTemporaryFile { private: void init(const char* tmp_dir) { snprintf(filename, sizeof(filename), "%s/TemporaryFile-XXXXXX", tmp_dir); - fd = mk_func(filename); + fd = mk_fn(filename); } }; typedef GenericTemporaryFile TemporaryFile; + +class TemporaryDir { + public: + TemporaryDir() { + if (!init("/data/local/tmp")) { + init("/tmp"); + } + } + + ~TemporaryDir() { + rmdir(dirname); + } + + char dirname[1024]; + + private: + bool init(const char* tmp_dir) { + snprintf(dirname, sizeof(dirname), "%s/TemporaryDir-XXXXXX", tmp_dir); + return (mkdtemp(dirname) != NULL); + } + +}; diff --git a/tests/ftw_test.cpp b/tests/ftw_test.cpp new file mode 100644 index 000000000..6d3a30897 --- /dev/null +++ b/tests/ftw_test.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed 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. + */ + +#include +#include "TemporaryFile.h" + +#include +#include +#include + +void sanity_check_ftw(const char* fpath, const struct stat* sb, int tflag) { + ASSERT_TRUE(fpath != NULL); + ASSERT_TRUE(sb != NULL); + bool is_dir = S_ISDIR(sb->st_mode); + ASSERT_TRUE((is_dir && tflag == FTW_D) || (!is_dir && tflag == FTW_F)); +} + +void sanity_check_nftw( + const char* fpath, const struct stat* sb, int tflag, struct FTW* ftwbuf) { + sanity_check_ftw(fpath, sb, tflag); + // either the parent dir or the file + bool is_dir = S_ISDIR(sb->st_mode); + ASSERT_TRUE( + (is_dir && ftwbuf->level == 0) || (!is_dir && ftwbuf->level == 1)); +} + +int check_ftw(const char* fpath, const struct stat* sb, int tflag) { + sanity_check_ftw(fpath, sb, tflag); + return 0; +} + +int check_ftw64(const char* fpath, const struct stat64* sb, int tflag) { + sanity_check_ftw(fpath, reinterpret_cast(sb), tflag); + return 0; +} + +int check_nftw( + const char* fpath, const struct stat* sb, int tflag, struct FTW* ftwbuf) { + sanity_check_nftw(fpath, sb, tflag, ftwbuf); + return 0; +} + +int check_nftw64( + const char* fpath, const struct stat64* sb, int tflag, struct FTW* ftwbuf) { + sanity_check_nftw(fpath, reinterpret_cast(sb), + tflag, ftwbuf); + return 0; +} + +TEST(ftw, ftw) { + TemporaryDir td; + TemporaryFile tf(td.dirname); + ftw(td.dirname, check_ftw, 1); +} + +TEST(ftw, ftw64) { + TemporaryDir td; + GenericTemporaryFile tf(td.dirname); + ftw64(td.dirname, check_ftw64, 1); +} + +TEST(ftw, nftw) { + TemporaryDir td; + TemporaryFile tf(td.dirname); + nftw(td.dirname, check_nftw, 1, 0); +} + +TEST(ftw, nftw64) { + TemporaryDir td; + GenericTemporaryFile tf(td.dirname); + nftw64(td.dirname, check_nftw64, 1, 0); +}