summaryrefslogtreecommitdiff
path: root/src/safe.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/safe.c')
-rw-r--r--src/safe.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/src/safe.c b/src/safe.c
index 3123a55..d2ff0d2 100644
--- a/src/safe.c
+++ b/src/safe.c
@@ -48,6 +48,10 @@
static const unsigned int MAX_PATH_COMPONENTS = 1024;
+/* Flag to turn the safe_* functions into their unsafe variants; files may then
+ lie outside the current working directory. */
+bool unsafe;
+
/* Path lookup results are cached in a hash table + LRU list. When the
cache is full, the oldest entries are removed. */
@@ -543,6 +547,9 @@ static int safe_xstat (const char *pathname, struct stat *buf, int flags)
{
int dirfd;
+ if (unsafe)
+ return fstatat (AT_FDCWD, pathname, buf, flags);
+
dirfd = traverse_path (&pathname);
if (dirfd < 0 && dirfd != AT_FDCWD)
return dirfd;
@@ -566,6 +573,9 @@ int safe_open (const char *pathname, int flags, mode_t mode)
{
int dirfd;
+ if (unsafe)
+ return open (pathname, flags, mode);
+
dirfd = traverse_path (&pathname);
if (dirfd < 0 && dirfd != AT_FDCWD)
return dirfd;
@@ -578,6 +588,9 @@ int safe_rename (const char *oldpath, const char *newpath)
int olddirfd, newdirfd;
int ret;
+ if (unsafe)
+ return rename (oldpath, newpath);
+
olddirfd = traverse_path (&oldpath);
if (olddirfd < 0 && olddirfd != AT_FDCWD)
return olddirfd;
@@ -600,6 +613,9 @@ int safe_mkdir (const char *pathname, mode_t mode)
{
int dirfd;
+ if (unsafe)
+ return mkdir (pathname, mode);
+
dirfd = traverse_path (&pathname);
if (dirfd < 0 && dirfd != AT_FDCWD)
return dirfd;
@@ -612,6 +628,9 @@ int safe_rmdir (const char *pathname)
int dirfd;
int ret;
+ if (unsafe)
+ return rmdir (pathname);
+
dirfd = traverse_path (&pathname);
if (dirfd < 0 && dirfd != AT_FDCWD)
return dirfd;
@@ -627,6 +646,9 @@ int safe_unlink (const char *pathname)
{
int dirfd;
+ if (unsafe)
+ return unlink (pathname);
+
dirfd = traverse_path (&pathname);
if (dirfd < 0 && dirfd != AT_FDCWD)
return dirfd;
@@ -638,6 +660,9 @@ int safe_symlink (const char *target, const char *linkpath)
{
int dirfd;
+ if (unsafe)
+ return symlink (target, linkpath);
+
dirfd = traverse_path (&linkpath);
if (dirfd < 0 && dirfd != AT_FDCWD)
return dirfd;
@@ -649,6 +674,9 @@ int safe_chmod (const char *pathname, mode_t mode)
{
int dirfd;
+ if (unsafe)
+ return chmod (pathname, mode);
+
dirfd = traverse_path (&pathname);
if (dirfd < 0 && dirfd != AT_FDCWD)
return dirfd;
@@ -660,6 +688,9 @@ int safe_lchown (const char *pathname, uid_t owner, gid_t group)
{
int dirfd;
+ if (unsafe)
+ return lchown (pathname, owner, group);
+
dirfd = traverse_path (&pathname);
if (dirfd < 0 && dirfd != AT_FDCWD)
return dirfd;
@@ -671,6 +702,9 @@ int safe_lutimens (const char *pathname, struct timespec const times[2])
{
int dirfd;
+ if (unsafe)
+ return utimensat (AT_FDCWD, pathname, times, AT_SYMLINK_NOFOLLOW);
+
dirfd = traverse_path (&pathname);
if (dirfd < 0 && dirfd != AT_FDCWD)
return dirfd;
@@ -682,6 +716,9 @@ ssize_t safe_readlink (const char *pathname, char *buf, size_t bufsiz)
{
int dirfd;
+ if (unsafe)
+ return readlink (pathname, buf, bufsiz);
+
dirfd = traverse_path (&pathname);
if (dirfd < 0 && dirfd != AT_FDCWD)
return dirfd;
@@ -693,6 +730,9 @@ int safe_access (const char *pathname, int mode)
{
int dirfd;
+ if (unsafe)
+ return access (pathname, mode);
+
dirfd = traverse_path (&pathname);
if (dirfd < 0 && dirfd != AT_FDCWD)
return dirfd;