diff options
Diffstat (limited to 'fs/hostfs/hostfs_user.c')
-rw-r--r-- | fs/hostfs/hostfs_user.c | 362 |
1 files changed, 362 insertions, 0 deletions
diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c new file mode 100644 index 000000000000..4796e8490f7d --- /dev/null +++ b/fs/hostfs/hostfs_user.c | |||
@@ -0,0 +1,362 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <unistd.h> | ||
7 | #include <stdio.h> | ||
8 | #include <fcntl.h> | ||
9 | #include <dirent.h> | ||
10 | #include <errno.h> | ||
11 | #include <utime.h> | ||
12 | #include <string.h> | ||
13 | #include <sys/stat.h> | ||
14 | #include <sys/time.h> | ||
15 | #include <sys/vfs.h> | ||
16 | #include "hostfs.h" | ||
17 | #include "kern_util.h" | ||
18 | #include "user.h" | ||
19 | |||
20 | int stat_file(const char *path, unsigned long long *inode_out, int *mode_out, | ||
21 | int *nlink_out, int *uid_out, int *gid_out, | ||
22 | unsigned long long *size_out, struct timespec *atime_out, | ||
23 | struct timespec *mtime_out, struct timespec *ctime_out, | ||
24 | int *blksize_out, unsigned long long *blocks_out) | ||
25 | { | ||
26 | struct stat64 buf; | ||
27 | |||
28 | if(lstat64(path, &buf) < 0) | ||
29 | return(-errno); | ||
30 | |||
31 | if(inode_out != NULL) *inode_out = buf.st_ino; | ||
32 | if(mode_out != NULL) *mode_out = buf.st_mode; | ||
33 | if(nlink_out != NULL) *nlink_out = buf.st_nlink; | ||
34 | if(uid_out != NULL) *uid_out = buf.st_uid; | ||
35 | if(gid_out != NULL) *gid_out = buf.st_gid; | ||
36 | if(size_out != NULL) *size_out = buf.st_size; | ||
37 | if(atime_out != NULL) { | ||
38 | atime_out->tv_sec = buf.st_atime; | ||
39 | atime_out->tv_nsec = 0; | ||
40 | } | ||
41 | if(mtime_out != NULL) { | ||
42 | mtime_out->tv_sec = buf.st_mtime; | ||
43 | mtime_out->tv_nsec = 0; | ||
44 | } | ||
45 | if(ctime_out != NULL) { | ||
46 | ctime_out->tv_sec = buf.st_ctime; | ||
47 | ctime_out->tv_nsec = 0; | ||
48 | } | ||
49 | if(blksize_out != NULL) *blksize_out = buf.st_blksize; | ||
50 | if(blocks_out != NULL) *blocks_out = buf.st_blocks; | ||
51 | return(0); | ||
52 | } | ||
53 | |||
54 | int file_type(const char *path, int *maj, int *min) | ||
55 | { | ||
56 | struct stat64 buf; | ||
57 | |||
58 | if(lstat64(path, &buf) < 0) | ||
59 | return(-errno); | ||
60 | /*We cannot pass rdev as is because glibc and the kernel disagree | ||
61 | *about its definition.*/ | ||
62 | if(maj != NULL) | ||
63 | *maj = major(buf.st_rdev); | ||
64 | if(min != NULL) | ||
65 | *min = minor(buf.st_rdev); | ||
66 | |||
67 | if(S_ISDIR(buf.st_mode)) return(OS_TYPE_DIR); | ||
68 | else if(S_ISLNK(buf.st_mode)) return(OS_TYPE_SYMLINK); | ||
69 | else if(S_ISCHR(buf.st_mode)) return(OS_TYPE_CHARDEV); | ||
70 | else if(S_ISBLK(buf.st_mode)) return(OS_TYPE_BLOCKDEV); | ||
71 | else if(S_ISFIFO(buf.st_mode))return(OS_TYPE_FIFO); | ||
72 | else if(S_ISSOCK(buf.st_mode))return(OS_TYPE_SOCK); | ||
73 | else return(OS_TYPE_FILE); | ||
74 | } | ||
75 | |||
76 | int access_file(char *path, int r, int w, int x) | ||
77 | { | ||
78 | int mode = 0; | ||
79 | |||
80 | if(r) mode = R_OK; | ||
81 | if(w) mode |= W_OK; | ||
82 | if(x) mode |= X_OK; | ||
83 | if(access(path, mode) != 0) return(-errno); | ||
84 | else return(0); | ||
85 | } | ||
86 | |||
87 | int open_file(char *path, int r, int w, int append) | ||
88 | { | ||
89 | int mode = 0, fd; | ||
90 | |||
91 | if(r && !w) | ||
92 | mode = O_RDONLY; | ||
93 | else if(!r && w) | ||
94 | mode = O_WRONLY; | ||
95 | else if(r && w) | ||
96 | mode = O_RDWR; | ||
97 | else panic("Impossible mode in open_file"); | ||
98 | |||
99 | if(append) | ||
100 | mode |= O_APPEND; | ||
101 | fd = open64(path, mode); | ||
102 | if(fd < 0) return(-errno); | ||
103 | else return(fd); | ||
104 | } | ||
105 | |||
106 | void *open_dir(char *path, int *err_out) | ||
107 | { | ||
108 | DIR *dir; | ||
109 | |||
110 | dir = opendir(path); | ||
111 | *err_out = errno; | ||
112 | if(dir == NULL) return(NULL); | ||
113 | return(dir); | ||
114 | } | ||
115 | |||
116 | char *read_dir(void *stream, unsigned long long *pos, | ||
117 | unsigned long long *ino_out, int *len_out) | ||
118 | { | ||
119 | DIR *dir = stream; | ||
120 | struct dirent *ent; | ||
121 | |||
122 | seekdir(dir, *pos); | ||
123 | ent = readdir(dir); | ||
124 | if(ent == NULL) return(NULL); | ||
125 | *len_out = strlen(ent->d_name); | ||
126 | *ino_out = ent->d_ino; | ||
127 | *pos = telldir(dir); | ||
128 | return(ent->d_name); | ||
129 | } | ||
130 | |||
131 | int read_file(int fd, unsigned long long *offset, char *buf, int len) | ||
132 | { | ||
133 | int n; | ||
134 | |||
135 | n = pread64(fd, buf, len, *offset); | ||
136 | if(n < 0) return(-errno); | ||
137 | *offset += n; | ||
138 | return(n); | ||
139 | } | ||
140 | |||
141 | int write_file(int fd, unsigned long long *offset, const char *buf, int len) | ||
142 | { | ||
143 | int n; | ||
144 | |||
145 | n = pwrite64(fd, buf, len, *offset); | ||
146 | if(n < 0) return(-errno); | ||
147 | *offset += n; | ||
148 | return(n); | ||
149 | } | ||
150 | |||
151 | int lseek_file(int fd, long long offset, int whence) | ||
152 | { | ||
153 | int ret; | ||
154 | |||
155 | ret = lseek64(fd, offset, whence); | ||
156 | if(ret < 0) return(-errno); | ||
157 | return(0); | ||
158 | } | ||
159 | |||
160 | void close_file(void *stream) | ||
161 | { | ||
162 | close(*((int *) stream)); | ||
163 | } | ||
164 | |||
165 | void close_dir(void *stream) | ||
166 | { | ||
167 | closedir(stream); | ||
168 | } | ||
169 | |||
170 | int file_create(char *name, int ur, int uw, int ux, int gr, | ||
171 | int gw, int gx, int or, int ow, int ox) | ||
172 | { | ||
173 | int mode, fd; | ||
174 | |||
175 | mode = 0; | ||
176 | mode |= ur ? S_IRUSR : 0; | ||
177 | mode |= uw ? S_IWUSR : 0; | ||
178 | mode |= ux ? S_IXUSR : 0; | ||
179 | mode |= gr ? S_IRGRP : 0; | ||
180 | mode |= gw ? S_IWGRP : 0; | ||
181 | mode |= gx ? S_IXGRP : 0; | ||
182 | mode |= or ? S_IROTH : 0; | ||
183 | mode |= ow ? S_IWOTH : 0; | ||
184 | mode |= ox ? S_IXOTH : 0; | ||
185 | fd = open64(name, O_CREAT | O_RDWR, mode); | ||
186 | if(fd < 0) | ||
187 | return(-errno); | ||
188 | return(fd); | ||
189 | } | ||
190 | |||
191 | int set_attr(const char *file, struct hostfs_iattr *attrs) | ||
192 | { | ||
193 | struct utimbuf buf; | ||
194 | int err, ma; | ||
195 | |||
196 | if(attrs->ia_valid & HOSTFS_ATTR_MODE){ | ||
197 | if(chmod(file, attrs->ia_mode) != 0) return(-errno); | ||
198 | } | ||
199 | if(attrs->ia_valid & HOSTFS_ATTR_UID){ | ||
200 | if(chown(file, attrs->ia_uid, -1)) return(-errno); | ||
201 | } | ||
202 | if(attrs->ia_valid & HOSTFS_ATTR_GID){ | ||
203 | if(chown(file, -1, attrs->ia_gid)) return(-errno); | ||
204 | } | ||
205 | if(attrs->ia_valid & HOSTFS_ATTR_SIZE){ | ||
206 | if(truncate(file, attrs->ia_size)) return(-errno); | ||
207 | } | ||
208 | ma = HOSTFS_ATTR_ATIME_SET | HOSTFS_ATTR_MTIME_SET; | ||
209 | if((attrs->ia_valid & ma) == ma){ | ||
210 | buf.actime = attrs->ia_atime.tv_sec; | ||
211 | buf.modtime = attrs->ia_mtime.tv_sec; | ||
212 | if(utime(file, &buf) != 0) return(-errno); | ||
213 | } | ||
214 | else { | ||
215 | struct timespec ts; | ||
216 | |||
217 | if(attrs->ia_valid & HOSTFS_ATTR_ATIME_SET){ | ||
218 | err = stat_file(file, NULL, NULL, NULL, NULL, NULL, | ||
219 | NULL, NULL, &ts, NULL, NULL, NULL); | ||
220 | if(err != 0) | ||
221 | return(err); | ||
222 | buf.actime = attrs->ia_atime.tv_sec; | ||
223 | buf.modtime = ts.tv_sec; | ||
224 | if(utime(file, &buf) != 0) | ||
225 | return(-errno); | ||
226 | } | ||
227 | if(attrs->ia_valid & HOSTFS_ATTR_MTIME_SET){ | ||
228 | err = stat_file(file, NULL, NULL, NULL, NULL, NULL, | ||
229 | NULL, &ts, NULL, NULL, NULL, NULL); | ||
230 | if(err != 0) | ||
231 | return(err); | ||
232 | buf.actime = ts.tv_sec; | ||
233 | buf.modtime = attrs->ia_mtime.tv_sec; | ||
234 | if(utime(file, &buf) != 0) | ||
235 | return(-errno); | ||
236 | } | ||
237 | } | ||
238 | if(attrs->ia_valid & HOSTFS_ATTR_CTIME) ; | ||
239 | if(attrs->ia_valid & (HOSTFS_ATTR_ATIME | HOSTFS_ATTR_MTIME)){ | ||
240 | err = stat_file(file, NULL, NULL, NULL, NULL, NULL, NULL, | ||
241 | &attrs->ia_atime, &attrs->ia_mtime, NULL, | ||
242 | NULL, NULL); | ||
243 | if(err != 0) return(err); | ||
244 | } | ||
245 | return(0); | ||
246 | } | ||
247 | |||
248 | int make_symlink(const char *from, const char *to) | ||
249 | { | ||
250 | int err; | ||
251 | |||
252 | err = symlink(to, from); | ||
253 | if(err) return(-errno); | ||
254 | return(0); | ||
255 | } | ||
256 | |||
257 | int unlink_file(const char *file) | ||
258 | { | ||
259 | int err; | ||
260 | |||
261 | err = unlink(file); | ||
262 | if(err) return(-errno); | ||
263 | return(0); | ||
264 | } | ||
265 | |||
266 | int do_mkdir(const char *file, int mode) | ||
267 | { | ||
268 | int err; | ||
269 | |||
270 | err = mkdir(file, mode); | ||
271 | if(err) return(-errno); | ||
272 | return(0); | ||
273 | } | ||
274 | |||
275 | int do_rmdir(const char *file) | ||
276 | { | ||
277 | int err; | ||
278 | |||
279 | err = rmdir(file); | ||
280 | if(err) return(-errno); | ||
281 | return(0); | ||
282 | } | ||
283 | |||
284 | int do_mknod(const char *file, int mode, int dev) | ||
285 | { | ||
286 | int err; | ||
287 | |||
288 | err = mknod(file, mode, dev); | ||
289 | if(err) return(-errno); | ||
290 | return(0); | ||
291 | } | ||
292 | |||
293 | int link_file(const char *to, const char *from) | ||
294 | { | ||
295 | int err; | ||
296 | |||
297 | err = link(to, from); | ||
298 | if(err) return(-errno); | ||
299 | return(0); | ||
300 | } | ||
301 | |||
302 | int do_readlink(char *file, char *buf, int size) | ||
303 | { | ||
304 | int n; | ||
305 | |||
306 | n = readlink(file, buf, size); | ||
307 | if(n < 0) | ||
308 | return(-errno); | ||
309 | if(n < size) | ||
310 | buf[n] = '\0'; | ||
311 | return(n); | ||
312 | } | ||
313 | |||
314 | int rename_file(char *from, char *to) | ||
315 | { | ||
316 | int err; | ||
317 | |||
318 | err = rename(from, to); | ||
319 | if(err < 0) return(-errno); | ||
320 | return(0); | ||
321 | } | ||
322 | |||
323 | int do_statfs(char *root, long *bsize_out, long long *blocks_out, | ||
324 | long long *bfree_out, long long *bavail_out, | ||
325 | long long *files_out, long long *ffree_out, | ||
326 | void *fsid_out, int fsid_size, long *namelen_out, | ||
327 | long *spare_out) | ||
328 | { | ||
329 | struct statfs64 buf; | ||
330 | int err; | ||
331 | |||
332 | err = statfs64(root, &buf); | ||
333 | if(err < 0) return(-errno); | ||
334 | *bsize_out = buf.f_bsize; | ||
335 | *blocks_out = buf.f_blocks; | ||
336 | *bfree_out = buf.f_bfree; | ||
337 | *bavail_out = buf.f_bavail; | ||
338 | *files_out = buf.f_files; | ||
339 | *ffree_out = buf.f_ffree; | ||
340 | memcpy(fsid_out, &buf.f_fsid, | ||
341 | sizeof(buf.f_fsid) > fsid_size ? fsid_size : | ||
342 | sizeof(buf.f_fsid)); | ||
343 | *namelen_out = buf.f_namelen; | ||
344 | spare_out[0] = buf.f_spare[0]; | ||
345 | spare_out[1] = buf.f_spare[1]; | ||
346 | spare_out[2] = buf.f_spare[2]; | ||
347 | spare_out[3] = buf.f_spare[3]; | ||
348 | spare_out[4] = buf.f_spare[4]; | ||
349 | spare_out[5] = buf.f_spare[5]; | ||
350 | return(0); | ||
351 | } | ||
352 | |||
353 | /* | ||
354 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
355 | * Emacs will notice this stuff at the end of the file and automatically | ||
356 | * adjust the settings for this buffer only. This must remain at the end | ||
357 | * of the file. | ||
358 | * --------------------------------------------------------------------------- | ||
359 | * Local variables: | ||
360 | * c-file-style: "linux" | ||
361 | * End: | ||
362 | */ | ||