From: Maciej P. <uzy...@gm...> - 2008-11-17 19:20:14
|
Hello. I'm tring to implement a filesystem to read a disk image and split it into partition files - I'm afraid that currently there are no such thing. Unfortunatly I have a problems with opening the file. I tried to open the descriptor and save it in static variable in main (to report error to user). However in calls it turned out to result in 0 (despite the open returned 4). Also in init it didn't worked. What's wrong? Regatds PS. Code /** * MBRFS is a FUSE module designed to low-level access to disk images without * superuser rights required by losetup. * Copyright (C) 2008 Maciej Piechotka * * 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 3 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, see <http://www.gnu.org/licenses/>. **/ #define FUSE_USE_VERSION 26 #include <sys/mman.h> #include <stdio.h> #include <stdint.h> #include <string.h> #include <errno.h> #include <fcntl.h> #include <stddef.h> #include <fuse.h> #include <stdlib.h> /** * Milestone 1: * On this stage the system consist of the following entries: * / - root directory * /<partition_number> - primary partition (normal) * /<partition_number>/ - primary partition (extended) * /<partition_number>/<partition> - extended partition * RO access to directories * RW, non-resizable to files */ struct mbr_partition { uint8_t type; uint32_t offset; uint32_t length; struct mbr_partition *first_sub_partition; struct mbr_partition *next; uint8_t bootable; uint32_t chs_start; uint32_t chs_end; }; static struct mbr_partition partitions[3]; static int disk_fd; struct mbr_options { char *disk; }; static struct mbr_options options; enum { KEY_VERSION, KEY_HELP }; static struct fuse_opt mbr_opts[] = { {"disk=%s", offsetof (struct mbr_options, disk), 0}, FUSE_OPT_KEY("-V", KEY_VERSION), FUSE_OPT_KEY("--version", KEY_VERSION), FUSE_OPT_KEY("-h", KEY_HELP), FUSE_OPT_KEY("--help", KEY_HELP), FUSE_OPT_END }; static struct mbr_partition * mbr_find_partition (const char *path) { char *tmp; char *tok; char *iter; struct mbr_partition *cpar; tmp = strdup (path); iter = strtok_r (tmp, "/", &tok); cpar = partitions; do { int i; sscanf (iter, "%d", &i); while(i != 0 && cpar != NULL) { cpar = cpar->next; i--; } } while ((cpar != NULL) && (iter = strtok_r (NULL, "/", &tok)) && (cpar = cpar->first_sub_partition)); return cpar; } static int mbr_read_entry (int n, uint8_t *mbr) { uint8_t *mbr_entry = mbr + 0x1BE + 0x010*n; partitions[n] = (struct mbr_partition) { .type = mbr_entry[0x04], .offset = *((uint32_t *)(mbr_entry + 0x08)), .length = *((uint32_t *)(mbr_entry + 0x0C)), .first_sub_partition = NULL, .next = (n == 3 ? NULL : &partitions[n + 1]), .bootable = (mbr_entry[0x00] == 0x80), .chs_start = *((uint32_t *)(mbr_entry + 0x01)) & 0x07, .chs_end = *((uint32_t *)(mbr_entry + 0x05)) & 0x07 }; return 0; } static int mbr_read_mbr () { int i; uint8_t *mbr; if ((mbr = mmap (NULL, 512, PROT_READ, MAP_PRIVATE, disk_fd, 0)) == MAP_FAILED) { return -1; } i = 0; while(i < 4) mbr_read_entry (i++, mbr); munmap (mbr, 512); return 0; } /* Implementation */ static void * mbr_init (struct fuse_conn_info *conn) { if ((disk_fd = open (options.disk, O_RDONLY)) == -1) { exit(2); } printf("%d\n", disk_fd); if (mbr_read_mbr()) { exit(2); } return NULL; } static int mbr_getattr (const char *path, struct stat *stbuf) { memset (stbuf, 0, sizeof (struct stat)); if (strcmp (path, "/") == 0) { stbuf->st_mode = S_IFDIR | 0555; stbuf->st_nlink = 2; return 0; } else { struct mbr_partition *cpar; cpar = mbr_find_partition (path); if (cpar != NULL) { if (cpar->first_sub_partition != NULL) { stbuf->st_mode = S_IFDIR | 0555; stbuf->st_nlink = 2; } else { stbuf->st_mode = S_IFREG | 0444; stbuf->st_nlink = 1; stbuf->st_size = (cpar->length * 512); } return 0; } else { return -ENOENT; } } } static int mbr_readdir (const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) { if (strcmp (path, "/") == 0) { int i; filler(buf, ".", NULL, 0); filler(buf, "..", NULL, 0); i = 0; while (i < 4) { if (partitions[i].length != 0) { char part[2]; snprintf (part, 2, "%d", i); filler (buf, part, NULL, 0); } i++; } return 0; } else { return -ENOENT; } } static int mbr_open (const char *path, struct fuse_file_info *fi) { struct mbr_partition *cpar; cpar = mbr_find_partition (path); if (cpar == NULL) { return -ENOENT; } else { return 0; } } static int mbr_read (const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { void *mapped; struct mbr_partition *cpar; cpar = mbr_find_partition (path); if (cpar == NULL) { return -ENOENT; } if (offset > cpar->length) { return 0; } else if (offset + size > cpar->length) { size = cpar->length - offset; } if((mapped = mmap (NULL, size, PROT_READ, MAP_PRIVATE, disk_fd, cpar->offset + offset)) == MAP_FAILED) { return -errno; } memcpy (buf, mapped, size); munmap (mapped, size); return -size; } static struct fuse_operations mbr_oper = { .init = mbr_init, .getattr = mbr_getattr, .readdir = mbr_readdir, .open = mbr_open, .read = mbr_read }; int main (int argc, char *argv[]) { int ret; struct fuse_args args = FUSE_ARGS_INIT (argc, argv); memset(&options, 0, sizeof (struct mbr_options)); if (fuse_opt_parse (&args, &options, mbr_opts, NULL) == -1) return 2; if ((ret = fuse_main (args.argc, args.argv, &mbr_oper, NULL))) printf("\n"); return ret; } -- I've probably left my head... somewhere. Please wait untill I find it. Homepage (pl_PL): http://uzytkownik.jogger.pl/ (GNU/)Linux User: #425935 (see http://counter.li.org/) |