summaryrefslogtreecommitdiffstats
path: root/libutil
diff options
context:
space:
mode:
authorMariusz Zaborski <oshogbo@FreeBSD.org>2017-08-04 14:24:24 +0000
committerMariusz Zaborski <oshogbo@FreeBSD.org>2017-08-04 14:24:24 +0000
commit6dc9032c654984992ef940fc975e99066897442d (patch)
tree798a59f4c95c26e12295746a4310a0e5be1d3378 /libutil
parentf9c75a7f5875ba6275cdaad7bd424f1b376e88ae (diff)
downloadpw-darwin-6dc9032c654984992ef940fc975e99066897442d.tar.gz
pw-darwin-6dc9032c654984992ef940fc975e99066897442d.tar.zst
pw-darwin-6dc9032c654984992ef940fc975e99066897442d.zip
Introduce the flopenat(3) function.
Reviewed by: des, emaste Differential Revision: https://reviews.freebsd.org/D11690
Diffstat (limited to 'libutil')
-rw-r--r--libutil/flopen.c36
-rw-r--r--libutil/libutil.h1
2 files changed, 29 insertions, 8 deletions
diff --git a/libutil/flopen.c b/libutil/flopen.c
index 8929729..bb5d996 100644
--- a/libutil/flopen.c
+++ b/libutil/flopen.c
@@ -45,8 +45,8 @@ __FBSDID("$FreeBSD$");
* code's apparent simplicity; there would be no need for this function if it
* was easy to get right.
*/
-int
-flopen(const char *path, int flags, ...)
+static int
+vflopenat(int dirfd, const char *path, int flags, va_list ap)
{
int fd, operation, serrno, trunc;
struct stat sb, fsb;
@@ -58,11 +58,7 @@ flopen(const char *path, int flags, ...)
mode = 0;
if (flags & O_CREAT) {
- va_list ap;
-
- va_start(ap, flags);
mode = (mode_t)va_arg(ap, int); /* mode_t promoted to int */
- va_end(ap);
}
operation = LOCK_EX;
@@ -73,7 +69,7 @@ flopen(const char *path, int flags, ...)
flags &= ~O_TRUNC;
for (;;) {
- if ((fd = open(path, flags, mode)) == -1)
+ if ((fd = openat(dirfd, path, flags, mode)) == -1)
/* non-existent or no access */
return (-1);
if (flock(fd, operation) == -1) {
@@ -83,7 +79,7 @@ flopen(const char *path, int flags, ...)
errno = serrno;
return (-1);
}
- if (stat(path, &sb) == -1) {
+ if (fstatat(dirfd, path, &sb, 0) == -1) {
/* disappeared from under our feet */
(void)close(fd);
continue;
@@ -123,3 +119,27 @@ flopen(const char *path, int flags, ...)
return (fd);
}
}
+
+int
+flopen(const char *path, int flags, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, flags);
+ ret = vflopenat(AT_FDCWD, path, flags, ap);
+ va_end(ap);
+ return (ret);
+}
+
+int
+flopenat(int dirfd, const char *path, int flags, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, flags);
+ ret = vflopenat(dirfd, path, flags, ap);
+ va_end(ap);
+ return (ret);
+}
diff --git a/libutil/libutil.h b/libutil/libutil.h
index b20ffa2..fa924db 100644
--- a/libutil/libutil.h
+++ b/libutil/libutil.h
@@ -93,6 +93,7 @@ int expand_number(const char *_buf, uint64_t *_num);
int extattr_namespace_to_string(int _attrnamespace, char **_string);
int extattr_string_to_namespace(const char *_string, int *_attrnamespace);
int flopen(const char *_path, int _flags, ...);
+int flopenat(int _dirfd, const char *_path, int _flags, ...);
int forkpty(int *_amaster, char *_name,
struct termios *_termp, struct winsize *_winp);
void hexdump(const void *_ptr, int _length, const char *_hdr, int _flags);