· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
FUSE Driver Example

FUSE(Filesystem in Userspace) driver¿¡ ´ëÇÑ ¿¹Á¦

  • ÀÛ¼ºÀÚ
    Á¶ÀçÇõ(Mminzkn@minzkn.com)

  • °íÄ£°úÁ¤
    2010³â 9¿ù 16ÀÏ : óÀ½¾¸

  • ¹®¼­ÀÇ ÀÛ¼º±âÁØ °³¹ßȯ°æ
    GNU/Linux

¼³¸í

  • ÀÌ°ÍÀº ¸®´ª½ºÈ¯°æ¿¡¼­ÀÇ FUSE(Filesystem in Userspace)¿¡ ´ëÇÑ ±¸Ã¼ÀûÀÎ ¿¹Á¦¸¦ ÀÛ¼ºÇغ»°ÍÀÔ´Ï´Ù. FUSE´Â ¼³¸íÀÌ ÇÊ¿ä¾øÀ»Á¤µµ·Î ¸Å¿ì °£°áÇÏ°Ô ¸¸µé¼ö À־ ¿¹Á¦¸¸À¸·Î ÃæºÐÇÑ ¼³¸íÀÌ µÇ´Âµí ÇÕ´Ï´Ù.
  • ÀÌ ¿¹Á¦¼Ò½ºÀÇ ÃÖ±Ù ¹öÁ¯Àº "svn://svn.hwport.com/extra/mzfusetest" À¸·Î checkout ¹ÞÀ¸½Ç¼ö ÀÖ½À´Ï´Ù.
  • Á»´õ ¼¼¹ÐÇÑ ¿¹Á¦´Â ""svn://svn.hwport.com/extra/mzfilesystem" À¸·Î checkout ¹ÞÀ¸½Ç¼ö ÀÖ½À´Ï´Ù.
  • ºôµåÈÄ ´ÙÀ½°ú °°ÀÌ ½ÇÇàÇϽøé mountÇϽǼö ÀÖ½À´Ï´Ù.
    ./mzfusetest <mount entry>
    
  • mountµÈ FUSE entry¸¦ unmonutÇϽ÷Á¸é ´ÙÀ½°ú °°ÀÌ ÇÏ½Ã¸é µË´Ï´Ù.
    fusermount -u <mount entry>
    

¿¹Á¦¼Ò½º main.c

/*
  Copyright (C) JAEHYUK CHO
  All rights reserved.
  Code by JaeHyuk Cho <mailto:minzkn@minzkn.com>
*/

#if !defined(FUSE_USE_VERSION)
# define FUSE_USE_VERSION 26
#endif

#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

#include <fuse.h>

#if !defined(mzfuse_virtual_filesystem_t)
typedef struct mzfuse_virtual_filesystem_ts {
    const char *m_pathname;
    const unsigned char *m_data;
}__mzfuse_virtual_filesystem_t;
# define mzfuse_virtual_filesystem_t __mzfuse_virtual_filesystem_t
#endif

int main(int s_argc, char **s_argv);

static int mzfuse_getattr(const char *s_pathname, struct stat *s_statbuffer);
static int mzfuse_open(const char *s_pathname, struct fuse_file_info *s_fileinfo);
static int mzfuse_read(const char *s_pathname, char *s_data, size_t s_size, off_t s_offset, struct fuse_file_info *s_fileinfo);
static int mzfuse_readdir(const char *s_pathname, void *s_buffer, fuse_fill_dir_t s_filler, off_t s_offset, struct fuse_file_info *s_fileinfo);

static mzfuse_virtual_filesystem_t g_mzfuse_virtual_filesystem[] = {
    {"/.", (const unsigned char *)0},
    {"/..", (const unsigned char *)0},
    {"/TEST FILE 00", (const unsigned char *)"VIRTUAL DATA 00"},
    {"/TEST FILE 01", (const unsigned char *)"VIRTUAL DATA 01"},
    {"/TEST FILE 02", (const unsigned char *)"VIRTUAL DATA 02"},
    {"/TEST FILE 03", (const unsigned char *)"VIRTUAL DATA 03"},
    {(const char *)0, (const unsigned char *)0}
};

