summaryrefslogtreecommitdiffstats
path: root/lib.c
diff options
context:
space:
mode:
authorThomas Roessler <roessler@does-not-exist.org>1998-09-06 10:05:41 +0000
committerThomas Roessler <roessler@does-not-exist.org>1998-09-06 10:05:41 +0000
commit90b1730bf76a468f9a9ad10078650bb01c63d9cd (patch)
tree71aea34d571b450a6f52c74164879a9757401bdb /lib.c
parentdb280634a64dddee807065a6c8fc841dcfae5ff7 (diff)
[patch-0.94.5i.tlr.safe_symlink.1] Introduce
safe_symlink() for /tmp-safe symlinking in the nametemplate code.
Diffstat (limited to 'lib.c')
-rw-r--r--lib.c38
1 files changed, 36 insertions, 2 deletions
diff --git a/lib.c b/lib.c
index 45d901d3..3d889c00 100644
--- a/lib.c
+++ b/lib.c
@@ -656,6 +656,41 @@ void mutt_expand_fmt (char *dest, size_t destlen, const char *fmt, const char *s
FREE(&_src);
}
+static int
+compare_stat (struct stat *osb, struct stat *nsb)
+{
+ if (osb->st_dev != nsb->st_dev || osb->st_ino != nsb->st_ino ||
+ osb->st_rdev != nsb->st_rdev)
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+int safe_symlink(const char *oldpath, const char *newpath)
+{
+ struct stat osb, nsb;
+
+ if(!oldpath || !newpath)
+ return -1;
+
+ if(unlink(newpath) == -1 && errno != ENOENT)
+ return -1;
+
+ if(symlink(oldpath, newpath) == -1)
+ return -1;
+
+ if(stat(oldpath, &osb) == -1 || stat(newpath, &nsb) == -1
+ || compare_stat(&osb, &nsb) == -1)
+ {
+ unlink(newpath);
+ return -1;
+ }
+
+ return 0;
+}
+
int safe_open (const char *path, int flags)
{
struct stat osb, nsb;
@@ -666,8 +701,7 @@ int safe_open (const char *path, int flags)
/* make sure the file is not symlink */
if (lstat (path, &osb) < 0 || fstat (fd, &nsb) < 0 ||
- osb.st_dev != nsb.st_dev || osb.st_ino != nsb.st_ino ||
- osb.st_rdev != nsb.st_rdev)
+ compare_stat(&osb, &nsb) == -1)
{
dprint (1, (debugfile, "safe_open(): %s is a symlink!\n", path));
close (fd);