summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/libarchive/Makefile2
-rw-r--r--lib/libarchive/archive_platform.h13
-rw-r--r--lib/libarchive/archive_read_extract.c289
-rw-r--r--lib/libarchive/configure.ac.in5
4 files changed, 204 insertions, 105 deletions
diff --git a/lib/libarchive/Makefile b/lib/libarchive/Makefile
index ecfea60..dbe9dad 100644
--- a/lib/libarchive/Makefile
+++ b/lib/libarchive/Makefile
@@ -7,7 +7,7 @@
LIB= archive
-VERSION= 1.02.019
+VERSION= 1.02.023
ARCHIVE_API_FEATURE= 2
ARCHIVE_API_VERSION= 1
SHLIB_MAJOR= ${ARCHIVE_API_VERSION}
diff --git a/lib/libarchive/archive_platform.h b/lib/libarchive/archive_platform.h
index 770d808..4140df2 100644
--- a/lib/libarchive/archive_platform.h
+++ b/lib/libarchive/archive_platform.h
@@ -46,6 +46,8 @@
#if __FreeBSD__ > 4
#define HAVE_ACL_CREATE_ENTRY 1
#define HAVE_ACL_INIT 1
+#define HAVE_ACL_SET_FD 1
+#define HAVE_ACL_SET_FD_NP 1
#define HAVE_ACL_SET_FILE 1
#endif
#define HAVE_BZLIB_H 1
@@ -55,7 +57,10 @@
#define HAVE_EILSEQ 1
#define HAVE_ERRNO_H 1
#define HAVE_FCHDIR 1
+#define HAVE_FCHMOD 1
+#define HAVE_FCHOWN 1
#define HAVE_FCNTL_H 1
+#define HAVE_FUTIMES 1
#define HAVE_INTTYPES_H 1
#define HAVE_LCHMOD 1
#define HAVE_LCHOWN 1
@@ -123,6 +128,14 @@
#define HAVE_POSIX_ACL 1
#endif
+/*
+ * If we can't restore metadata using a file descriptor, then
+ * for compatibility's sake, close files before trying to restore metadata.
+ */
+#if defined(HAVE_FCHMOD) || defined(HAVE_FUTIMES) || defined(HAVE_ACL_SET_FD) || defined(HAVE_ACL_SET_FD_NP) || defined(HAVE_FCHOWN)
+#define CAN_RESTORE_METADATA_FD
+#endif
+
/* Set up defaults for internal error codes. */
#ifndef ARCHIVE_ERRNO_FILE_FORMAT
#if HAVE_EFTYPE
diff --git a/lib/libarchive/archive_read_extract.c b/lib/libarchive/archive_read_extract.c
index 20fb1dd..4a8f1d2 100644
--- a/lib/libarchive/archive_read_extract.c
+++ b/lib/libarchive/archive_read_extract.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003-2004 Tim Kientzle
+ * Copyright (c) 2003-2005 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -94,9 +94,6 @@ struct extract {
* Cached stat data from disk for the current entry.
* If this is valid, pst points to st. Otherwise,
* pst is null.
- *
- * TODO: Have all of the stat calls use this cached data
- * if possible.
*/
struct stat st;
struct stat *pst;
@@ -130,19 +127,20 @@ static int create_dir_mutable(struct archive *, char *, int flags);
static int create_dir_recursive(struct archive *, char *, int flags);
static int create_parent_dir(struct archive *, const char *, int flags);
static int create_parent_dir_mutable(struct archive *, char *, int flags);
-static int restore_metadata(struct archive *, struct archive_entry *,
- int flags);
+static int restore_metadata(struct archive *, int fd,
+ struct archive_entry *, int flags);
#ifdef HAVE_POSIX_ACL
-static int set_acl(struct archive *, struct archive_entry *,
+static int set_acl(struct archive *, int fd, struct archive_entry *,
acl_type_t, int archive_entry_acl_type, const char *tn);
#endif
-static int set_acls(struct archive *, struct archive_entry *);
-static int set_fflags(struct archive *, const char *name, mode_t mode,
+static int set_acls(struct archive *, int fd, struct archive_entry *);
+static int set_fflags(struct archive *, int fd, const char *name, mode_t,
unsigned long fflags_set, unsigned long fflags_clear);
-static int set_ownership(struct archive *, struct archive_entry *, int);
-static int set_perm(struct archive *, struct archive_entry *, int mode,
+static int set_ownership(struct archive *, int fd, struct archive_entry *,
int flags);
-static int set_time(struct archive *, struct archive_entry *, int);
+static int set_perm(struct archive *, int fd, struct archive_entry *,
+ int mode, int flags);
+static int set_time(struct archive *, int fd, struct archive_entry *, int);
static struct fixup_entry *sort_dir_list(struct fixup_entry *p);
@@ -183,6 +181,8 @@ archive_read_extract(struct archive *a, struct archive_entry *entry, int flags)
restore_pwd = -1;
original_filename = NULL;
+ /* The following is not possible without fchdir. <sigh> */
+#ifdef HAVE_FCHDIR
/*
* If pathname is longer than PATH_MAX, record starting directory
* and chdir to a suitable intermediate dir.
@@ -190,13 +190,19 @@ archive_read_extract(struct archive *a, struct archive_entry *entry, int flags)
if (strlen(archive_entry_pathname(entry)) > PATH_MAX) {
char *intdir, *tail;
+ restore_pwd = open(".", O_RDONLY);
+ if (restore_pwd < 0) {
+ archive_set_error(a, errno,
+ "Unable to restore long pathname");
+ return (ARCHIVE_WARN);
+ }
+
/*
* Yes, the copy here is necessary because we edit
* the pathname in-place to create intermediate dirnames.
*/
original_filename = strdup(archive_entry_pathname(entry));
- restore_pwd = open(".", O_RDONLY);
/*
* "intdir" points to the initial dir section we're going
* to remove, "tail" points to the remainder of the path.
@@ -230,6 +236,7 @@ archive_read_extract(struct archive *a, struct archive_entry *entry, int flags)
}
archive_entry_set_pathname(entry, tail);
}
+#endif
if (stat(archive_entry_pathname(entry), &extract->st) == 0)
extract->pst = &extract->st;
@@ -269,6 +276,7 @@ archive_read_extract(struct archive *a, struct archive_entry *entry, int flags)
cleanup:
+#ifdef HAVE_FCHDIR
/* If we changed directory above, restore it here. */
if (restore_pwd >= 0 && original_filename != NULL) {
fchdir(restore_pwd);
@@ -276,6 +284,7 @@ cleanup:
archive_entry_copy_pathname(entry, original_filename);
free(original_filename);
}
+#endif
return (ret);
}
@@ -287,7 +296,7 @@ cleanup:
* dir, so we restore the dir 0700 first, then correct the
* mode at the end.
* * Similarly, the act of restoring a file touches the directory
- * and changes the timestamp on the dir, so we have to touch-up the
+ * and changes the timestamp on the dir, so we have to touch-up dir
* timestamps at the end as well.
* * Some file flags can interfere with the restore by, for example,
* preventing the creation of hardlinks to those files.
@@ -316,7 +325,7 @@ archive_extract_cleanup(struct archive *a)
p = sort_dir_list(extract->fixup_list);
while (p != NULL) {
- extract->pst = NULL; /* Mark stat buff as out-of-date. */
+ extract->pst = NULL; /* Mark stat cache as out-of-date. */
if (p->fixup & FIXUP_TIMES) {
struct timeval times[2];
times[1].tv_sec = p->mtime;
@@ -329,7 +338,7 @@ archive_extract_cleanup(struct archive *a)
chmod(p->name, p->mode);
if (p->fixup & FIXUP_FFLAGS)
- set_fflags(a, p->name, p->mode, p->fflags_set, 0);
+ set_fflags(a, -1, p->name, p->mode, p->fflags_set, 0);
next = p->next;
free(p->name);
@@ -482,9 +491,9 @@ extract_file(struct archive *a, struct archive_entry *entry, int flags)
return (ARCHIVE_WARN);
}
r = archive_read_data_into_fd(a, fd);
- close(fd);
extract->pst = NULL; /* Cached stat data no longer valid. */
- r2 = restore_metadata(a, entry, flags);
+ r2 = restore_metadata(a, fd, entry, flags);
+ close(fd);
return (err_combine(r, r2));
}
@@ -503,28 +512,40 @@ extract_dir(struct archive *a, struct archive_entry *entry, int flags)
archive_entry_pathname(entry));
path = extract->create_parent_dir.s;
+ if (*path == '\0') {
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Invalid empty pathname");
+ return (ARCHIVE_WARN);
+ }
+
/* Deal with any troublesome trailing path elements. */
+ /* TODO: Someday, generalize this to remove '//' or '/./' from
+ * the middle of paths. But, it should not compress '..' from
+ * the middle of paths. It's a feature that restoring
+ * "a/../b" creates both 'a' and 'b' directories. */
for (;;) {
- if (*path == '\0')
- return (ARCHIVE_OK);
- /* Locate last element; trim trailing '/'. */
+ /* Locate last element. */
p = strrchr(path, '/');
- if (p != NULL) {
- if (p[1] == '\0') {
- *p = '\0';
- continue;
- }
+ if (p != NULL)
p++;
- } else
+ else
p = path;
- /* Trim trailing '.'. */
- if (p[0] == '.' && p[1] == '\0') {
+ /* Trim trailing '/' unless that's the entire path. */
+ if (p[0] == '\0' && p - 1 > path) {
+ p[-1] = '\0';
+ continue;
+ }
+ /* Trim trailing '.' unless that's the entire path. */
+ if (p > path && p[0] == '.' && p[1] == '\0') {
p[0] = '\0';
continue;
}
/* Just exit on trailing '..'. */
- if (p[0] == '.' && p[1] == '.' && p[2] == '\0')
- return (ARCHIVE_OK);
+ if (p[0] == '.' && p[1] == '.' && p[2] == '\0') {
+ archive_set_error(a, ARCHIVE_ERRNO_MISC,
+ "Can't restore directory '..'");
+ return (ARCHIVE_WARN);
+ }
break;
}
@@ -570,7 +591,7 @@ success:
}
/* For now, set the mode to SECURE_DIR_MODE. */
archive_entry_set_mode(entry, SECURE_DIR_MODE);
- return (restore_metadata(a, entry, flags));
+ return (restore_metadata(a, -1, entry, flags));
}
@@ -762,7 +783,7 @@ extract_hard_link(struct archive *a, struct archive_entry *entry, int flags)
}
/* Set ownership, time, permission information. */
- r = restore_metadata(a, entry, flags);
+ r = restore_metadata(a, -1, entry, flags);
return (r);
}
@@ -798,7 +819,7 @@ extract_symlink(struct archive *a, struct archive_entry *entry, int flags)
return (ARCHIVE_WARN);
}
- r = restore_metadata(a, entry, flags);
+ r = restore_metadata(a, -1, entry, flags);
return (r);
}
@@ -830,7 +851,7 @@ extract_device(struct archive *a, struct archive_entry *entry,
return (ARCHIVE_WARN);
}
- r = restore_metadata(a, entry, flags);
+ r = restore_metadata(a, -1, entry, flags);
return (r);
}
@@ -879,24 +900,25 @@ extract_fifo(struct archive *a, struct archive_entry *entry, int flags)
return (ARCHIVE_WARN);
}
- r = restore_metadata(a, entry, flags);
+ r = restore_metadata(a, -1, entry, flags);
return (r);
}
static int
-restore_metadata(struct archive *a, struct archive_entry *entry, int flags)
+restore_metadata(struct archive *a, int fd, struct archive_entry *entry, int flags)
{
int r, r2;
- r = set_ownership(a, entry, flags);
- r2 = set_time(a, entry, flags);
+ r = set_ownership(a, fd, entry, flags);
+ r2 = set_time(a, fd, entry, flags);
r = err_combine(r, r2);
- r2 = set_perm(a, entry, archive_entry_mode(entry), flags);
+ r2 = set_perm(a, fd, entry, archive_entry_mode(entry), flags);
return (err_combine(r, r2));
}
static int
-set_ownership(struct archive *a, struct archive_entry *entry, int flags)
+set_ownership(struct archive *a, int fd,
+ struct archive_entry *entry, int flags)
{
uid_t uid;
gid_t gid;
@@ -914,6 +936,11 @@ set_ownership(struct archive *a, struct archive_entry *entry, int flags)
if (a->user_uid != 0 && a->user_uid != uid)
return (ARCHIVE_OK);
+#ifdef HAVE_FCHOWN
+ if (fd >= 0 && fchown(fd, uid, gid) == 0)
+ return (ARCHIVE_OK);
+#endif
+
#ifdef HAVE_LCHOWN
if (lchown(archive_entry_pathname(entry), uid, gid))
#else
@@ -930,7 +957,7 @@ set_ownership(struct archive *a, struct archive_entry *entry, int flags)
}
static int
-set_time(struct archive *a, struct archive_entry *entry, int flags)
+set_time(struct archive *a, int fd, struct archive_entry *entry, int flags)
{
const struct stat *st;
struct timeval times[2];
@@ -950,6 +977,11 @@ set_time(struct archive *a, struct archive_entry *entry, int flags)
times[0].tv_sec = st->st_atime;
times[0].tv_usec = ARCHIVE_STAT_ATIME_NANOS(st) / 1000;
+#ifdef HAVE_FUTIMES
+ if (fd >= 0 && futimes(fd, times) == 0)
+ return (ARCHIVE_OK);
+#endif
+
#ifdef HAVE_LUTIMES
if (lutimes(archive_entry_pathname(entry), times) != 0) {
#else
@@ -973,7 +1005,8 @@ set_time(struct archive *a, struct archive_entry *entry, int flags)
}
static int
-set_perm(struct archive *a, struct archive_entry *entry, int mode, int flags)
+set_perm(struct archive *a, int fd, struct archive_entry *entry,
+ int mode, int flags)
{
struct extract *extract;
struct fixup_entry *le;
@@ -990,11 +1023,20 @@ set_perm(struct archive *a, struct archive_entry *entry, int mode, int flags)
name = archive_entry_pathname(entry);
if (mode & (S_ISUID | S_ISGID)) {
- if (extract->pst == NULL && stat(name, &extract->st) != 0) {
- archive_set_error(a, errno, "Can't check ownership");
+ if (extract->pst != NULL) {
+ /* Already have stat() data available. */
+#ifdef HAVE_FSTAT
+ } else if (fd >= 0 && fstat(fd, &extract->st) == 0) {
+ extract->pst = &extract->st;
+#endif
+ } else if (stat(name, &extract->st) == 0) {
+ extract->pst = &extract->st;
+ } else {
+ archive_set_error(a, errno,
+ "Couldn't stat file");
return (ARCHIVE_WARN);
}
- extract->pst = &extract->st;
+
/*
* TODO: Use the uid/gid looked up in set_ownership
* above rather than the uid/gid stored in the entry.
@@ -1011,6 +1053,10 @@ set_perm(struct archive *a, struct archive_entry *entry, int mode, int flags)
* the way.
*/
if (!S_ISLNK(archive_entry_mode(entry))) {
+#ifdef HAVE_FCHMOD
+ if (fd >= 0 && fchmod(fd, mode) == 0)
+ return (ARCHIVE_OK);
+#endif
if (chmod(name, mode) != 0) {
archive_set_error(a, errno, "Can't set permissions");
return (ARCHIVE_WARN);
@@ -1030,7 +1076,7 @@ set_perm(struct archive *a, struct archive_entry *entry, int mode, int flags)
}
if (flags & ARCHIVE_EXTRACT_ACL) {
- r = set_acls(a, entry);
+ r = set_acls(a, fd, entry);
if (r != ARCHIVE_OK)
return (r);
}
@@ -1086,7 +1132,7 @@ set_perm(struct archive *a, struct archive_entry *entry, int mode, int flags)
if ((le->fixup & FIXUP_MODE) == 0)
le->mode = mode;
} else {
- r = set_fflags(a, archive_entry_pathname(entry),
+ r = set_fflags(a, fd, archive_entry_pathname(entry),
mode, set, clear);
if (r != ARCHIVE_OK)
return (r);
@@ -1095,24 +1141,18 @@ set_perm(struct archive *a, struct archive_entry *entry, int mode, int flags)
return (ARCHIVE_OK);
}
+
+#if defined(HAVE_CHFLAGS) && !defined(__linux)
static int
-set_fflags(struct archive *a, const char *name, mode_t mode,
+set_fflags(struct archive *a, int fd, const char *name, mode_t mode,
unsigned long set, unsigned long clear)
{
struct extract *extract;
- int ret;
-#ifdef linux
- int fd;
- int err;
- unsigned long newflags, oldflags;
-#endif
extract = a->extract;
- ret = ARCHIVE_OK;
if (set == 0 && clear == 0)
- return (ret);
+ return (ARCHIVE_OK);
-#ifdef HAVE_CHFLAGS
(void)mode; /* UNUSED */
/*
* XXX Is the stat here really necessary? Or can I just use
@@ -1120,65 +1160,99 @@ set_fflags(struct archive *a, const char *name, mode_t mode,
* about the correct approach if we're overwriting an existing
* file that already has flags on it. XXX
*/
- if (stat(name, &extract->st) == 0) {
- extract->st.st_flags &= ~clear;
- extract->st.st_flags |= set;
- if (chflags(name, extract->st.st_flags) != 0) {
- archive_set_error(a, errno,
- "Failed to set file flags");
- ret = ARCHIVE_WARN;
- }
+ if (extract->pst != NULL) {
+ /* Already have stat() data available. */
+ } else if (fd >= 0 && fstat(fd, &extract->st) == 0)
+ extract->pst = &extract->st;
+ else if (stat(name, &extract->st) == 0)
extract->pst = &extract->st;
+ else {
+ archive_set_error(a, errno,
+ "Couldn't stat file");
+ return (ARCHIVE_WARN);
}
-#else
-#ifdef linux
- /* Linux has flags too, but no chflags syscall */
+
+ extract->st.st_flags &= ~clear;
+ extract->st.st_flags |= set;
+ if (chflags(name, extract->st.st_flags) == 0)
+ return (ARCHIVE_OK);
+
+ archive_set_error(a, errno,
+ "Failed to set file flags");
+ return (ARCHIVE_WARN);
+}
+#endif /* HAVE_CHFLAGS */
+
+#ifdef __linux
+/* Linux has flags too, but uses ioctl() instead of chflags(). */
+static int
+set_fflags(struct archive *a, int fd, const char *name, mode_t mode,
+ unsigned long set, unsigned long clear)
+{
+ struct extract *extract;
+ int ret;
+ int myfd = fd;
+ int err;
+ unsigned long newflags, oldflags;
+
+ extract = a->extract;
+ ret = ARCHIVE_OK;
+ if (set == 0 && clear == 0)
+ return (ret);
+ /* Only regular files and dirs can have flags. */
+ if (!S_ISREG(mode) && !S_ISDIR(mode))
+ return (ret);
+
+ /* If we weren't given an fd, open it ourselves. */
+ if (myfd < 0)
+ myfd = open(name, O_RDONLY|O_NONBLOCK);
+ if (myfd < 0)
+ return (ret);
+
/*
* Linux has no define for the flags that are only settable
* by the root user...
*/
#define SF_MASK (EXT2_IMMUTABLE_FL|EXT2_APPEND_FL)
-
/*
* XXX As above, this would be way simpler if we didn't have
* to read the current flags from disk. XXX
*/
- if ((S_ISREG(mode) || S_ISDIR(mode)) &&
- ((fd = open(name, O_RDONLY|O_NONBLOCK)) >= 0)) {
- err = 1;
- if (fd >= 0 && (ioctl(fd, EXT2_IOC_GETFLAGS, &oldflags) >= 0)) {
- newflags = (oldflags & ~clear) | set;
- if (ioctl(fd, EXT2_IOC_SETFLAGS, &newflags) >= 0) {
- err = 0;
- } else if (errno == EPERM) {
- if (ioctl(fd, EXT2_IOC_GETFLAGS, &oldflags) >= 0) {
- newflags &= ~SF_MASK;
- oldflags &= SF_MASK;
- newflags |= oldflags;
- if (ioctl(fd, EXT2_IOC_SETFLAGS, &newflags) >= 0)
- err = 0;
- }
- }
- }
- close(fd);
- if (err) {
- archive_set_error(a, errno,
- "Failed to set file flags");
- ret = ARCHIVE_WARN;
- }
+ /* Try setting the flags as given. */
+ if (ioctl(myfd, EXT2_IOC_GETFLAGS, &oldflags) >= 0) {
+ newflags = (oldflags & ~clear) | set;
+ if (ioctl(myfd, EXT2_IOC_SETFLAGS, &newflags) >= 0)
+ goto cleanup;
+ if (errno != EPERM)
+ goto fail;
}
-#endif /* linux */
-#endif /* HAVE_CHFLAGS */
-
+ /* If we couldn't set all the flags, try again with a subset. */
+ if (ioctl(myfd, EXT2_IOC_GETFLAGS, &oldflags) >= 0) {
+ newflags &= ~SF_MASK;
+ oldflags &= SF_MASK;
+ newflags |= oldflags;
+ if (ioctl(myfd, EXT2_IOC_SETFLAGS, &newflags) >= 0)
+ goto cleanup;
+ }
+ /* We couldn't set the flags, so report the failure. */
+fail:
+ archive_set_error(a, errno,
+ "Failed to set file flags");
+ ret = ARCHIVE_WARN;
+cleanup:
+ if (fd < 0)
+ close(myfd);
return (ret);
}
+#endif /* __linux */
#ifndef HAVE_POSIX_ACL
/* Default empty function body to satisfy mainline code. */
static int
-set_acls(struct archive *a, struct archive_entry *entry)
+set_acls(struct archive *a, int fd, struct archive_entry *entry)
{
(void)a;
+ (void)fd;
(void)entry;
return (ARCHIVE_OK);
@@ -1190,23 +1264,23 @@ set_acls(struct archive *a, struct archive_entry *entry)
* XXX TODO: What about ACL types other than ACCESS and DEFAULT?
*/
static int
-set_acls(struct archive *a, struct archive_entry *entry)
+set_acls(struct archive *a, int fd, struct archive_entry *entry)
{
int ret;
- ret = set_acl(a, entry, ACL_TYPE_ACCESS,
+ ret = set_acl(a, fd, entry, ACL_TYPE_ACCESS,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
if (ret != ARCHIVE_OK)
return (ret);
- ret = set_acl(a, entry, ACL_TYPE_DEFAULT,
+ ret = set_acl(a, fd, entry, ACL_TYPE_DEFAULT,
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
return (ret);
}
static int
-set_acl(struct archive *a, struct archive_entry *entry, acl_type_t acl_type,
- int ae_requested_type, const char *typename)
+set_acl(struct archive *a, int fd, struct archive_entry *entry,
+ acl_type_t acl_type, int ae_requested_type, const char *typename)
{
acl_t acl;
acl_entry_t acl_entry;
@@ -1268,6 +1342,17 @@ set_acl(struct archive *a, struct archive_entry *entry, acl_type_t acl_type,
name = archive_entry_pathname(entry);
+ /* Try restoring the ACL through 'fd' if we can. */
+#if HAVE_ACL_SET_FD
+ if (fd >= 0 && acl_type == ACL_TYPE_ACCESS && acl_set_fd(fd, acl) == 0)
+ ret = ARCHIVE_OK;
+ else
+#endif
+#if HAVE_ACL_SET_FD_NP
+ if (fd >= 0 && acl_set_fd_np(fd, acl, acl_type) == 0)
+ ret = ARCHIVE_OK;
+ else
+#endif
if (acl_set_file(name, acl_type, acl) != 0) {
archive_set_error(a, errno, "Failed to set %s acl", typename);
ret = ARCHIVE_WARN;
diff --git a/lib/libarchive/configure.ac.in b/lib/libarchive/configure.ac.in
index 537b577..09d8ed3 100644
--- a/lib/libarchive/configure.ac.in
+++ b/lib/libarchive/configure.ac.in
@@ -72,8 +72,9 @@ AC_FUNC_MALLOC
AC_FUNC_MEMCMP
AC_FUNC_STAT
AC_FUNC_STRERROR_R
-AC_CHECK_FUNCS([acl_create_entry acl_init acl_set_file])
-AC_CHECK_FUNCS([chflags fchdir lchmod lchown lutimes memmove])
+AC_CHECK_FUNCS([acl_create_entry acl_init acl_set_fd acl_set_fd_np acl_set_file])
+AC_CHECK_FUNCS([chflags fchdir fchmod fchown futimes])
+AC_CHECK_FUNCS([lchmod lchown lutimes memmove])
AC_CHECK_FUNCS([memset mkdir mkfifo strchr strdup strerror strrchr])
# Additional requirements
OpenPOWER on IntegriCloud