static struct fuse_operations g_mzfuse_operations = {
    /* int (*getattr) (const char *, struct stat *); */
    .getattr = mzfuse_getattr,
    /* int (*readlink) (const char *, char *, size_t); */
    /* int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t); */
    /* int (*mknod) (const char *, mode_t, dev_t); */
    /* int (*mkdir) (const char *, mode_t); */
    /* int (*unlink) (const char *); */
    /* int (*rmdir) (const char *); */
    /* int (*symlink) (const char *, const char *); */
    /* int (*rename) (const char *, const char *); */
    /* int (*link) (const char *, const char *); */
    /* int (*chmod) (const char *, mode_t); */
    /* int (*chown) (const char *, uid_t, gid_t); */
    /* int (*truncate) (const char *, off_t); */
    /* int (*utime) (const char *, struct utimbuf *); */
    /* int (*open) (const char *, struct fuse_file_info *); */
    .open = mzfuse_open,
    /* int (*read) (const char *, char *, size_t, off_t, struct fuse_file_info *); */
    .read = mzfuse_read,
    /* int (*write) (const char *, const char *, size_t, off_t, struct fuse_file_info *); */
    /* int (*statfs) (const char *, struct statvfs *); */
    /* int (*flush) (const char *, struct fuse_file_info *); */
    /* int (*release) (const char *, struct fuse_file_info *); */
    /* int (*fsync) (const char *, int, struct fuse_file_info *); */
    /* int (*setxattr) (const char *, const char *, const char *, size_t, int); */
    /* int (*getxattr) (const char *, const char *, char *, size_t); */
    /* int (*listxattr) (const char *, char *, size_t); */
    /* int (*removexattr) (const char *, const char *); */
    /* int (*opendir) (const char *, struct fuse_file_info *); */
    /* int (*readdir) (const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *); */
    .readdir = mzfuse_readdir,
    /* int (*releasedir) (const char *, struct fuse_file_info *); */
    /* int (*fsyncdir) (const char *, int, struct fuse_file_info *); */
    /* void *(*init) (struct fuse_conn_info *conn); */
    /* void (*destroy) (void *); */
    /* int (*access) (const char *, int); */
    /* int (*create) (const char *, mode_t, struct fuse_file_info *); */
    /* int (*ftruncate) (const char *, off_t, struct fuse_file_info *); */
    /* int (*fgetattr) (const char *, struct stat *, struct fuse_file_info *); */
    /* int (*lock) (const char *, struct fuse_file_info *, int cmd, struct flock *); */
    /* int (*utimens) (const char *, const struct timespec tv[2]); */
    /* int (*bmap) (const char *, size_t blocksize, uint64_t *idx); */
    /* unsigned int flag_nullpath_ok : 1; */
    /* unsigned int flag_reserved : 31; */
    /* int (*ioctl) (const char *, int cmd, void *arg, struct fuse_file_info *, unsigned int flags, void *data); */
    /* int (*poll) (const char *, struct fuse_file_info *, struct fuse_pollhandle *ph, unsigned *reventsp); */
};

static int mzfuse_getattr(const char *s_pathname, struct stat *s_statbuffer)
{
    int s_index = 0;

    (void)memset((void *)s_statbuffer, 0, sizeof(struct stat));

    if(strcmp(s_pathname, "/") == 0) {
        s_statbuffer->st_mode = S_IFDIR | 0755;
        s_statbuffer->st_nlink = 2;

        return(0);
    }

    while(g_mzfuse_virtual_filesystem[s_index].m_pathname != ((const char *)0)) {
        if(strcmp(s_pathname, g_mzfuse_virtual_filesystem[s_index].m_pathname) == 0) {
            break;
        }
        ++s_index;
    }

    if(g_mzfuse_virtual_filesystem[s_index].m_pathname == ((const char *)0)) {
        return(-ENOENT);
    }

    s_statbuffer->st_mode = S_IFREG | 0444;
    s_statbuffer->st_nlink = 1;
    s_statbuffer->st_size = strlen("TEST DATA");

    return(0);
}

