@@ -70,6 +70,57 @@ static int utimes_common(const struct path *path, struct timespec64 *times)
70
70
return error ;
71
71
}
72
72
73
+ static int do_utimes_path (int dfd , const char __user * filename ,
74
+ struct timespec64 * times , int flags )
75
+ {
76
+ struct path path ;
77
+ int lookup_flags = 0 , error ;
78
+
79
+ if (times &&
80
+ (!nsec_valid (times [0 ].tv_nsec ) || !nsec_valid (times [1 ].tv_nsec )))
81
+ return - EINVAL ;
82
+ if (flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH ))
83
+ return - EINVAL ;
84
+
85
+ if (!(flags & AT_SYMLINK_NOFOLLOW ))
86
+ lookup_flags |= LOOKUP_FOLLOW ;
87
+ if (flags & AT_EMPTY_PATH )
88
+ lookup_flags |= LOOKUP_EMPTY ;
89
+
90
+ retry :
91
+ error = user_path_at (dfd , filename , lookup_flags , & path );
92
+ if (error )
93
+ return error ;
94
+
95
+ error = utimes_common (& path , times );
96
+ path_put (& path );
97
+ if (retry_estale (error , lookup_flags )) {
98
+ lookup_flags |= LOOKUP_REVAL ;
99
+ goto retry ;
100
+ }
101
+
102
+ return error ;
103
+ }
104
+
105
+ static int do_utimes_fd (int fd , struct timespec64 * times , int flags )
106
+ {
107
+ struct fd f ;
108
+ int error ;
109
+
110
+ if (times &&
111
+ (!nsec_valid (times [0 ].tv_nsec ) || !nsec_valid (times [1 ].tv_nsec )))
112
+ return - EINVAL ;
113
+ if (flags )
114
+ return - EINVAL ;
115
+
116
+ f = fdget (fd );
117
+ if (!f .file )
118
+ return - EBADF ;
119
+ error = utimes_common (& f .file -> f_path , times );
120
+ fdput (f );
121
+ return error ;
122
+ }
123
+
73
124
/*
74
125
* do_utimes - change times on filename or file descriptor
75
126
* @dfd: open file descriptor, -1 or AT_FDCWD
@@ -88,52 +139,9 @@ static int utimes_common(const struct path *path, struct timespec64 *times)
88
139
long do_utimes (int dfd , const char __user * filename , struct timespec64 * times ,
89
140
int flags )
90
141
{
91
- int error = - EINVAL ;
92
-
93
- if (times && (!nsec_valid (times [0 ].tv_nsec ) ||
94
- !nsec_valid (times [1 ].tv_nsec ))) {
95
- goto out ;
96
- }
97
-
98
- if (flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH ))
99
- goto out ;
100
-
101
- if (filename == NULL && dfd != AT_FDCWD ) {
102
- struct fd f ;
103
-
104
- if (flags )
105
- goto out ;
106
-
107
- f = fdget (dfd );
108
- error = - EBADF ;
109
- if (!f .file )
110
- goto out ;
111
-
112
- error = utimes_common (& f .file -> f_path , times );
113
- fdput (f );
114
- } else {
115
- struct path path ;
116
- int lookup_flags = 0 ;
117
-
118
- if (!(flags & AT_SYMLINK_NOFOLLOW ))
119
- lookup_flags |= LOOKUP_FOLLOW ;
120
- if (flags & AT_EMPTY_PATH )
121
- lookup_flags |= LOOKUP_EMPTY ;
122
- retry :
123
- error = user_path_at (dfd , filename , lookup_flags , & path );
124
- if (error )
125
- goto out ;
126
-
127
- error = utimes_common (& path , times );
128
- path_put (& path );
129
- if (retry_estale (error , lookup_flags )) {
130
- lookup_flags |= LOOKUP_REVAL ;
131
- goto retry ;
132
- }
133
- }
134
-
135
- out :
136
- return error ;
142
+ if (filename == NULL && dfd != AT_FDCWD )
143
+ return do_utimes_fd (dfd , times , flags );
144
+ return do_utimes_path (dfd , filename , times , flags );
137
145
}
138
146
139
147
SYSCALL_DEFINE4 (utimensat , int , dfd , const char __user * , filename ,
0 commit comments