== [wiki:FUSEDriverExample FUSE(Filesystem in Userspace) driver¿¡ ´ëÇÑ ¿¹Á¦] == * ÀÛ¼ºÀÚ Á¶ÀçÇõ([mailto:minzkn@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ÇϽǼö ÀÖ½À´Ï´Ù. {{{#!plain ./mzfusetest }}} * mountµÈ FUSE entry¸¦ unmonutÇϽ÷Á¸é ´ÙÀ½°ú °°ÀÌ ÇÏ½Ã¸é µË´Ï´Ù. {{{#!plain fusermount -u }}} === ¿¹Á¦¼Ò½º main.c === {{{#!vim c /* Copyright (C) JAEHYUK CHO All rights reserved. Code by JaeHyuk Cho */ #if !defined(FUSE_USE_VERSION) # define FUSE_USE_VERSION 26 #endif #include #include #include #include #include #include #include #include #include #include #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 === {{{#!plain # Copyright (C) JAEHYUK CHO # All rights reserved. # Code by JaeHyuk Cho 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 }}}