static int mzfuse_open(const char *s_pathname, struct fuse_file_info *s_fileinfo)
{
    int s_index = 0;

    while(g_mzfuse_virtual_filesystem[s_index].m_pathname != ((const char *)0)) {
        if(strcmp(s_pathname, g_mzfuse_virtual_filesystem[s_index].m_pathname) == 0) {
            break;
        }
        ++s_index;
    }

    if(g_mzfuse_virtual_filesystem[s_index].m_pathname == ((const char *)0)) {
        return(-ENOENT);
    }

    if((s_fileinfo->flags & O_RDONLY) != O_RDONLY) {
        return(-EACCES);
    }

    return(0);
}

static int mzfuse_read(const char *s_pathname, char *s_data, size_t s_size, off_t s_offset, struct fuse_file_info *s_fileinfo)
{
    off_t s_result;
    int s_index = 0;

    while(g_mzfuse_virtual_filesystem[s_index].m_pathname != ((const char *)0)) {
        if(strcmp(s_pathname, g_mzfuse_virtual_filesystem[s_index].m_pathname) == 0) {
            break;
        }
        ++s_index;
    }

    if(g_mzfuse_virtual_filesystem[s_index].m_pathname == ((const char *)0)) {
        return(-ENOENT);
    }

    s_result = strlen((const char *)g_mzfuse_virtual_filesystem[s_index].m_data);
    if(s_offset >= s_result) {
        return(0);
    }

    if(s_result < (s_offset + ((off_t)s_size))) {
        s_size = (size_t)(s_result - s_offset);
    }

    (void)memcpy((void *)s_data, (const void *)(&g_mzfuse_virtual_filesystem[s_index].m_data[s_offset]), s_size);

    return(s_result);
}

static int mzfuse_readdir(const char *s_pathname, void *s_buffer, fuse_fill_dir_t s_filler, off_t s_offset, struct fuse_file_info *s_fileinfo)
{
    int s_index = 0;

    if(strcmp(s_pathname, "/") != 0) {
        return(-ENOENT);
    }

    while(g_mzfuse_virtual_filesystem[s_index].m_pathname != ((const char *)0)) {
        /* typedef int (*fuse_fill_dir_t) (void *buf, const char *name, const struct stat *stbuf, off_t off); */
        s_filler(s_buffer, (const char *)(&g_mzfuse_virtual_filesystem[s_index].m_pathname[1]), (const struct stat *)0, (off_t)0);

        ++s_index;
    }

    return(0);
}

int main(int s_argc, char **s_argv)
{
    /* int fuse_main(int argc, char *argv[], const struct fuse_operations *op, void *user_data); */
    return(fuse_main(s_argc, s_argv, (const struct fuse_operations *)(&g_mzfuse_operations), (void *)0));
}

/* End of source */

makefile

# Copyright (C) JAEHYUK CHO
# All rights reserved.
# Code by JaeHyuk Cho <mailto:minzkn@minzkn.com>

CROSS_COMPILE                ?=#

CC                           := $(CROSS_COMPILE)gcc#
RM                           := rm -f#
STRIP                        := $(CROSS_COMPILE)strip#

THIS_NAME                    := mzfusetest#

CFLAGS                       := -Os -pipe#
CFLAGS                       += -Wall -Werror#
CFLAGS                       += -fomit-frame-pointer#
#CFLAGS                       += -ansi#
CFLAGS                       += -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64#
CFLAGS                       += -I.#

LDFLAGS                      := -s -lfuse#

TARGET                       := $(THIS_NAME)#
#OBJECTS                      := $(THIS_NAME).o#
OBJECTS                      := main.o#

.PHONY: all clean

all: $(TARGET) ; $(STRIP) --remove-section=.comment --remove-section=.note $(TARGET)
clean: ; $(RM) *.o $(TARGET)

$(TARGET): $(OBJECTS) ; $(CC) $(LDFLAGS) -o $(@) $(^)
$(OBJECTS): makefile
%.o: %.c ; $(CC) $(CFLAGS) -c -o $(@) $(<)

# End of Makefile

ID
Password
Join
You will be singled out for promotion in your work.


sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2012-01-19 12:05:21
Processing time 0.0056 sec