📄 fs_client.c
字号:
/* * Copyright (C) 2008 dhewg, #wiidev efnet * * this file is part of wiifuse * http://wiibrew.org/index.php?title=Wiifuse * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <ctype.h>#include <errno.h>#include "global.h"#include "client.h"#include "fs_client.h"int fs_client_get_native_error (const enum remote_result result) { switch (result) { case RES_ENOENT: return -ENOENT; case RES_ENOTDIR: return -ENOTDIR; case RES_EISDIR: return -EISDIR; case RES_EACCES: return -EACCES; case RES_ENAMETOOLONG: return -ENAMETOOLONG; default: return -EFAULT; }}void get_remote_attr (struct remote_attr *attributes, const u8 *data) { attributes->is_dir = data[0]; attributes->nlink = get_be16 (&data[1]); attributes->size = get_be32 (&data[3]); attributes->owner = get_be32 (&data[7]); attributes->group = get_be32 (&data[11]); attributes->perms = get_be16 (&data[15]);}void put_remote_attr (u8 *data, const struct remote_attr *attributes) { data[0] = attributes->is_dir; put_be16 (&data[1], attributes->nlink); put_be32 (&data[3], attributes->size); put_be32 (&data[7], attributes->owner); put_be32 (&data[11], attributes->group); put_be16 (&data[15], attributes->perms);}void get_remote_perms (mode_t *mode, const u16 perms) { *mode = 0; if (perms & MODE_IRUSR) *mode |= S_IRUSR; if (perms & MODE_IWUSR) *mode |= S_IWUSR; if (perms & MODE_IXUSR) *mode |= S_IXUSR; if (perms & MODE_IRGRP) *mode |= S_IRGRP; if (perms & MODE_IWGRP) *mode |= S_IWGRP; if (perms & MODE_IXGRP) *mode |= S_IXGRP; if (perms & MODE_IROTH) *mode |= S_IROTH; if (perms & MODE_IWOTH) *mode |= S_IWOTH; if (perms & MODE_IXOTH) *mode |= S_IXOTH;}void put_remote_perms (u16 *perms, const mode_t mode) { *perms = 0; if (mode & S_IRUSR) *perms |= MODE_IRUSR; if (mode & S_IWUSR) *perms |= MODE_IWUSR; if (mode & S_IXUSR) *perms |= MODE_IXUSR; if (mode & S_IRGRP) *perms |= MODE_IRGRP; if (mode & S_IWGRP) *perms |= MODE_IWGRP; if (mode & S_IXGRP) *perms |= MODE_IXGRP; if (mode & S_IROTH) *perms |= MODE_IROTH; if (mode & S_IWOTH) *perms |= MODE_IWOTH; if (mode & S_IXOTH) *perms |= MODE_IXOTH;}int fs_client_access (const char *path, int mode) { struct server_response *r; int res; u8 data; data = 0; if (mode & R_OK) data |= ACCESS_R_OK; if (mode & W_OK) data |= ACCESS_W_OK; if (mode & X_OK) data |= ACCESS_X_OK; r = client_request (CMD_FS_ACCESS, path, &data, 1); if (!r) return -EFAULT; if (r->result != RES_OK) { res = fs_client_get_native_error (r->result); client_free_response (r); return res; } client_free_response (r); return 0;}int fs_client_getattr (const char *path, struct stat *stbuf) { struct server_response *r; int res; struct remote_attr attributes; memset (stbuf, 0, sizeof (struct stat)); r = client_request (CMD_FS_GETATTR, path, NULL, 0); if (!r) return -EFAULT; if (!r->data || r->data_size != 17) { client_free_response (r); return -ENOENT; } if (r->result != RES_OK) { res = fs_client_get_native_error (r->result); client_free_response (r); return res; } get_remote_attr (&attributes, r->data); get_remote_perms (&(stbuf->st_mode), attributes.perms); if (attributes.is_dir) stbuf->st_mode |= S_IFDIR; else stbuf->st_mode |= S_IFREG; stbuf->st_nlink = attributes.nlink; stbuf->st_size = attributes.size; stbuf->st_blocks = attributes.size / 512; stbuf->st_uid = attributes.owner; stbuf->st_gid = attributes.group; client_free_response (r); return 0;}int fs_client_open (const char *path, struct fuse_file_info *fi) { struct server_response *r; int res; (void) fi; r = client_request (CMD_FS_OPEN, path, NULL, 0); if (!r) return -EFAULT; if (r->result != RES_OK) { res = fs_client_get_native_error (r->result); client_free_response (r); return res; } client_free_response (r); return 0;}int fs_client_read (const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { struct server_response *r; u8 data[10]; int bytes_read; int res; (void) fi; // if (size > 0xffff) // return -EFAULT; put_be16 (data, size); put_be64 (&data[2], offset); r = client_request (CMD_FS_READ, path, data, 10); if (!r) return -EIO; if (r->result != RES_OK) { res = fs_client_get_native_error (r->result); client_free_response (r); return res; } bytes_read = r->data_size; if (bytes_read > 0) memcpy (buf, r->data, bytes_read); client_free_response (r); return bytes_read;}int fs_client_opendir (const char *path, struct fuse_file_info *fi) { struct server_response *r; int res; (void) fi; r = client_request (CMD_FS_OPENDIR, path, NULL, 0); if (!r) return -EFAULT; if (r->result != RES_OK) { res = fs_client_get_native_error (r->result); client_free_response (r); return res; } client_free_response (r); return 0;}int fs_client_readdir (const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) { struct server_response *r; char *p; size_t s; int res; (void) offset; (void) fi; r = client_request (CMD_FS_READDIR, path, NULL, 0); if (!r) return -EFAULT; if (r->result != RES_OK) { res = fs_client_get_native_error (r->result); client_free_response (r); return res; } filler (buf, ".", NULL, 0); filler (buf, "..", NULL, 0); if (r->data) { p = (char *) r->data; while (*p) { s = strlen (p); filler (buf, p, NULL, 0); p += s + 1; } } client_free_response (r); return 0;}int fs_client_mkdir (const char *path, mode_t mode) { struct server_response *r; int res; u16 perms; u8 data[2]; put_remote_perms (&perms, mode); put_be16 (data, perms); r = client_request (CMD_FS_MKDIR, path, data, 2); if (!r) return -EFAULT; if (r->result != RES_OK) { res = fs_client_get_native_error (r->result); client_free_response (r); return res; } client_free_response (r); return 0;}int fs_client_rmdir (const char *path) { struct server_response *r; int res; r = client_request (CMD_FS_RMDIR, path, NULL, 0); if (!r) return -EFAULT; if (r->result != RES_OK) { res = fs_client_get_native_error (r->result); client_free_response (r); return res; } client_free_response (r); return 0;}int fs_client_create (const char *path, mode_t mode, struct fuse_file_info *fi) { struct server_response *r; int res; u16 perms; u8 data[2]; (void) fi; put_remote_perms (&perms, mode); put_be16 (data, perms); r = client_request (CMD_FS_CREATE, path, data, 2); if (!r) return -EFAULT; if (r->result != RES_OK) { res = fs_client_get_native_error (r->result); client_free_response (r); return res; } client_free_response (r); return 0;}int fs_client_write (const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { struct server_response *r; u8 *data; int bytes_written; int res; (void) fi; if (size > 0xffff) return -EFAULT; data = malloc (size + 10); put_be16 (data, size); put_be64 (&data[2], offset); memcpy (&data[10], buf, size); r = client_request (CMD_FS_WRITE, path, data, size + 10); free (data); if (!r) return -EIO; if (r->result != RES_OK) { res = fs_client_get_native_error (r->result); client_free_response (r); return res; } if (r->data_size != 8) { client_free_response (r); return -EIO; } bytes_written = get_be64 (r->data); client_free_response (r); return bytes_written;}int fs_client_chown (const char *filename, uid_t uid, gid_t gid) { struct server_response *r; int res; u32 owner; u32 group; u8 data[8]; owner = uid; group = gid; put_be32 (data, owner); put_be32 (&data[4], group); r = client_request (CMD_FS_CHOWN, filename, data, 8); if (!r) return -EFAULT; if (r->result != RES_OK) { res = fs_client_get_native_error (r->result); client_free_response (r); return res; } client_free_response (r); return 0;}int fs_client_chmod (const char *filename, mode_t mode) { struct server_response *r; int res; u16 perms; u8 data[2]; put_remote_perms (&perms, mode); put_be16 (data, perms); r = client_request (CMD_FS_CHMOD, filename, &data, 2); if (!r) return -EFAULT; if (r->result != RES_OK) { res = fs_client_get_native_error (r->result); client_free_response (r); return res; } client_free_response (r); return 0;}int fs_client_rename (const char *src, const char *dst) { struct server_response *r; int res; r = client_request (CMD_FS_RENAME, src, dst, strlen (dst)); if (!r) return -EFAULT; if (r->result != RES_OK) { res = fs_client_get_native_error (r->result); client_free_response (r); return res; } client_free_response (r); return 0;}int fs_client_unlink (const char *path) { struct server_response *r; int res; r = client_request (CMD_FS_UNLINK, path, NULL, 0); if (!r) return -EFAULT; if (r->result != RES_OK) { res = fs_client_get_native_error (r->result); client_free_response (r); return res; } client_free_response (r); return 0;}int fs_client_statfs (const char *path, struct statvfs *svfs) { struct server_response *r; int res; memset (svfs, 0, sizeof (struct statvfs)); r = client_request (CMD_FS_STATFS, path, NULL, 0); if (!r) return -EFAULT; if (r->result != RES_OK) { res = fs_client_get_native_error (r->result); client_free_response (r); return res; } if (r->data_size != 5 * 8) { client_free_response (r); return -EIO; } svfs->f_bsize = get_be64 (r->data); svfs->f_blocks = get_be64 (&(r->data[8])); svfs->f_bfree = get_be64 (&(r->data[16])); svfs->f_files = get_be64 (&(r->data[24])); svfs->f_ffree = get_be64 (&(r->data[32])); client_free_response (r); return 0;}void fs_client_destroy () { struct server_response *r; r = client_request (CMD_UMOUNT, NULL, NULL, 0); if (!r) { LOG_ERR ("server did not ack the umount"); return; } if (r->result != RES_OK) LOG_ERR ("server did not umount (%d)", r->result); client_free_response (r);}void fs_client_get_ops (struct fuse_operations *fs_ops) { memset (fs_ops, 0, sizeof (struct fuse_operations)); fs_ops->access = fs_client_access; fs_ops->getattr = fs_client_getattr; fs_ops->open = fs_client_open; fs_ops->read = fs_client_read; fs_ops->opendir = fs_client_opendir; fs_ops->readdir = fs_client_readdir; fs_ops->mkdir = fs_client_mkdir; fs_ops->unlink = fs_client_unlink; fs_ops->rmdir = fs_client_rmdir; fs_ops->chown = fs_client_chown; fs_ops->chmod = fs_client_chmod; fs_ops->rename = fs_client_rename; fs_ops->write = fs_client_write; fs_ops->create = fs_client_create; fs_ops->statfs = fs_client_statfs; fs_ops->destroy = fs_client_destroy;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -