DECL(int, FSGetFreeSpaceSizeAsync, void *pClient, void *pCmd, const char *path, uint64_t *returnedFreeSize, int error, void *asyncParams) { int client = GetCurClient(pClient); if (client != -1) { // log //fs_log_string(bss.socket_fs[client], path, BYTE_REMOVE); char buffer[200]; __os_snprintf(buffer, sizeof(buffer), "FSGetFreeSpaceSizeAsync: %s", path); fs_log_string(bss.global_sock, buffer, BYTE_LOG_STR); // change path if it is a save folder int pathType = getPathType(path); if (pathType == PATH_TYPE_SAVE) { int len = strlen(path); int len_base = getNewPathLen(pathType); char new_path[len + len_base + 1]; compute_new_path(new_path, path, len, pathType); // log new path fs_log_string(bss.socket_fs[client], new_path, BYTE_LOG_STR); return real_FSGetFreeSpaceSizeAsync(pClient, pCmd, new_path, returnedFreeSize, error, asyncParams); } } return real_FSGetFreeSpaceSizeAsync(pClient, pCmd, path, returnedFreeSize, error, asyncParams); }
// only for saves on sdcard DECL(int, FSRenameAsync, void *pClient, void *pCmd, const char *oldPath, const char *newPath, int error, void *asyncParams) { int client = GetCurClient(pClient); if (client != -1) { // log fs_log_string(bss.socket_fs[client], oldPath, BYTE_RENAME); fs_log_string(bss.socket_fs[client], newPath, BYTE_RENAME); // change path if it is a save folder int pathType = getPathType(oldPath); if (pathType == PATH_TYPE_SAVE) { // old path int len_base = getNewPathLen(pathType); int len_old = strlen(oldPath); char new_old_path[len_old + len_base + 1]; compute_new_path(new_old_path, oldPath, len_old, pathType); // new path int len_new = strlen(newPath); char new_new_path[len_new + len_base + 1]; compute_new_path(new_new_path, newPath, len_new, pathType); // log new path fs_log_string(bss.socket_fs[client], new_old_path, BYTE_LOG_STR); fs_log_string(bss.socket_fs[client], new_new_path, BYTE_LOG_STR); return real_FSRenameAsync(pClient, pCmd, new_old_path, new_new_path, error, asyncParams); } } return real_FSRenameAsync(pClient, pCmd, oldPath, newPath, error, asyncParams); }
/* * Creates a directory. We can ignore mode since we're not dealing with * permissions, as long as getattr returns appropriate ones for us. */ static int cs1550_mkdir(const char *path, mode_t mode) { (void) mode; char dir[MAX_FILENAME + 1]; char fileName[MAX_FILENAME + 1]; char ext[MAX_EXTENSION + 1]; getPath(path, dir, fileName, ext); int pathType = getPathType(path, dir, fileName, ext); if (strlen(dir) >= MAX_FILENAME) { return -ENAMETOOLONG; } else if (dirExists(dir) == 1){ return -EEXIST; } else if (pathType != 1){ return -EPERM; } else { cs1550_root_directory r; getRoot(&r); if (r.nDirectories < MAX_DIRS_IN_ROOT) { createDir(dir); } } return 0; }
/* * Deletes a file */ static int cs1550_unlink(const char *path) { char dir[MAX_FILENAME + 1]; char fileName[MAX_FILENAME + 1]; char ext[MAX_EXTENSION + 1]; getPath(path, dir, fileName, ext); int pathType = getPathType(path, dir, fileName, ext); int fileSize = getFileSize(dir, fileName, ext, pathType); if (pathType < 2) { return -EISDIR; } else if (fileSize == -1){ return -ENOENT; } else { cs1550_directory_entry parentDir; getDir(&parentDir, dir); int i =0; for (i = 0; i < parentDir.nFiles; i++) { if ((pathType==2 && strcmp(parentDir.files[i].fname, fileName)==0) || (pathType==3 && strcmp(parentDir.files[i].fname, fileName) == 0 && strcmp(parentDir.files[i].fext, ext) == 0)) { long startBlock = parentDir.files[i].nStartBlock; long seek = startBlock; FILE *f = fopen(".disk", "rb"); while(seek != 0) { fseek(f, seek, SEEK_SET); cs1550_disk_block curBlock; fread(&curBlock, BLOCK_SIZE, 1, f); cs1550_disk_block empty; memset(&empty, 0, BLOCK_SIZE); writeBlock(&empty, seek); int index = seek / BLOCK_SIZE; updateBitmap(index, 0); if (curBlock.magic_number != 0) { seek = curBlock.magic_number; } else { seek = 0; } } fclose(f); int x =0; for (x = 0; x < parentDir.nFiles; x++) { if (x >= i && x != parentDir.nFiles-1) { strcpy(parentDir.files[x].fname, parentDir.files[x+1].fname); strcpy(parentDir.files[x].fext, parentDir.files[x+1].fext); parentDir.files[x].fsize = parentDir.files[x+1].fsize; parentDir.files[x].nStartBlock = parentDir.files[x+1].nStartBlock; } } parentDir.nFiles--; updateDir(&parentDir, dir); } } } return 0; }
/* * Does the actual creation of a file. Mode and dev can be ignored. * */ static int cs1550_mknod(const char *path, mode_t mode, dev_t dev) { (void) mode; (void) dev; char dir[MAX_FILENAME + 1]; char fileName[MAX_FILENAME + 1]; char ext[MAX_EXTENSION + 1]; getPath(path, dir, fileName, ext); int pathType = getPathType(path, dir, fileName, ext); int fileSize = getFileSize(dir, fileName, ext, pathType); if (pathType < 2) { return -EPERM; } else if (fileSize != -1){ return -EEXIST; } else if (strlen(fileName) > MAX_FILENAME || strlen(ext) > MAX_EXTENSION) { return -ENAMETOOLONG; } else { cs1550_root_directory r; getRoot(&r); int i =0; for(i = 0; i < r.nDirectories; i++) { if (strcmp(r.directories[i].dname, dir) == 0) { int blockNum = getNextBlock(); long startBlock = (long)(BLOCK_SIZE * blockNum); updateBitmap(blockNum, 1); cs1550_directory_entry parentDir; getDir(&parentDir, dir); strcpy(parentDir.files[parentDir.nFiles].fname, fileName); strcpy(parentDir.files[parentDir.nFiles].fext, ext); parentDir.files[parentDir.nFiles].fsize = 0; parentDir.files[parentDir.nFiles].nStartBlock = startBlock; parentDir.nFiles++; int parentDirMagicNum = r.directories[i].nStartBlock; FILE *f = fopen(".disk", "rb+"); if (f != NULL) { fseek(f, 0, SEEK_END); int diskSize = ftell(f); rewind(f); char *buffer = (char *)malloc(diskSize); fread(buffer, diskSize, 1, f); rewind(f); memmove(buffer+parentDirMagicNum, &parentDir, BLOCK_SIZE); fwrite(buffer, diskSize, 1, f); fclose(f); free(buffer); } } } } return 0; }
/* * Called whenever the contents of a directory are desired. Could be from an 'ls' * or could even be when a user hits TAB to do autocompletion */ static int cs1550_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) { //Since we're building with -Wall (all warnings reported) we need //to "use" every parameter, so let's just cast them to void to //satisfy the compiler (void) offset; (void) fi; char dir[MAX_FILENAME + 1]; char fileName[MAX_FILENAME + 1]; char ext[MAX_EXTENSION + 1]; getPath(path, dir, fileName, ext); int pathType = getPathType(path, dir, fileName, ext); if (pathType == 0) { filler(buf, ".", NULL, 0); filler(buf, "..", NULL, 0); cs1550_root_directory r; getRoot(&r); int i = 0; for(i = 0; i < r.nDirectories; i++) { filler(buf, r.directories[i].dname, NULL, 0); } } else if (pathType == 1) { int dir_exists = dirExists(dir); if ( dir_exists == 1) { filler(buf, ".", NULL,0); filler(buf, "..", NULL, 0); cs1550_directory_entry curDir; getDir(&curDir, dir); int i =0; for (i = 0; i < curDir.nFiles; i++) { if ((strcmp(curDir.files[i].fext, "\0") == 0)) { filler(buf, curDir.files[i].fname, NULL, 0); } else { char *fileNameExt = (char *) malloc(2 + MAX_FILENAME + MAX_EXTENSION); strcpy(fileNameExt, curDir.files[i].fname); strcat(fileNameExt, "."); strcat(fileNameExt, curDir.files[i].fext); filler(buf, fileNameExt, NULL, 0); } } } else { return -ENOENT; } } else { return -ENOENT; } return 0; }
/* * Called whenever the system wants to know the file attributes, including * simply whether the file exists or not. * * man -s 2 stat will show the fields of a stat structure */ static int cs1550_getattr(const char *path, struct stat *stbuf) { memset(stbuf, 0, sizeof(struct stat)); char dir[MAX_FILENAME + 1]; char fileName[MAX_FILENAME + 1]; char ext[MAX_EXTENSION + 1]; getPath(path, dir, fileName, ext); int pathType = getPathType(path, dir, fileName, ext); if (pathType == 0) { //Root stbuf->st_mode = S_IFDIR | 0755; stbuf->st_nlink = 2; } else if (pathType == 1) { //Directory if (dirExists(dir) == 1) { stbuf->st_mode = S_IFDIR | 0755; stbuf->st_nlink = 2; } else { return -ENOENT; } } else if (pathType == 2 || pathType == 3) { //File int size = getFileSize(dir, fileName, ext, pathType); if (size != -1) { stbuf->st_mode = S_IFREG | 0666; stbuf->st_nlink = 1; //file links stbuf->st_size = (size_t)size; } else { return -ENOENT; } } else { return -ENOENT; } return 0; }
// only for saves on sdcard DECL(int, FSMakeDir, void *pClient, void *pCmd, const char *path, int error) { int client = GetCurClient(pClient); if (client != -1) { // log fs_log_string(bss.socket_fs[client], path, BYTE_MAKE_DIR); // change path if it is a save folder int pathType = getPathType(path); if (pathType == PATH_TYPE_SAVE) { int len = strlen(path); int len_base = getNewPathLen(pathType); char new_path[len + len_base + 1]; compute_new_path(new_path, path, len, pathType); // log new path fs_log_string(bss.socket_fs[client], new_path, BYTE_LOG_STR); return real_FSMakeDir(pClient, pCmd, new_path, error); } } return real_FSMakeDir(pClient, pCmd, path, error); }
DECL(int, FSRollbackQuota, void *pClient, void *pCmd, const char *path, int error) { int client = GetCurClient(pClient); if (client != -1) { // log char buffer[200]; __os_snprintf(buffer, sizeof(buffer), "FSRollbackQuota: %s", path); fs_log_string(bss.global_sock, buffer, BYTE_LOG_STR); // change path if it is a save folder int pathType = getPathType(path); if (pathType == PATH_TYPE_SAVE) { int len = strlen(path); int len_base = getNewPathLen(pathType); char new_path[len + len_base + 1]; compute_new_path(new_path, path, len, pathType); // log new path fs_log_string(bss.socket_fs[client], new_path, BYTE_LOG_STR); return real_FSRollbackQuota(pClient, pCmd, new_path, error); } } return real_FSRollbackQuota(pClient, pCmd, path, error); }
/* * Write size bytes from buf into file starting from offset * */ static int cs1550_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { int ret = 0; (void) fi; char dir[MAX_FILENAME + 1]; char fileName[MAX_FILENAME + 1]; char ext[MAX_EXTENSION + 1]; getPath(path, dir, fileName, ext); int pathType = getPathType(path, dir, fileName, ext); int fileSize = getFileSize(dir, fileName, ext, pathType); if (dirExists(dir) == 1 && pathType >= 2 && fileSize != -1 && size > 0) { cs1550_directory_entry parentDir; getDir(&parentDir, dir); int i =0; for (i = 0; i < parentDir.nFiles; i++) { if ((pathType==2 && strcmp(parentDir.files[i].fname, fileName)==0) || (pathType==3 && strcmp(parentDir.files[i].fname, fileName) == 0 && strcmp(parentDir.files[i].fext, ext) == 0)) { if (offset > parentDir.files[i].fsize) { return -EFBIG; } else { long startBlock = parentDir.files[i].nStartBlock; int blockNum = offset / BLOCK_SIZE; long seek = startBlock; long bStart = 0; FILE *f = fopen(".disk", "rb+"); int j = 0; for (j = 0; j <= blockNum; j++) { bStart = seek; fseek(f, seek, SEEK_SET); cs1550_disk_block fileBlock; fread(&fileBlock, BLOCK_SIZE, 1, f); seek = fileBlock.magic_number; } rewind(f); int off = (int)offset - (blockNum * BLOCK_SIZE); int index; int count = off; seek = bStart; fseek(f, seek, SEEK_SET); cs1550_disk_block curBlock; fread(&curBlock, BLOCK_SIZE, 1, f); for (index = 0; index < strlen(buf); index++) { if (count < MAX_DATA_IN_BLOCK) { curBlock.data[count] = (char)buf[index]; count++; } else { count = 0; if (curBlock.magic_number != 0) { writeBlock(&curBlock, seek); seek = curBlock.magic_number; fseek(f, seek, SEEK_SET); fread(&curBlock, BLOCK_SIZE, 1, f); } else { long cSeek = seek; int nextBlock = getNextBlock(); seek = nextBlock * BLOCK_SIZE; curBlock.magic_number = seek; writeBlock(&curBlock, cSeek); fseek(f, seek, SEEK_SET); fread(&curBlock, BLOCK_SIZE, 1, f); updateBitmap(nextBlock, 1); } } if (index == strlen(buf)-1) { writeBlock(&curBlock, seek); count = 0; } } fclose(f); int old = parentDir.files[i].fsize; int newSize = (size - (old - offset)) + (old - (old - offset)); parentDir.files[i].fsize = newSize; updateDir(&parentDir, dir); ret = newSize; } } } } return ret; }
/* * Read size bytes from file into buf starting from offset * */ static int cs1550_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { (void) fi; int ret =0; char dir[MAX_FILENAME + 1]; char fileName[MAX_FILENAME + 1]; char ext[MAX_EXTENSION + 1]; getPath(path, dir, fileName, ext); int pathType = getPathType(path, dir, fileName, ext); int fileSize = getFileSize(dir, fileName, ext, pathType); if (pathType < 2) { return -EISDIR; } else if (dirExists(dir) == 1 && fileSize != -1 && size > 0){ cs1550_directory_entry parentDir; getDir(&parentDir, dir); int i =0; for (i = 0; i < parentDir.nFiles; i++) { if ((pathType==2 && strcmp(parentDir.files[i].fname, fileName)==0) || (pathType==3 && strcmp(parentDir.files[i].fname, fileName) == 0 && strcmp(parentDir.files[i].fext, ext) == 0)) { if (offset <= parentDir.files[i].fsize) { long startBlock = parentDir.files[i].nStartBlock; int blockNum = offset / BLOCK_SIZE; long seek = startBlock; long bStart = 0; FILE *f = fopen(".disk", "rb+"); int j =0; for (j = 0; j <= blockNum; j++) { bStart = seek; fseek(f, seek, SEEK_SET); cs1550_disk_block fileBlock; fread(&fileBlock, BLOCK_SIZE, 1, f); seek = fileBlock.magic_number; } rewind(f); int off = (int)offset - (blockNum * BLOCK_SIZE); int count = off; int index = 0; seek = bStart; while(seek != 0) { fseek(f, seek, SEEK_SET); cs1550_disk_block curBlock; fread(&curBlock, BLOCK_SIZE, 1, f); if (count < MAX_DATA_IN_BLOCK) { buf[index] = (char)curBlock.data[count]; count++; index++; } else { seek = curBlock.magic_number; count = 0; } } fclose(f); ret = size; } } } } return ret; }