diff options
author | Bryan Drewery <bryan@shatow.net> | 2017-03-08 21:42:31 +0300 |
---|---|---|
committer | Bryan Drewery <bryan@shatow.net> | 2017-03-08 21:47:51 +0300 |
commit | f9b13a5a76e63fc2860ae17b875ca864615d650e (patch) | |
tree | ba19e960e4c7fcf4336f67d558399c0b714338d6 /external | |
parent | 1e799ff4e64643cb53b4bcaa67c245bfdf5138ad (diff) |
Add compat for utimensat(2) for touch builtin.
This is taken from FreeBSD head r301763 at tools/build/utimensat.c
Diffstat (limited to 'external')
-rw-r--r-- | external/sh_compat/compat.h | 15 | ||||
-rw-r--r-- | external/sh_compat/strchrnul.c (renamed from external/sh_compat/compat.c) | 0 | ||||
-rw-r--r-- | external/sh_compat/utimensat.c | 110 | ||||
-rw-r--r-- | external/update_sh.sh | 7 |
4 files changed, 128 insertions, 4 deletions
diff --git a/external/sh_compat/compat.h b/external/sh_compat/compat.h index 68723189..aecd90f7 100644 --- a/external/sh_compat/compat.h +++ b/external/sh_compat/compat.h @@ -3,7 +3,18 @@ #include "config.h" +#ifndef HAVE_UTIMENSAT +#include <sys/stat.h> +#endif /* !HAVE_UTIMENSAT */ + #ifndef HAVE_STRCHRNUL char *strchrnul(const char*, int); -#endif -#endif +#endif /* !HAVE_STRCHRNUL */ +#ifndef HAVE_UTIMENSAT +#ifndef UTIME_NOW +#define UTIME_NOW -1 +#define UTIME_OMIT -2 +#endif /* !UTIME_NOW */ +int utimensat(int, const char *, const struct timespec *, int); +#endif /* !HAVE_UTIMENSAT */ +#endif /* !_SH_COMPAT_COMPAT_H */ diff --git a/external/sh_compat/compat.c b/external/sh_compat/strchrnul.c index dde91685..dde91685 100644 --- a/external/sh_compat/compat.c +++ b/external/sh_compat/strchrnul.c diff --git a/external/sh_compat/utimensat.c b/external/sh_compat/utimensat.c new file mode 100644 index 00000000..10d1352e --- /dev/null +++ b/external/sh_compat/utimensat.c @@ -0,0 +1,110 @@ +/*- + * Copyright (c) 2015 Jilles Tjoelker + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/stat.h> + +#include <errno.h> +#include <fcntl.h> +#include <time.h> + +#ifndef UTIME_NOW +#define UTIME_NOW -1 +#define UTIME_OMIT -2 +#endif + +#ifndef HAVE_UTIMENSAT +int +utimensat(int fd, const char *path, const struct timespec times[2], int flag) +{ + struct timeval now, tv[2], *tvp; + struct stat sb; + int osreldate; + + if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) { + errno = EINVAL; + return (-1); + } + if (times == NULL || (times[0].tv_nsec == UTIME_NOW && + times[1].tv_nsec == UTIME_NOW)) + tvp = NULL; + else if (times[0].tv_nsec == UTIME_OMIT && + times[1].tv_nsec == UTIME_OMIT) + return (0); + else { + if ((times[0].tv_nsec < 0 || times[0].tv_nsec > 999999999) && + times[0].tv_nsec != UTIME_NOW && + times[0].tv_nsec != UTIME_OMIT) { + errno = EINVAL; + return (-1); + } + if ((times[1].tv_nsec < 0 || times[1].tv_nsec > 999999999) && + times[1].tv_nsec != UTIME_NOW && + times[1].tv_nsec != UTIME_OMIT) { + errno = EINVAL; + return (-1); + } + tv[0].tv_sec = times[0].tv_sec; + tv[0].tv_usec = times[0].tv_nsec / 1000; + tv[1].tv_sec = times[1].tv_sec; + tv[1].tv_usec = times[1].tv_nsec / 1000; + tvp = tv; + if (times[0].tv_nsec == UTIME_OMIT || + times[1].tv_nsec == UTIME_OMIT) { + if (fstatat(fd, path, &sb, flag) == -1) + return (-1); + if (times[0].tv_nsec == UTIME_OMIT) { + tv[0].tv_sec = sb.st_atim.tv_sec; + tv[0].tv_usec = sb.st_atim.tv_nsec / 1000; + } + if (times[1].tv_nsec == UTIME_OMIT) { + tv[1].tv_sec = sb.st_mtim.tv_sec; + tv[1].tv_usec = sb.st_mtim.tv_nsec / 1000; + } + } + if (times[0].tv_nsec == UTIME_NOW || + times[1].tv_nsec == UTIME_NOW) { + if (gettimeofday(&now, NULL) == -1) + return (-1); + if (times[0].tv_nsec == UTIME_NOW) + tv[0] = now; + if (times[1].tv_nsec == UTIME_NOW) + tv[1] = now; + } + } + if ((flag & AT_SYMLINK_NOFOLLOW) == 0) + return (futimesat(fd, path, tvp)); + else if ((flag & AT_SYMLINK_NOFOLLOW) != 0 && + (fd == AT_FDCWD || path[0] == '/')) + return (lutimes(path, tvp)); + else { + errno = ENOTSUP; + return (-1); + } +} +#endif diff --git a/external/update_sh.sh b/external/update_sh.sh index 9718d4d6..73b917fd 100644 --- a/external/update_sh.sh +++ b/external/update_sh.sh @@ -47,5 +47,8 @@ sed -i '' -e 's,[[:<:]]st_mtim[[:>:]],st_mtimespec,g' "${DESTDIR}/test.c" mv "${DESTDIR}/builtins.def" "${DESTDIR}/builtins.def.sh" git add -A "${DESTDIR}" -echo "sh_SOURCES= external/sh_compat/compat.c \\" -find "${DESTDIR}" -name '*.c'|sed -e 's,$, \\,'|sort +cat <<EOF +sh_SOURCES= external/sh_compat/strchrnul.c \\ + external/sh_compat/utimensat.c \\ +EOF +find "${DESTDIR}" -name '*.c'|sed -e 's,^, ,' -e 's,$, \\,'|sort |