Merge branch 'akpm-incoming-1'
[sfrench/cifs-2.6.git] / fs / hostfs / hostfs_user.c
1 /*
2  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3  * Licensed under the GPL
4  */
5
6 #include <stdio.h>
7 #include <stddef.h>
8 #include <unistd.h>
9 #include <dirent.h>
10 #include <errno.h>
11 #include <fcntl.h>
12 #include <string.h>
13 #include <sys/stat.h>
14 #include <sys/time.h>
15 #include <sys/types.h>
16 #include <sys/vfs.h>
17 #include "hostfs.h"
18 #include "os.h"
19 #include "user.h"
20 #include <utime.h>
21
22 static void stat64_to_hostfs(const struct stat64 *buf, struct hostfs_stat *p)
23 {
24         p->ino = buf->st_ino;
25         p->mode = buf->st_mode;
26         p->nlink = buf->st_nlink;
27         p->uid = buf->st_uid;
28         p->gid = buf->st_gid;
29         p->size = buf->st_size;
30         p->atime.tv_sec = buf->st_atime;
31         p->atime.tv_nsec = 0;
32         p->ctime.tv_sec = buf->st_ctime;
33         p->ctime.tv_nsec = 0;
34         p->mtime.tv_sec = buf->st_mtime;
35         p->mtime.tv_nsec = 0;
36         p->blksize = buf->st_blksize;
37         p->blocks = buf->st_blocks;
38         p->maj = os_major(buf->st_rdev);
39         p->min = os_minor(buf->st_rdev);
40 }
41
42 int stat_file(const char *path, struct hostfs_stat *p, int fd)
43 {
44         struct stat64 buf;
45
46         if (fd >= 0) {
47                 if (fstat64(fd, &buf) < 0)
48                         return -errno;
49         } else if (lstat64(path, &buf) < 0) {
50                 return -errno;
51         }
52         stat64_to_hostfs(&buf, p);
53         return 0;
54 }
55
56 int access_file(char *path, int r, int w, int x)
57 {
58         int mode = 0;
59
60         if (r)
61                 mode = R_OK;
62         if (w)
63                 mode |= W_OK;
64         if (x)
65                 mode |= X_OK;
66         if (access(path, mode) != 0)
67                 return -errno;
68         else return 0;
69 }
70
71 int open_file(char *path, int r, int w, int append)
72 {
73         int mode = 0, fd;
74
75         if (r && !w)
76                 mode = O_RDONLY;
77         else if (!r && w)
78                 mode = O_WRONLY;
79         else if (r && w)
80                 mode = O_RDWR;
81         else panic("Impossible mode in open_file");
82
83         if (append)
84                 mode |= O_APPEND;
85         fd = open64(path, mode);
86         if (fd < 0)
87                 return -errno;
88         else return fd;
89 }
90
91 void *open_dir(char *path, int *err_out)
92 {
93         DIR *dir;
94
95         dir = opendir(path);
96         *err_out = errno;
97
98         return dir;
99 }
100
101 char *read_dir(void *stream, unsigned long long *pos,
102                unsigned long long *ino_out, int *len_out)
103 {
104         DIR *dir = stream;
105         struct dirent *ent;
106
107         seekdir(dir, *pos);
108         ent = readdir(dir);
109         if (ent == NULL)
110                 return NULL;
111         *len_out = strlen(ent->d_name);
112         *ino_out = ent->d_ino;
113         *pos = telldir(dir);
114         return ent->d_name;
115 }
116
117 int read_file(int fd, unsigned long long *offset, char *buf, int len)
118 {
119         int n;
120
121         n = pread64(fd, buf, len, *offset);
122         if (n < 0)
123                 return -errno;
124         *offset += n;
125         return n;
126 }
127
128 int write_file(int fd, unsigned long long *offset, const char *buf, int len)
129 {
130         int n;
131
132         n = pwrite64(fd, buf, len, *offset);
133         if (n < 0)
134                 return -errno;
135         *offset += n;
136         return n;
137 }
138
139 int lseek_file(int fd, long long offset, int whence)
140 {
141         int ret;
142
143         ret = lseek64(fd, offset, whence);
144         if (ret < 0)
145                 return -errno;
146         return 0;
147 }
148
149 int fsync_file(int fd, int datasync)
150 {
151         int ret;
152         if (datasync)
153                 ret = fdatasync(fd);
154         else
155                 ret = fsync(fd);
156
157         if (ret < 0)
158                 return -errno;
159         return 0;
160 }
161
162 int replace_file(int oldfd, int fd)
163 {
164         return dup2(oldfd, fd);
165 }
166
167 void close_file(void *stream)
168 {
169         close(*((int *) stream));
170 }
171
172 void close_dir(void *stream)
173 {
174         closedir(stream);
175 }
176
177 int file_create(char *name, int ur, int uw, int ux, int gr,
178                 int gw, int gx, int or, int ow, int ox)
179 {
180         int mode, fd;
181
182         mode = 0;
183         mode |= ur ? S_IRUSR : 0;
184         mode |= uw ? S_IWUSR : 0;
185         mode |= ux ? S_IXUSR : 0;
186         mode |= gr ? S_IRGRP : 0;
187         mode |= gw ? S_IWGRP : 0;
188         mode |= gx ? S_IXGRP : 0;
189         mode |= or ? S_IROTH : 0;
190         mode |= ow ? S_IWOTH : 0;
191         mode |= ox ? S_IXOTH : 0;
192         fd = open64(name, O_CREAT | O_RDWR, mode);
193         if (fd < 0)
194                 return -errno;
195         return fd;
196 }
197
198 int set_attr(const char *file, struct hostfs_iattr *attrs, int fd)
199 {
200         struct hostfs_stat st;
201         struct timeval times[2];
202         int err, ma;
203
204         if (attrs->ia_valid & HOSTFS_ATTR_MODE) {
205                 if (fd >= 0) {
206                         if (fchmod(fd, attrs->ia_mode) != 0)
207                                 return -errno;
208                 } else if (chmod(file, attrs->ia_mode) != 0) {
209                         return -errno;
210                 }
211         }
212         if (attrs->ia_valid & HOSTFS_ATTR_UID) {
213                 if (fd >= 0) {
214                         if (fchown(fd, attrs->ia_uid, -1))
215                                 return -errno;
216                 } else if (chown(file, attrs->ia_uid, -1)) {
217                         return -errno;
218                 }
219         }
220         if (attrs->ia_valid & HOSTFS_ATTR_GID) {
221                 if (fd >= 0) {
222                         if (fchown(fd, -1, attrs->ia_gid))
223                                 return -errno;
224                 } else if (chown(file, -1, attrs->ia_gid)) {
225                         return -errno;
226                 }
227         }
228         if (attrs->ia_valid & HOSTFS_ATTR_SIZE) {
229                 if (fd >= 0) {
230                         if (ftruncate(fd, attrs->ia_size))
231                                 return -errno;
232                 } else if (truncate(file, attrs->ia_size)) {
233                         return -errno;
234                 }
235         }
236
237         /*
238          * Update accessed and/or modified time, in two parts: first set
239          * times according to the changes to perform, and then call futimes()
240          * or utimes() to apply them.
241          */
242         ma = (HOSTFS_ATTR_ATIME_SET | HOSTFS_ATTR_MTIME_SET);
243         if (attrs->ia_valid & ma) {
244                 err = stat_file(file, &st, fd);
245                 if (err != 0)
246                         return err;
247
248                 times[0].tv_sec = st.atime.tv_sec;
249                 times[0].tv_usec = st.atime.tv_nsec / 1000;
250                 times[1].tv_sec = st.mtime.tv_sec;
251                 times[1].tv_usec = st.mtime.tv_nsec / 1000;
252
253                 if (attrs->ia_valid & HOSTFS_ATTR_ATIME_SET) {
254                         times[0].tv_sec = attrs->ia_atime.tv_sec;
255                         times[0].tv_usec = attrs->ia_atime.tv_nsec / 1000;
256                 }
257                 if (attrs->ia_valid & HOSTFS_ATTR_MTIME_SET) {
258                         times[1].tv_sec = attrs->ia_mtime.tv_sec;
259                         times[1].tv_usec = attrs->ia_mtime.tv_nsec / 1000;
260                 }
261
262                 if (fd >= 0) {
263                         if (futimes(fd, times) != 0)
264                                 return -errno;
265                 } else if (utimes(file, times) != 0) {
266                         return -errno;
267                 }
268         }
269
270         /* Note: ctime is not handled */
271         if (attrs->ia_valid & (HOSTFS_ATTR_ATIME | HOSTFS_ATTR_MTIME)) {
272                 err = stat_file(file, &st, fd);
273                 attrs->ia_atime = st.atime;
274                 attrs->ia_mtime = st.mtime;
275                 if (err != 0)
276                         return err;
277         }
278         return 0;
279 }
280
281 int make_symlink(const char *from, const char *to)
282 {
283         int err;
284
285         err = symlink(to, from);
286         if (err)
287                 return -errno;
288         return 0;
289 }
290
291 int unlink_file(const char *file)
292 {
293         int err;
294
295         err = unlink(file);
296         if (err)
297                 return -errno;
298         return 0;
299 }
300
301 int do_mkdir(const char *file, int mode)
302 {
303         int err;
304
305         err = mkdir(file, mode);
306         if (err)
307                 return -errno;
308         return 0;
309 }
310
311 int do_rmdir(const char *file)
312 {
313         int err;
314
315         err = rmdir(file);
316         if (err)
317                 return -errno;
318         return 0;
319 }
320
321 int do_mknod(const char *file, int mode, unsigned int major, unsigned int minor)
322 {
323         int err;
324
325         err = mknod(file, mode, os_makedev(major, minor));
326         if (err)
327                 return -errno;
328         return 0;
329 }
330
331 int link_file(const char *to, const char *from)
332 {
333         int err;
334
335         err = link(to, from);
336         if (err)
337                 return -errno;
338         return 0;
339 }
340
341 int hostfs_do_readlink(char *file, char *buf, int size)
342 {
343         int n;
344
345         n = readlink(file, buf, size);
346         if (n < 0)
347                 return -errno;
348         if (n < size)
349                 buf[n] = '\0';
350         return n;
351 }
352
353 int rename_file(char *from, char *to)
354 {
355         int err;
356
357         err = rename(from, to);
358         if (err < 0)
359                 return -errno;
360         return 0;
361 }
362
363 int do_statfs(char *root, long *bsize_out, long long *blocks_out,
364               long long *bfree_out, long long *bavail_out,
365               long long *files_out, long long *ffree_out,
366               void *fsid_out, int fsid_size, long *namelen_out)
367 {
368         struct statfs64 buf;
369         int err;
370
371         err = statfs64(root, &buf);
372         if (err < 0)
373                 return -errno;
374
375         *bsize_out = buf.f_bsize;
376         *blocks_out = buf.f_blocks;
377         *bfree_out = buf.f_bfree;
378         *bavail_out = buf.f_bavail;
379         *files_out = buf.f_files;
380         *ffree_out = buf.f_ffree;
381         memcpy(fsid_out, &buf.f_fsid,
382                sizeof(buf.f_fsid) > fsid_size ? fsid_size :
383                sizeof(buf.f_fsid));
384         *namelen_out = buf.f_namelen;
385
386         return 0;
387 }