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>
33 #include "fs_client.h"
35 int fs_client_get_native_error (const enum remote_result result
) {
45 case RES_ENAMETOOLONG
:
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
) {
72 if (perms
& MODE_IRUSR
)
74 if (perms
& MODE_IWUSR
)
76 if (perms
& MODE_IXUSR
)
79 if (perms
& MODE_IRGRP
)
81 if (perms
& MODE_IWGRP
)
83 if (perms
& MODE_IXGRP
)
86 if (perms
& MODE_IROTH
)
88 if (perms
& MODE_IWOTH
)
90 if (perms
& MODE_IXOTH
)
94 void put_remote_perms (u16
*perms
, const mode_t mode
) {
101 *perms
|= MODE_IXUSR
;
104 *perms
|= MODE_IRGRP
;
106 *perms
|= MODE_IWGRP
;
108 *perms
|= MODE_IXGRP
;
111 *perms
|= MODE_IROTH
;
113 *perms
|= MODE_IWOTH
;
115 *perms
|= MODE_IXOTH
;
118 int fs_client_access (const char *path
, int mode
) {
119 struct server_response
*r
;
131 r
= client_request (CMD_FS_ACCESS
, path
, &data
, 1);
135 if (r
->result
!= RES_OK
) {
136 res
= fs_client_get_native_error (r
->result
);
137 client_free_response (r
);
141 client_free_response (r
);
145 int fs_client_getattr (const char *path
, struct stat
*stbuf
) {
146 struct server_response
*r
;
148 struct remote_attr attributes
;
150 memset (stbuf
, 0, sizeof (struct stat
));
152 r
= client_request (CMD_FS_GETATTR
, path
, NULL
, 0);
157 if (!r
->data
|| r
->data_size
!= 17) {
158 client_free_response (r
);
162 if (r
->result
!= RES_OK
) {
163 res
= fs_client_get_native_error (r
->result
);
164 client_free_response (r
);
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
;
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
);
186 int fs_client_open (const char *path
, struct fuse_file_info
*fi
) {
187 struct server_response
*r
;
192 r
= client_request (CMD_FS_OPEN
, path
, NULL
, 0);
197 if (r
->result
!= RES_OK
) {
198 res
= fs_client_get_native_error (r
->result
);
199 client_free_response (r
);
203 client_free_response (r
);
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
;
219 put_be16 (data
, size
);
220 put_be64 (&data
[2], offset
);
222 r
= client_request (CMD_FS_READ
, path
, data
, 10);
227 if (r
->result
!= RES_OK
) {
228 res
= fs_client_get_native_error (r
->result
);
229 client_free_response (r
);
233 bytes_read
= r
->data_size
;
236 memcpy (buf
, r
->data
, bytes_read
);
238 client_free_response (r
);
242 int fs_client_opendir (const char *path
, struct fuse_file_info
*fi
) {
243 struct server_response
*r
;
248 r
= client_request (CMD_FS_OPENDIR
, path
, NULL
, 0);
253 if (r
->result
!= RES_OK
) {
254 res
= fs_client_get_native_error (r
->result
);
255 client_free_response (r
);
259 client_free_response (r
);
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
;
273 r
= client_request (CMD_FS_READDIR
, path
, NULL
, 0);
278 if (r
->result
!= RES_OK
) {
279 res
= fs_client_get_native_error (r
->result
);
280 client_free_response (r
);
284 filler (buf
, ".", NULL
, 0);
285 filler (buf
, "..", NULL
, 0);
288 p
= (char *) r
->data
;
291 filler (buf
, p
, NULL
, 0);
296 client_free_response (r
);
300 int fs_client_mkdir (const char *path
, mode_t mode
) {
301 struct server_response
*r
;
306 put_remote_perms (&perms
, mode
);
308 put_be16 (data
, perms
);
310 r
= client_request (CMD_FS_MKDIR
, path
, data
, 2);
315 if (r
->result
!= RES_OK
) {
316 res
= fs_client_get_native_error (r
->result
);
317 client_free_response (r
);
321 client_free_response (r
);
325 int fs_client_rmdir (const char *path
) {
326 struct server_response
*r
;
329 r
= client_request (CMD_FS_RMDIR
, path
, NULL
, 0);
334 if (r
->result
!= RES_OK
) {
335 res
= fs_client_get_native_error (r
->result
);
336 client_free_response (r
);
340 client_free_response (r
);
344 int fs_client_create (const char *path
, mode_t mode
,
345 struct fuse_file_info
*fi
) {
346 struct server_response
*r
;
353 put_remote_perms (&perms
, mode
);
355 put_be16 (data
, perms
);
357 r
= client_request (CMD_FS_CREATE
, path
, data
, 2);
362 if (r
->result
!= RES_OK
) {
363 res
= fs_client_get_native_error (r
->result
);
364 client_free_response (r
);
368 client_free_response (r
);
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
;
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);
397 if (r
->result
!= RES_OK
) {
398 res
= fs_client_get_native_error (r
->result
);
399 client_free_response (r
);
403 if (r
->data_size
!= 8) {
404 client_free_response (r
);
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
;
424 put_be32 (data
, owner
);
425 put_be32 (&data
[4], group
);
427 r
= client_request (CMD_FS_CHOWN
, filename
, data
, 8);
432 if (r
->result
!= RES_OK
) {
433 res
= fs_client_get_native_error (r
->result
);
434 client_free_response (r
);
438 client_free_response (r
);
442 int fs_client_chmod (const char *filename
, mode_t mode
) {
443 struct server_response
*r
;
448 put_remote_perms (&perms
, mode
);
449 put_be16 (data
, perms
);
451 r
= client_request (CMD_FS_CHMOD
, filename
, &data
, 2);
456 if (r
->result
!= RES_OK
) {
457 res
= fs_client_get_native_error (r
->result
);
458 client_free_response (r
);
462 client_free_response (r
);
466 int fs_client_rename (const char *src
, const char *dst
) {
467 struct server_response
*r
;
470 r
= client_request (CMD_FS_RENAME
, src
, dst
, strlen (dst
));
475 if (r
->result
!= RES_OK
) {
476 res
= fs_client_get_native_error (r
->result
);
477 client_free_response (r
);
481 client_free_response (r
);
485 int fs_client_unlink (const char *path
) {
486 struct server_response
*r
;
489 r
= client_request (CMD_FS_UNLINK
, path
, NULL
, 0);
494 if (r
->result
!= RES_OK
) {
495 res
= fs_client_get_native_error (r
->result
);
496 client_free_response (r
);
500 client_free_response (r
);
504 int fs_client_statfs (const char *path
, struct statvfs
*svfs
) {
505 struct server_response
*r
;
508 memset (svfs
, 0, sizeof (struct statvfs
));
510 r
= client_request (CMD_FS_STATFS
, path
, NULL
, 0);
515 if (r
->result
!= RES_OK
) {
516 res
= fs_client_get_native_error (r
->result
);
517 client_free_response (r
);
521 if (r
->data_size
!= 5 * 8) {
522 client_free_response (r
);
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
);
536 void fs_client_destroy () {
537 struct server_response
*r
;
539 r
= client_request (CMD_UMOUNT
, NULL
, NULL
, 0);
542 LOG_ERR ("server did not ack the umount");
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
;