summaryrefslogtreecommitdiffstats
path: root/patches/unfs3-0.9.22/0005-attr-handle-symlinks-correctly.patch
blob: 31428deabecf92a5fbc5c0aeec7b33b0035fd6cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de>
Date: Thu, 27 Feb 2020 14:04:18 +0100
Subject: [PATCH] attr: handle symlinks correctly

Make sure to change the properties of the symlink and not the symlink
target. So use utimensat(), fchownat() and fchmodat() with
AT_SYMLINK_NOFOLLOW to set the relevant attributes.

This change breaks compilation on Windows.

Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de>
---
 attr.c | 57 ++++++++++++++++++++++++++++++---------------------------
 1 file changed, 30 insertions(+), 27 deletions(-)

diff --git a/attr.c b/attr.c
index 2653ed0a16bb..2a13441179a0 100644
--- a/attr.c
+++ b/attr.c
@@ -267,38 +267,41 @@ post_op_attr get_post_cached(struct svc_req * req)
 
 /*
  * setting of time, races with local filesystem
- *
- * there is no futimes() function in POSIX or Linux
  */
-static nfsstat3 set_time(const char *path, backend_statstruct buf, sattr3 new)
+static nfsstat3 set_time(const char *path, sattr3 new)
 {
-    time_t new_atime, new_mtime;
-    struct utimbuf utim;
-    int res;
-
     /* set atime and mtime */
     if (new.atime.set_it != DONT_CHANGE || new.mtime.set_it != DONT_CHANGE) {
 
+	/* atime in t[0], mtime in t[1] */
+	struct timespec t[2];
+	int res;
+
 	/* compute atime to set */
-	if (new.atime.set_it == SET_TO_SERVER_TIME)
-	    new_atime = time(NULL);
-	else if (new.atime.set_it == SET_TO_CLIENT_TIME)
-	    new_atime = new.atime.set_atime_u.atime.seconds;
-	else			       /* DONT_CHANGE */
-	    new_atime = buf.st_atime;
+	if (new.atime.set_it == SET_TO_SERVER_TIME) {
+	    t[0].tv_sec = UTIME_NOW;
+	    t[0].tv_nsec = UTIME_NOW;
+	} else if (new.atime.set_it == SET_TO_CLIENT_TIME) {
+	    t[0].tv_sec = new.atime.set_atime_u.atime.seconds;
+	    t[0].tv_nsec = new.atime.set_atime_u.atime.nseconds;
+	} else {
+	    t[0].tv_sec = UTIME_OMIT;
+	    t[0].tv_nsec = UTIME_OMIT;
+	}
 
 	/* compute mtime to set */
-	if (new.mtime.set_it == SET_TO_SERVER_TIME)
-	    new_mtime = time(NULL);
-	else if (new.mtime.set_it == SET_TO_CLIENT_TIME)
-	    new_mtime = new.mtime.set_mtime_u.mtime.seconds;
-	else			       /* DONT_CHANGE */
-	    new_mtime = buf.st_mtime;
-
-	utim.actime = new_atime;
-	utim.modtime = new_mtime;
+	if (new.mtime.set_it == SET_TO_SERVER_TIME) {
+	    t[1].tv_sec = UTIME_NOW;
+	    t[1].tv_nsec = UTIME_NOW;
+	} else if (new.mtime.set_it == SET_TO_CLIENT_TIME) {
+	    t[1].tv_sec = new.mtime.set_mtime_u.mtime.seconds;
+	    t[1].tv_nsec = new.mtime.set_mtime_u.mtime.nseconds;
+	} else {
+	    t[1].tv_sec = UTIME_OMIT;
+	    t[1].tv_nsec = UTIME_OMIT;
+	}
 
-	res = backend_utime(path, &utim);
+	res = utimensat(AT_FDCWD, path, t, AT_SYMLINK_NOFOLLOW);
 	if (res == -1)
 	    return setattr_err();
     }
@@ -346,19 +349,19 @@ static nfsstat3 set_attr_unsafe(const char *path, nfs_fh3 nfh, sattr3 new)
 	else
 	    new_gid = -1;
 
-	res = backend_lchown(path, new_uid, new_gid);
+	res = fchownat(AT_FDCWD, path, new_uid, new_gid, AT_SYMLINK_NOFOLLOW);
 	if (res == -1)
 	    return setattr_err();
     }
 
     /* set mode */
     if (new.mode.set_it == TRUE) {
-	res = backend_chmod(path, new.mode.set_mode3_u.mode);
+	res = fchmodat(AT_FDCWD, path, new.mode.set_mode3_u.mode, 0);
 	if (res == -1)
 	    return setattr_err();
     }
 
-    return set_time(path, buf, new);
+    return set_time(path, new);
 }
 
 /*
@@ -461,7 +464,7 @@ nfsstat3 set_attr(const char *path, nfs_fh3 nfh, sattr3 new)
     }
 
     /* finally, set times */
-    return set_time(path, buf, new);
+    return set_time(path, new);
 }
 
 /*