switch stat_file() to passing a single struct rather than fsckloads of pointers
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / fs / hostfs / hostfs_user.c
blob701d454a6791ca001ecc24499cd21be59121f731
1 /*
2 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL
4 */
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>
22 static void stat64_to_hostfs(const struct stat64 *buf, struct hostfs_stat *p)
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);
42 int stat_file(const char *path, struct hostfs_stat *p, int fd)
44 struct stat64 buf;
46 if (fd >= 0) {
47 if (fstat64(fd, &buf) < 0)
48 return -errno;
49 } else if (lstat64(path, &buf) < 0) {
50 return -errno;
52 stat64_to_hostfs(&buf, p);
53 return 0;
56 int file_type(const char *path, int *maj, int *min)
58 struct stat64 buf;
60 if (lstat64(path, &buf) < 0)
61 return -errno;
63 * We cannot pass rdev as is because glibc and the kernel disagree
64 * about its definition.
66 if (maj != NULL)
67 *maj = os_major(buf.st_rdev);
68 if (min != NULL)
69 *min = os_minor(buf.st_rdev);
71 if (S_ISDIR(buf.st_mode))
72 return OS_TYPE_DIR;
73 else if (S_ISLNK(buf.st_mode))
74 return OS_TYPE_SYMLINK;
75 else if (S_ISCHR(buf.st_mode))
76 return OS_TYPE_CHARDEV;
77 else if (S_ISBLK(buf.st_mode))
78 return OS_TYPE_BLOCKDEV;
79 else if (S_ISFIFO(buf.st_mode))
80 return OS_TYPE_FIFO;
81 else if (S_ISSOCK(buf.st_mode))
82 return OS_TYPE_SOCK;
83 else return OS_TYPE_FILE;
86 int access_file(char *path, int r, int w, int x)
88 int mode = 0;
90 if (r)
91 mode = R_OK;
92 if (w)
93 mode |= W_OK;
94 if (x)
95 mode |= X_OK;
96 if (access(path, mode) != 0)
97 return -errno;
98 else return 0;
101 int open_file(char *path, int r, int w, int append)
103 int mode = 0, fd;
105 if (r && !w)
106 mode = O_RDONLY;
107 else if (!r && w)
108 mode = O_WRONLY;
109 else if (r && w)
110 mode = O_RDWR;
111 else panic("Impossible mode in open_file");
113 if (append)
114 mode |= O_APPEND;
115 fd = open64(path, mode);
116 if (fd < 0)
117 return -errno;
118 else return fd;
121 void *open_dir(char *path, int *err_out)
123 DIR *dir;
125 dir = opendir(path);
126 *err_out = errno;
127 if (dir == NULL)
128 return NULL;
129 return dir;
132 char *read_dir(void *stream, unsigned long long *pos,
133 unsigned long long *ino_out, int *len_out)
135 DIR *dir = stream;
136 struct dirent *ent;
138 seekdir(dir, *pos);
139 ent = readdir(dir);
140 if (ent == NULL)
141 return NULL;
142 *len_out = strlen(ent->d_name);
143 *ino_out = ent->d_ino;
144 *pos = telldir(dir);
145 return ent->d_name;
148 int read_file(int fd, unsigned long long *offset, char *buf, int len)
150 int n;
152 n = pread64(fd, buf, len, *offset);
153 if (n < 0)
154 return -errno;
155 *offset += n;
156 return n;
159 int write_file(int fd, unsigned long long *offset, const char *buf, int len)
161 int n;
163 n = pwrite64(fd, buf, len, *offset);
164 if (n < 0)
165 return -errno;
166 *offset += n;
167 return n;
170 int lseek_file(int fd, long long offset, int whence)
172 int ret;
174 ret = lseek64(fd, offset, whence);
175 if (ret < 0)
176 return -errno;
177 return 0;
180 int fsync_file(int fd, int datasync)
182 int ret;
183 if (datasync)
184 ret = fdatasync(fd);
185 else
186 ret = fsync(fd);
188 if (ret < 0)
189 return -errno;
190 return 0;
193 void close_file(void *stream)
195 close(*((int *) stream));
198 void close_dir(void *stream)
200 closedir(stream);
203 int file_create(char *name, int ur, int uw, int ux, int gr,
204 int gw, int gx, int or, int ow, int ox)
206 int mode, fd;
208 mode = 0;
209 mode |= ur ? S_IRUSR : 0;
210 mode |= uw ? S_IWUSR : 0;
211 mode |= ux ? S_IXUSR : 0;
212 mode |= gr ? S_IRGRP : 0;
213 mode |= gw ? S_IWGRP : 0;
214 mode |= gx ? S_IXGRP : 0;
215 mode |= or ? S_IROTH : 0;
216 mode |= ow ? S_IWOTH : 0;
217 mode |= ox ? S_IXOTH : 0;
218 fd = open64(name, O_CREAT | O_RDWR, mode);
219 if (fd < 0)
220 return -errno;
221 return fd;
224 int set_attr(const char *file, struct hostfs_iattr *attrs, int fd)
226 struct hostfs_stat st;
227 struct timeval times[2];
228 int err, ma;
230 if (attrs->ia_valid & HOSTFS_ATTR_MODE) {
231 if (fd >= 0) {
232 if (fchmod(fd, attrs->ia_mode) != 0)
233 return (-errno);
234 } else if (chmod(file, attrs->ia_mode) != 0) {
235 return -errno;
238 if (attrs->ia_valid & HOSTFS_ATTR_UID) {
239 if (fd >= 0) {
240 if (fchown(fd, attrs->ia_uid, -1))
241 return -errno;
242 } else if (chown(file, attrs->ia_uid, -1)) {
243 return -errno;
246 if (attrs->ia_valid & HOSTFS_ATTR_GID) {
247 if (fd >= 0) {
248 if (fchown(fd, -1, attrs->ia_gid))
249 return -errno;
250 } else if (chown(file, -1, attrs->ia_gid)) {
251 return -errno;
254 if (attrs->ia_valid & HOSTFS_ATTR_SIZE) {
255 if (fd >= 0) {
256 if (ftruncate(fd, attrs->ia_size))
257 return -errno;
258 } else if (truncate(file, attrs->ia_size)) {
259 return -errno;
264 * Update accessed and/or modified time, in two parts: first set
265 * times according to the changes to perform, and then call futimes()
266 * or utimes() to apply them.
268 ma = (HOSTFS_ATTR_ATIME_SET | HOSTFS_ATTR_MTIME_SET);
269 if (attrs->ia_valid & ma) {
270 err = stat_file(file, &st, fd);
271 if (err != 0)
272 return err;
274 times[0].tv_sec = st.atime.tv_sec;
275 times[0].tv_usec = st.atime.tv_nsec / 1000;
276 times[1].tv_sec = st.mtime.tv_sec;
277 times[1].tv_usec = st.mtime.tv_nsec / 1000;
279 if (attrs->ia_valid & HOSTFS_ATTR_ATIME_SET) {
280 times[0].tv_sec = attrs->ia_atime.tv_sec;
281 times[0].tv_usec = attrs->ia_atime.tv_nsec / 1000;
283 if (attrs->ia_valid & HOSTFS_ATTR_MTIME_SET) {
284 times[1].tv_sec = attrs->ia_mtime.tv_sec;
285 times[1].tv_usec = attrs->ia_mtime.tv_nsec / 1000;
288 if (fd >= 0) {
289 if (futimes(fd, times) != 0)
290 return -errno;
291 } else if (utimes(file, times) != 0) {
292 return -errno;
296 /* Note: ctime is not handled */
297 if (attrs->ia_valid & (HOSTFS_ATTR_ATIME | HOSTFS_ATTR_MTIME)) {
298 err = stat_file(file, &st, fd);
299 attrs->ia_atime = st.atime;
300 attrs->ia_mtime = st.mtime;
301 if (err != 0)
302 return err;
304 return 0;
307 int make_symlink(const char *from, const char *to)
309 int err;
311 err = symlink(to, from);
312 if (err)
313 return -errno;
314 return 0;
317 int unlink_file(const char *file)
319 int err;
321 err = unlink(file);
322 if (err)
323 return -errno;
324 return 0;
327 int do_mkdir(const char *file, int mode)
329 int err;
331 err = mkdir(file, mode);
332 if (err)
333 return -errno;
334 return 0;
337 int do_rmdir(const char *file)
339 int err;
341 err = rmdir(file);
342 if (err)
343 return -errno;
344 return 0;
347 int do_mknod(const char *file, int mode, unsigned int major, unsigned int minor)
349 int err;
351 err = mknod(file, mode, os_makedev(major, minor));
352 if (err)
353 return -errno;
354 return 0;
357 int link_file(const char *to, const char *from)
359 int err;
361 err = link(to, from);
362 if (err)
363 return -errno;
364 return 0;
367 int hostfs_do_readlink(char *file, char *buf, int size)
369 int n;
371 n = readlink(file, buf, size);
372 if (n < 0)
373 return -errno;
374 if (n < size)
375 buf[n] = '\0';
376 return n;
379 int rename_file(char *from, char *to)
381 int err;
383 err = rename(from, to);
384 if (err < 0)
385 return -errno;
386 return 0;
389 int do_statfs(char *root, long *bsize_out, long long *blocks_out,
390 long long *bfree_out, long long *bavail_out,
391 long long *files_out, long long *ffree_out,
392 void *fsid_out, int fsid_size, long *namelen_out,
393 long *spare_out)
395 struct statfs64 buf;
396 int err;
398 err = statfs64(root, &buf);
399 if (err < 0)
400 return -errno;
402 *bsize_out = buf.f_bsize;
403 *blocks_out = buf.f_blocks;
404 *bfree_out = buf.f_bfree;
405 *bavail_out = buf.f_bavail;
406 *files_out = buf.f_files;
407 *ffree_out = buf.f_ffree;
408 memcpy(fsid_out, &buf.f_fsid,
409 sizeof(buf.f_fsid) > fsid_size ? fsid_size :
410 sizeof(buf.f_fsid));
411 *namelen_out = buf.f_namelen;
412 spare_out[0] = buf.f_spare[0];
413 spare_out[1] = buf.f_spare[1];
414 spare_out[2] = buf.f_spare[2];
415 spare_out[3] = buf.f_spare[3];
416 spare_out[4] = buf.f_spare[4];
417 return 0;