⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fs_nand.c

📁 WiiFuse is a FUSE filesystem module for Linux and Mac OS X. It will let you mount a Wii disc ISO an
💻 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 <stdio.h>#include <stdlib.h>#include <string.h>#include <malloc.h>#include <gccore.h>#include <ogcsys.h>#include <ogc/isfs.h>#include "../../shared.h"#include "global.h"// TODO use libogc stuff when available#define ISFS_ACCESS_R         0x01#define ISFS_ACCESS_W         0x02#define ISFS_ACCESS_RW        (ISFS_ACCESS_R | ISFS_ACCESS_W)#define ISFS_MAX_PATHNAMELEN  64#define ISFS_MAX_FILENAMELEN  12#define NAND_TYPE_FILE        0x01#define NAND_TYPE_DIR         0x02s32 ISFS_GetType (const char *filename, u8 *type) {        s32 res;        u32 num;        res = ISFS_ReadDir (filename, NULL, &num);        //LOG (2, "ISFS_GetType %d %u", res, num);        switch (res) {        case 0:        case -102:                *type = NAND_TYPE_DIR;                res = ISFS_OK;                break;        case -101:                *type = NAND_TYPE_FILE;                res = ISFS_OK;                break;        }        return res;}enum remote_result get_server_error (const s32 err_code) {        switch (err_code) {                case -101:                        return RES_EISDIR;                case -102:                        return RES_EACCES;                case -106:                        return RES_ENOENT;                default:                        LOG_ERR ("unhandled error code: %d", err_code);                        return RES_ENOENT;        }}bool nand_init (u8 **data, u16 *data_size) {        s32 res;        u64 title_id;        static char path[ISFS_MAX_PATHNAMELEN] ATTRIBUTE_ALIGN(32);        res = ISFS_Initialize ();                if (res != ISFS_OK)                return false;        res = ES_GetTitleID (&title_id);        if (res != ISFS_OK) {                LOG_ERR ("ES_GetTitleID failed: %d", res);                return false;        }        res = ES_GetDataDir (title_id, path);        if (res != ISFS_OK) {                LOG_ERR ("ES_GetDataDir failed: %d", res);                return false;        }        LOG (1, "nand data dir is \"%s\"", path);        *data_size = strlen (path);        *data = malloc (*data_size);        memcpy (*data, path, *data_size);        return true;}bool nand_deinit () {        return ISFS_Deinitialize () == ISFS_OK;}void get_remote_perms (u8 *u_perms, u8 *g_perms, u8 *o_perms, const u16 perms) {        *u_perms = 0;        *g_perms = 0;        *o_perms = 0;        if (perms & MODE_IRUSR)                *u_perms |= ISFS_ACCESS_R;        if (perms & MODE_IWUSR)                *u_perms |= ISFS_ACCESS_W;        if (perms & MODE_IRGRP)                *g_perms |= ISFS_ACCESS_R;        if (perms & MODE_IWGRP)                *g_perms |= ISFS_ACCESS_W;        if (perms & MODE_IROTH)                *o_perms |= ISFS_ACCESS_R;        if (perms & MODE_IWOTH)                *o_perms |= ISFS_ACCESS_W;}void put_remote_perms (u16 *perms, const u8 u_perms, const u8 g_perms,                       const u8 o_perms, const bool is_dir) {        *perms = 0;        if (u_perms & ISFS_ACCESS_R)                *perms |= MODE_IRUSR;        if (u_perms & ISFS_ACCESS_W)                *perms |= MODE_IWUSR;        if (g_perms & ISFS_ACCESS_R)                *perms |= MODE_IRGRP;        if (g_perms & ISFS_ACCESS_W)                *perms |= MODE_IWGRP;        if (o_perms & ISFS_ACCESS_R)                *perms |= MODE_IROTH;        if (o_perms & ISFS_ACCESS_W)                *perms |= MODE_IWOTH;        if (is_dir) {                if (u_perms & ISFS_ACCESS_RW)                        *perms |= MODE_IXUSR;                if (g_perms & ISFS_ACCESS_RW)                        *perms |= MODE_IXGRP;                if (o_perms & ISFS_ACCESS_RW)                        *perms |= MODE_IXOTH;        }}enum remote_result nand_access (const char *filename, u8 mode) {        s32 res;        u8 type;        res = ISFS_GetType (filename, &type);        if (res != ISFS_OK)                return get_server_error (res);        if ((mode & ACCESS_X_OK) && (type != NAND_TYPE_DIR))                return RES_ENOTDIR;        return RES_OK;}enum remote_result nand_getattr (const char *filename,                                 struct remote_attr *attributes) {        s32 fd, res;        static fstats fstat ATTRIBUTE_ALIGN(32);        u32 owner;        u16 group;        u8 attr, u_perms, g_perms, o_perms;        u8 type;        res = ISFS_GetAttr (filename, &owner, &group, &attr,                            &u_perms, &g_perms, &o_perms);        if (res != ISFS_OK) {                LOG_ERR ("ISFS_GetAttr failed: %d", res);                return get_server_error (res);        }        LOG (2, "o=0x%08x g=0x%04x a=0x%02x perm=0x%02x,0x%02x,0x%02x (%s)",             owner, group, attr, u_perms, g_perms, o_perms, filename);        if (attr)                printf ("ATTENTION: attr=0x%02x on %s\n", attr, filename);        attributes->owner = owner;        attributes->group = group;        res = ISFS_GetType (filename, &type);        if (type == NAND_TYPE_DIR) {                attributes->is_dir = 1;                attributes->nlink = 2;                put_remote_perms (&(attributes->perms), u_perms, g_perms,                                  o_perms, true);                return RES_OK;        }        put_remote_perms (&(attributes->perms), u_perms, g_perms,                          o_perms, false);        fd = ISFS_Open (filename, ISFS_ACCESS_R);        if (fd < 0) {                LOG_ERR ("ISFS_Open failed: %d", fd);                return get_server_error (fd);        }        res = ISFS_GetFileStats (fd, &fstat);        ISFS_Close (fd);        if (res != ISFS_OK) {                LOG_ERR ("ISFS_GetFileStats failed: %d", res);                return get_server_error (res);        }        attributes->size = fstat.file_length;        attributes->nlink = 1;        return RES_OK;}enum remote_result nand_open (const char *filename) {        s32 fd;        fd = ISFS_Open (filename, ISFS_ACCESS_R);        if (fd < 0) {                LOG_ERR ("ISFS_Open failed: %d", fd);                return get_server_error (fd);        }        ISFS_Close (fd);        return RES_OK;}enum remote_result nand_read (const char *filename, const u64 offset,                              u16 *size, u8 *buffer) {        s32 fd, res;        s32 off;        fd = ISFS_Open (filename, ISFS_ACCESS_R);        if (fd < 0) {                LOG_ERR ("ISFS_Open failed: %d", fd);                return get_server_error (fd);        }        off = offset & 0x7fffffff;        if (off > 0) {                res = ISFS_Seek (fd, off, 0);                if (res != off) {                        LOG_ERR ("ISFS_Seek failed: %d", res);                        ISFS_Close (fd);                        return get_server_error (res);                }        }	LOG_ERR ("Reading %hu bytes\n", *size);	int bytes_read = 0;	while (bytes_read < *size) {	  int bytes_to_read = (*size - bytes_read) > 2048 ? 2048 : (*size - bytes_read);	  LOG_ERR("Calling ISFS_Read(%d, %p, %d)\n", fd, buffer+bytes_read, bytes_to_read);	  res = ISFS_Read (fd, buffer+bytes_read, bytes_to_read);	  	  if (res < 0) {	    LOG_ERR ("ISFS_Read failed: %d", res);	    ISFS_Close (fd);	    return get_server_error (res);	  }	  bytes_read += bytes_to_read;	}        *size = bytes_read;        ISFS_Close (fd);        return RES_OK;}enum remote_result nand_opendir (const char *dirname) {        s32 res;        u8 type;        res = ISFS_GetType (dirname, &type);        if (res != ISFS_OK) {                LOG_ERR ("ISFS_GetType failed: %d", res);                return get_server_error (res);        }        if (type == NAND_TYPE_DIR)                return RES_OK;        else                return RES_ENOTDIR;}enum remote_result nand_readdir (const char *dirname, u8 **data,                                 u16 *data_size) {        s32 res;        char *list;        u32 num;        u32 i;        res = ISFS_ReadDir (dirname, NULL, &num);        if (res != ISFS_OK) {                LOG_ERR ("ISFS_ReadDir failed: %d", res);                return get_server_error (res);        }        if (num < 1) {                LOG (2, "dir is empty");                return RES_OK;        }        list = memalign (32, num * (ISFS_MAX_FILENAMELEN + 1) + 1);        res = ISFS_ReadDir (dirname, list, &num);        if (res != ISFS_OK) {                LOG_ERR ("ISFS_ReadDir failed %d", res);                free (list);                return get_server_error (res);        }        for (i = 0; i < num; ++i)                *data_size += strlen (&list[*data_size]) + 1;        *data = malloc (*data_size + 1);        memcpy (*data, list, *data_size);        (*data)[*data_size] = 0;        *data_size += 1;        free (list);        return RES_OK;}enum remote_result nand_mkdir (const char *dirname, const u16 perms) {        u8 u_perms, g_perms, o_perms;        s32 res;        get_remote_perms (&u_perms, &g_perms, &o_perms, perms);        LOG (2, "nand perms 0x%02x 0x%02x 0x%02x", u_perms, g_perms, o_perms);        res = ISFS_CreateDir (dirname, 0, u_perms, g_perms, o_perms);        if (res != ISFS_OK) {                LOG_ERR ("ISFS_CreateDir failed: %d", res);                return get_server_error (res);        }        return RES_OK;}enum remote_result nand_rmdir (const char *dirname) {        s32 res;        res = ISFS_Delete (dirname);        if (res != ISFS_OK) {                LOG_ERR ("ISFS_Delete failed: %d", res);                return get_server_error (res);        }        return RES_OK;}enum remote_result nand_create (const char *filename, const u16 perms) {        u8 u_perms, g_perms, o_perms;        s32 res;        get_remote_perms (&u_perms, &g_perms, &o_perms, perms);        LOG (2, "nand perms 0x%02x 0x%02x 0x%02x", u_perms, g_perms, o_perms);        res = ISFS_CreateFile (filename, 0, u_perms, g_perms, o_perms);        if (res != ISFS_OK) {                LOG_ERR ("ISFS_CreateFile failed: %d", res);                return get_server_error (res);        }        return RES_OK;}enum remote_result nand_write (const char *filename, const u64 offset,                               u16 *size, u8 *buffer) {        s32 fd, res;        s32 off;        u8 *buf;        fd = ISFS_Open (filename, ISFS_ACCESS_W);        if (fd < 0) {                LOG_ERR ("ISFS_Open failed: %d", fd);                return get_server_error (fd);        }        off = offset & 0x7fffffff;        if (off > 0) {                res = ISFS_Seek (fd, off, 0);                if (res != off) {                        LOG_ERR ("ISFS_Seek failed: %d", res);                        ISFS_Close (fd);                        return get_server_error (res);                }        }        buf = memalign (32, *size);        memcpy (buf, buffer, *size);        res = ISFS_Write (fd, buf, *size);        free (buf);        if (res < 0) {                LOG_ERR ("ISFS_Write failed: %d", res);                ISFS_Close (fd);                return get_server_error (res);        }        *size = res;        ISFS_Close (fd);        return RES_OK;}enum remote_result nand_chown (const char *filename, const u32 uid,                               const u32 gid) {        u32 owner;        u16 group;        u8 attr, u_perms, g_perms, o_perms;        s32 res;        if (gid > 0xffff) {                LOG_ERR ("group id is only 16bit");                res = RES_EACCES;        }        res = ISFS_GetAttr (filename, &owner, &group, &attr,                            &u_perms, &g_perms, &o_perms);        if (res != ISFS_OK) {                LOG_ERR ("ISFS_GetAttr failed: %d", res);                return get_server_error (res);        }        LOG (2, "current nand id's %u %u", owner, group);        group = gid & 0xffff;        res = ISFS_SetAttr (filename, uid, group, attr,                            u_perms, g_perms, o_perms);        if (res != ISFS_OK) {                LOG_ERR ("ISFS_SetAttr failed: %d", res);                return get_server_error (res);        }        return RES_OK;}enum remote_result nand_chmod (const char *filename, const u16 perms) {        u32 owner;        u16 group;        u8 attr, u_perms, g_perms, o_perms;        s32 res;        res = ISFS_GetAttr (filename, &owner, &group, &attr,                            &u_perms, &g_perms, &o_perms);        if (res != ISFS_OK) {                LOG_ERR ("ISFS_GetAttr failed: %d", res);                return get_server_error (res);        }        LOG (2, "current nand perms 0x%02x 0x%02x 0x%02x", u_perms, g_perms,             o_perms);        get_remote_perms (&u_perms, &g_perms, &o_perms, perms);        LOG (2, "new nand perms 0x%02x 0x%02x 0x%02x", u_perms, g_perms,             o_perms);        res = ISFS_SetAttr (filename, owner, group, attr,                            u_perms, g_perms, o_perms);        if (res != ISFS_OK) {                LOG_ERR ("ISFS_SetAttr failed: %d", res);                return get_server_error (res);        }        return RES_OK;}enum remote_result nand_rename (const char *src, const char *dst) {        s32 res;        res = ISFS_Rename (src, dst);        if (res != ISFS_OK) {                LOG_ERR ("ISFS_Rename failed: %d", res);                return get_server_error (res);        }        return RES_OK;}enum remote_result nand_unlink (const char *filename) {        s32 res;        res = ISFS_Delete (filename);        if (res != ISFS_OK) {                LOG_ERR ("ISFS_Delete failed: %d", res);                return get_server_error (res);        }        return RES_OK;}enum remote_result nand_statfs (const char *filename, u64 *bsize, u64 *blocks,                                u64 *bfree, u64 *files, u64 *ffree){        *bsize = 0x4000;        *blocks = 0x8000;        // TODO missing call, just some dummy values so os's wont error out        *bfree = 0x4000;        *files = 0x400;        *ffree = 0x200;        return RES_OK;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -