Initial Commit
[Projects.git] / pkgbuilds / wiifuse / src / wiifuse-0.2.0 / fs_client.c
blob3d7d6a9f20d6712bdbbaff2717ffa2c1c696745c
1 /*
2 * Copyright (C) 2008 dhewg, #wiidev efnet
4 * this file is part of wiifuse
5 * http://wiibrew.org/index.php?title=Wiifuse
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <unistd.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <ctype.h>
29 #include <errno.h>
31 #include "global.h"
32 #include "client.h"
33 #include "fs_client.h"
35 int fs_client_get_native_error (const enum remote_result result) {
36 switch (result) {
37 case RES_ENOENT:
38 return -ENOENT;
39 case RES_ENOTDIR:
40 return -ENOTDIR;
41 case RES_EISDIR:
42 return -EISDIR;
43 case RES_EACCES:
44 return -EACCES;
45 case RES_ENAMETOOLONG:
46 return -ENAMETOOLONG;
47 default:
48 return -EFAULT;
52 void get_remote_attr (struct remote_attr *attributes, const u8 *data) {
53 attributes->is_dir = data[0];
54 attributes->nlink = get_be16 (&data[1]);
55 attributes->size = get_be32 (&data[3]);
56 attributes->owner = get_be32 (&data[7]);
57 attributes->group = get_be32 (&data[11]);
58 attributes->perms = get_be16 (&data[15]);
61 void put_remote_attr (u8 *data, const struct remote_attr *attributes) {
62 data[0] = attributes->is_dir;
63 put_be16 (&data[1], attributes->nlink);
64 put_be32 (&data[3], attributes->size);
65 put_be32 (&data[7], attributes->owner);
66 put_be32 (&data[11], attributes->group);
67 put_be16 (&data[15], attributes->perms);
70 void get_remote_perms (mode_t *mode, const u16 perms) {
71 *mode = 0;
72 if (perms & MODE_IRUSR)
73 *mode |= S_IRUSR;
74 if (perms & MODE_IWUSR)
75 *mode |= S_IWUSR;
76 if (perms & MODE_IXUSR)
77 *mode |= S_IXUSR;
79 if (perms & MODE_IRGRP)
80 *mode |= S_IRGRP;
81 if (perms & MODE_IWGRP)
82 *mode |= S_IWGRP;
83 if (perms & MODE_IXGRP)
84 *mode |= S_IXGRP;
86 if (perms & MODE_IROTH)
87 *mode |= S_IROTH;
88 if (perms & MODE_IWOTH)
89 *mode |= S_IWOTH;
90 if (perms & MODE_IXOTH)
91 *mode |= S_IXOTH;
94 void put_remote_perms (u16 *perms, const mode_t mode) {
95 *perms = 0;
96 if (mode & S_IRUSR)
97 *perms |= MODE_IRUSR;
98 if (mode & S_IWUSR)
99 *perms |= MODE_IWUSR;
100 if (mode & S_IXUSR)
101 *perms |= MODE_IXUSR;
103 if (mode & S_IRGRP)
104 *perms |= MODE_IRGRP;
105 if (mode & S_IWGRP)
106 *perms |= MODE_IWGRP;
107 if (mode & S_IXGRP)
108 *perms |= MODE_IXGRP;
110 if (mode & S_IROTH)
111 *perms |= MODE_IROTH;
112 if (mode & S_IWOTH)
113 *perms |= MODE_IWOTH;
114 if (mode & S_IXOTH)
115 *perms |= MODE_IXOTH;
118 int fs_client_access (const char *path, int mode) {
119 struct server_response *r;
120 int res;
121 u8 data;
123 data = 0;
124 if (mode & R_OK)
125 data |= ACCESS_R_OK;
126 if (mode & W_OK)
127 data |= ACCESS_W_OK;
128 if (mode & X_OK)
129 data |= ACCESS_X_OK;
131 r = client_request (CMD_FS_ACCESS, path, &data, 1);
132 if (!r)
133 return -EFAULT;
135 if (r->result != RES_OK) {
136 res = fs_client_get_native_error (r->result);
137 client_free_response (r);
138 return res;
141 client_free_response (r);
142 return 0;
145 int fs_client_getattr (const char *path, struct stat *stbuf) {
146 struct server_response *r;
147 int res;
148 struct remote_attr attributes;
150 memset (stbuf, 0, sizeof (struct stat));
152 r = client_request (CMD_FS_GETATTR, path, NULL, 0);
154 if (!r)
155 return -EFAULT;
157 if (!r->data || r->data_size != 17) {
158 client_free_response (r);
159 return -ENOENT;
162 if (r->result != RES_OK) {
163 res = fs_client_get_native_error (r->result);
164 client_free_response (r);
165 return res;
168 get_remote_attr (&attributes, r->data);
169 get_remote_perms (&(stbuf->st_mode), attributes.perms);
171 if (attributes.is_dir)
172 stbuf->st_mode |= S_IFDIR;
173 else
174 stbuf->st_mode |= S_IFREG;
176 stbuf->st_nlink = attributes.nlink;
177 stbuf->st_size = attributes.size;
178 stbuf->st_blocks = attributes.size / 512;
179 stbuf->st_uid = attributes.owner;
180 stbuf->st_gid = attributes.group;
182 client_free_response (r);
183 return 0;
186 int fs_client_open (const char *path, struct fuse_file_info *fi) {
187 struct server_response *r;
188 int res;
190 (void) fi;
192 r = client_request (CMD_FS_OPEN, path, NULL, 0);
194 if (!r)
195 return -EFAULT;
197 if (r->result != RES_OK) {
198 res = fs_client_get_native_error (r->result);
199 client_free_response (r);
200 return res;
203 client_free_response (r);
204 return 0;
207 int fs_client_read (const char *path, char *buf, size_t size,
208 off_t offset, struct fuse_file_info *fi) {
209 struct server_response *r;
210 u8 data[10];
211 int bytes_read;
212 int res;
214 (void) fi;
216 if (size > 0xffff)
217 return -EFAULT;
219 put_be16 (data, size);
220 put_be64 (&data[2], offset);
222 r = client_request (CMD_FS_READ, path, data, 10);
224 if (!r)
225 return -EIO;
227 if (r->result != RES_OK) {
228 res = fs_client_get_native_error (r->result);
229 client_free_response (r);
230 return res;
233 bytes_read = r->data_size;
235 if (bytes_read > 0)
236 memcpy (buf, r->data, bytes_read);
238 client_free_response (r);
239 return bytes_read;
242 int fs_client_opendir (const char *path, struct fuse_file_info *fi) {
243 struct server_response *r;
244 int res;
246 (void) fi;
248 r = client_request (CMD_FS_OPENDIR, path, NULL, 0);
250 if (!r)
251 return -EFAULT;
253 if (r->result != RES_OK) {
254 res = fs_client_get_native_error (r->result);
255 client_free_response (r);
256 return res;
259 client_free_response (r);
260 return 0;
263 int fs_client_readdir (const char *path, void *buf, fuse_fill_dir_t filler,
264 off_t offset, struct fuse_file_info *fi) {
265 struct server_response *r;
266 char *p;
267 size_t s;
268 int res;
270 (void) offset;
271 (void) fi;
273 r = client_request (CMD_FS_READDIR, path, NULL, 0);
275 if (!r)
276 return -EFAULT;
278 if (r->result != RES_OK) {
279 res = fs_client_get_native_error (r->result);
280 client_free_response (r);
281 return res;
284 filler (buf, ".", NULL, 0);
285 filler (buf, "..", NULL, 0);
287 if (r->data) {
288 p = (char *) r->data;
289 while (*p) {
290 s = strlen (p);
291 filler (buf, p, NULL, 0);
292 p += s + 1;
296 client_free_response (r);
297 return 0;
300 int fs_client_mkdir (const char *path, mode_t mode) {
301 struct server_response *r;
302 int res;
303 u16 perms;
304 u8 data[2];
306 put_remote_perms (&perms, mode);
308 put_be16 (data, perms);
310 r = client_request (CMD_FS_MKDIR, path, data, 2);
312 if (!r)
313 return -EFAULT;
315 if (r->result != RES_OK) {
316 res = fs_client_get_native_error (r->result);
317 client_free_response (r);
318 return res;
321 client_free_response (r);
322 return 0;
325 int fs_client_rmdir (const char *path) {
326 struct server_response *r;
327 int res;
329 r = client_request (CMD_FS_RMDIR, path, NULL, 0);
331 if (!r)
332 return -EFAULT;
334 if (r->result != RES_OK) {
335 res = fs_client_get_native_error (r->result);
336 client_free_response (r);
337 return res;
340 client_free_response (r);
341 return 0;
344 int fs_client_create (const char *path, mode_t mode,
345 struct fuse_file_info *fi) {
346 struct server_response *r;
347 int res;
348 u16 perms;
349 u8 data[2];
351 (void) fi;
353 put_remote_perms (&perms, mode);
355 put_be16 (data, perms);
357 r = client_request (CMD_FS_CREATE, path, data, 2);
359 if (!r)
360 return -EFAULT;
362 if (r->result != RES_OK) {
363 res = fs_client_get_native_error (r->result);
364 client_free_response (r);
365 return res;
368 client_free_response (r);
369 return 0;
372 int fs_client_write (const char *path, const char *buf, size_t size,
373 off_t offset, struct fuse_file_info *fi) {
374 struct server_response *r;
375 u8 *data;
376 int bytes_written;
377 int res;
379 (void) fi;
381 if (size > 0xffff)
382 return -EFAULT;
384 data = malloc (size + 10);
386 put_be16 (data, size);
387 put_be64 (&data[2], offset);
388 memcpy (&data[10], buf, size);
390 r = client_request (CMD_FS_WRITE, path, data, size + 10);
392 free (data);
394 if (!r)
395 return -EIO;
397 if (r->result != RES_OK) {
398 res = fs_client_get_native_error (r->result);
399 client_free_response (r);
400 return res;
403 if (r->data_size != 8) {
404 client_free_response (r);
405 return -EIO;
408 bytes_written = get_be64 (r->data);
410 client_free_response (r);
411 return bytes_written;
414 int fs_client_chown (const char *filename, uid_t uid, gid_t gid) {
415 struct server_response *r;
416 int res;
417 u32 owner;
418 u32 group;
419 u8 data[8];
421 owner = uid;
422 group = gid;
424 put_be32 (data, owner);
425 put_be32 (&data[4], group);
427 r = client_request (CMD_FS_CHOWN, filename, data, 8);
429 if (!r)
430 return -EFAULT;
432 if (r->result != RES_OK) {
433 res = fs_client_get_native_error (r->result);
434 client_free_response (r);
435 return res;
438 client_free_response (r);
439 return 0;
442 int fs_client_chmod (const char *filename, mode_t mode) {
443 struct server_response *r;
444 int res;
445 u16 perms;
446 u8 data[2];
448 put_remote_perms (&perms, mode);
449 put_be16 (data, perms);
451 r = client_request (CMD_FS_CHMOD, filename, &data, 2);
453 if (!r)
454 return -EFAULT;
456 if (r->result != RES_OK) {
457 res = fs_client_get_native_error (r->result);
458 client_free_response (r);
459 return res;
462 client_free_response (r);
463 return 0;
466 int fs_client_rename (const char *src, const char *dst) {
467 struct server_response *r;
468 int res;
470 r = client_request (CMD_FS_RENAME, src, dst, strlen (dst));
472 if (!r)
473 return -EFAULT;
475 if (r->result != RES_OK) {
476 res = fs_client_get_native_error (r->result);
477 client_free_response (r);
478 return res;
481 client_free_response (r);
482 return 0;
485 int fs_client_unlink (const char *path) {
486 struct server_response *r;
487 int res;
489 r = client_request (CMD_FS_UNLINK, path, NULL, 0);
491 if (!r)
492 return -EFAULT;
494 if (r->result != RES_OK) {
495 res = fs_client_get_native_error (r->result);
496 client_free_response (r);
497 return res;
500 client_free_response (r);
501 return 0;
504 int fs_client_statfs (const char *path, struct statvfs *svfs) {
505 struct server_response *r;
506 int res;
508 memset (svfs, 0, sizeof (struct statvfs));
510 r = client_request (CMD_FS_STATFS, path, NULL, 0);
512 if (!r)
513 return -EFAULT;
515 if (r->result != RES_OK) {
516 res = fs_client_get_native_error (r->result);
517 client_free_response (r);
518 return res;
521 if (r->data_size != 5 * 8) {
522 client_free_response (r);
523 return -EIO;
526 svfs->f_bsize = get_be64 (r->data);
527 svfs->f_blocks = get_be64 (&(r->data[8]));
528 svfs->f_bfree = get_be64 (&(r->data[16]));
529 svfs->f_files = get_be64 (&(r->data[24]));
530 svfs->f_ffree = get_be64 (&(r->data[32]));
532 client_free_response (r);
533 return 0;
536 void fs_client_destroy () {
537 struct server_response *r;
539 r = client_request (CMD_UMOUNT, NULL, NULL, 0);
541 if (!r) {
542 LOG_ERR ("server did not ack the umount");
543 return;
546 if (r->result != RES_OK)
547 LOG_ERR ("server did not umount (%d)", r->result);
549 client_free_response (r);
552 void fs_client_get_ops (struct fuse_operations *fs_ops) {
553 memset (fs_ops, 0, sizeof (struct fuse_operations));
555 fs_ops->access = fs_client_access;
556 fs_ops->getattr = fs_client_getattr;
557 fs_ops->open = fs_client_open;
558 fs_ops->read = fs_client_read;
559 fs_ops->opendir = fs_client_opendir;
560 fs_ops->readdir = fs_client_readdir;
562 fs_ops->mkdir = fs_client_mkdir;
563 fs_ops->unlink = fs_client_unlink;
564 fs_ops->rmdir = fs_client_rmdir;
565 fs_ops->chown = fs_client_chown;
566 fs_ops->chmod = fs_client_chmod;
567 fs_ops->rename = fs_client_rename;
568 fs_ops->write = fs_client_write;
569 fs_ops->create = fs_client_create;
571 fs_ops->statfs = fs_client_statfs;
573 fs_ops->destroy = fs_client_destroy;