commit - ace90326f82adffc32a25213124922899e849771
commit + 3dc1dc04a5ecf97ba3ce3f8c103c73bcfe00e31e
blob - c4e5c1824c875392b7ef1495c9256b3f8f5c84d6
blob + ddcebec4e3d857a20d7894579e2d4ee08bbf0fe9
--- got/got.c
+++ got/got.c
if (dirfd != -1) {
fd = openat(dirfd, de_name, O_RDONLY | O_NOFOLLOW);
if (fd == -1) {
- if (errno != ELOOP) {
+ if (!got_err_open_nofollow_on_symlink()) {
err = got_error_from_errno2("openat",
abspath);
goto done;
} else {
fd = open(abspath, O_RDONLY | O_NOFOLLOW);
if (fd == -1) {
- if (errno != ELOOP) {
+ if (!got_err_open_nofollow_on_symlink()) {
err = got_error_from_errno2("open",
abspath);
goto done;
blob - 4e87ec59462a265ba7b4c932db9772fbd93373c1
blob + 63f4fa74abf23dd8211a43333dd555ccf57acd6d
--- include/got_error.h
+++ include/got_error.h
* additional arguments.
*/
const struct got_error *got_error_fmt(int, const char *, ...);
+
+/*
+ * Check whether open(2) with O_NOFOLLOW failed on a symlink.
+ * This must be called directly after open(2) because it uses errno!
+ */
+int got_err_open_nofollow_on_symlink(void);
blob - 62a1719e317f17da42a7802c245017926889d142
blob + 7771a0b6aa35dd88d61d89d337613f8c62f6da75
--- lib/error.c
+++ lib/error.c
abort();
}
+
+int
+got_err_open_nofollow_on_symlink(void)
+{
+ /*
+ * Check whether open(2) with O_NOFOLLOW failed on a symlink.
+ * Posix mandates ELOOP and OpenBSD follows it. Others return
+ * different error codes. We carry this workaround to help the
+ * portable version a little.
+ */
+ return (errno == ELOOP
+#ifdef EMLINK
+ || errno == EMLINK
+#endif
+#ifdef EFTYPE
+ || errno == EFTYPE
+#endif
+ );
+}
blob - 2d3f2ac0339c7d159f40426028eb11947353a4f1
blob + 26749965b1904cf8d808d8157bf204b30403deae
--- lib/object_create.c
+++ lib/object_create.c
fd = open(ondisk_path, O_RDONLY | O_NOFOLLOW);
if (fd == -1) {
- if (errno != ELOOP)
+ if (!got_err_open_nofollow_on_symlink())
return got_error_from_errno2("open", ondisk_path);
if (lstat(ondisk_path, &sb) == -1) {
blob - acf42c1ab053024ca6b05a987842225c8dd06846
blob + a3e841f3fe4b794959a4b3b7a60de73abf4e6dd0
--- lib/worktree.c
+++ lib/worktree.c
*/
fd = open(ondisk_path, O_RDWR | O_EXCL | O_NOFOLLOW);
if (fd == -1) {
- if (errno != ELOOP)
+ if (!got_err_open_nofollow_on_symlink())
return got_error_from_errno2("open", ondisk_path);
/* We are updating an existing on-disk symlink. */
}
} else {
fd = open(abspath, O_RDONLY | O_NOFOLLOW);
- if (fd == -1 && errno != ENOENT && errno != ELOOP)
+ if (fd == -1 && errno != ENOENT &&
+ !got_err_open_nofollow_on_symlink())
return got_error_from_errno2("open", abspath);
- else if (fd == -1 && errno == ELOOP) {
+ else if (fd == -1 && got_err_open_nofollow_on_symlink()) {
if (lstat(abspath, sb) == -1)
return got_error_from_errno2("lstat", abspath);
} else if (fd == -1 || fstat(fd, sb) == -1) {
fd = open(ondisk_path, O_RDONLY | O_NOFOLLOW | O_DIRECTORY);
if (fd == -1) {
if (errno != ENOTDIR && errno != ENOENT && errno != EACCES &&
- errno != ELOOP)
+ !got_err_open_nofollow_on_symlink())
err = got_error_from_errno2("open", ondisk_path);
else {
if (!no_ignores) {
if (dirfd2 != -1) {
fd2 = openat(dirfd2, de_name2, O_RDONLY | O_NOFOLLOW);
if (fd2 == -1) {
- if (errno != ELOOP) {
+ if (!got_err_open_nofollow_on_symlink()) {
err = got_error_from_errno2("openat", path2);
goto done;
}
} else {
fd2 = open(path2, O_RDONLY | O_NOFOLLOW);
if (fd2 == -1) {
- if (errno != ELOOP) {
+ if (!got_err_open_nofollow_on_symlink()) {
err = got_error_from_errno2("open", path2);
goto done;
}