Filesystem in Userspace (FUSE) merupakan mekanisme sistem operasi untuk sistem operasi Unix-like yang memungkinkan pengguna tidak ber-hak istimewa menciptakan file system mereka sendiri tanpa mengubah kode kernel. Hal ini dicapai dengan menjalankan kode file system di userspace, sedangkan modul FUSE hanya menyediakan "jembatan" untuk antarmuka kernel yang sebenarnya.
Diagram cara kerja FUSE |
Module kernel FUSE dan FUSE library berhubungan melalui sebuah special file descriptor yang didapatkan dengan membuka /dev/fuse. FUSE kernal module meneruskan request ke aplikasi fuse anda. aplikasi anda memerintahkan fuse cara menjawab request. FUSE kernal module dan FUSE library berkomunikasi lewat file deskriptor spesial yang diperoleh dengan membuka /dev/fuse. file ini dapat terbuka berkali-kali dan file deskriptor yang diperoleh diteruskan ke mount syscall, untuk menyesuaikan deskriptor dengan filesystem mount.
Installasi FUSE:
- Download FUSE dari http://fuse.sourceforge.net/ pada bagian Download stable release
- Extract file tar.gz dan masuk ke direktori FUSE. (tar –xvzf fuse-2.9.4.tar.gz)
- Lakukan installasi FUSE dengan cara :
- Gunakan hak akses super user (sudo su)
- Ketikkan perintah ./configure
- Ketikkan perintah make
- Ketikkan perintah make install
- FUSE siap digunakan
Membuat file system sendiri menggunakan FUSE :
#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <errno.h>
#include <sys/statfs.h>
static const char *dirpath = "/home/[nama user kalian]/[path bebas]";
static int xmp_getattr(const char *path, struct stat *stbuf) {
int res;
char fpath[1000];
sprintf(fpath,"%s%s",dirpath,path);
res = lstat(fpath, stbuf);
if(res == -1) return -errno;
return 0;
}
static int xmp_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t filler) {
char fpath[1000];
if(strcmp(path,"/") == 0) {
path=dirpath;
sprintf(fpath,"%s",path);
}
else sprintf(fpath, "%s%s",dirpath,path);
int res = 0;
DIR *dp;
struct dirent *de;
dp = opendir(fpath);
if(dp==NULL) return -errno;
while((de = readdir(dp))!=NULL) {
res = filler(h, de->d_name, de->d_type);
if(res!=0) break;
}
closedir(dp);
return res;
}
static struct fuse_operations xmp_oper = {
.getattr = xmp_getattr,
//.readlink = xmp_readlink,
.getdir = xmp_getdir,
//.mknod = xmp_mknod,
//.mkdir = xmp_mkdir,
//.symlink = xmp_symlink,
//.unlink = xmp_unlink,
//.rmdir = xmp_rmdir,
//.rename = xmp_rename,
//.link = xmp_link,
//.chmod = xmp_chmod,
//.chown = xmp_chown,
//.truncate = xmp_truncate,
//.utime = xmp_utime,
//.open = xmp_open,
//.read = xmp_read,
//.write = xmp_write,
//.release = xmp_release,
//.fsync = xmp_fsync,
//.readdir = hello_readdir
};
int main(int argc, char *argv[]) {
return fuse_main(argc, argv, &xmp_oper);
}
Simpan kemudian compile dengan menggunakan perintah: gcc -Wall [nama file].c `pkg-config fuse --cflags --libs` -o [nama file]
Kemudian buat sebuah direktori, misalnya: /tmp/fuse
Coba jalankan fuse tadi dengan cara: ./[nama file] /tmp/fuse
Maka semua isi direktori /home/[nama user kalian]/[path bebas] akan dimount ke direktori /tmp/fuse
Untuk Fuse ini, kita hanya bermain dalam fungsi - fungsi mana yang akan kita gunakan (cek static struct fuse_operations xmp_oper). Berikut beberapa fungsi dalam fuse :
static int xmp_getattr(const char *path, struct stat *stbuf) {
int res;
char fpath[1000];
sprintf(fpath,"%s%s",dirpath,path);
res = lstat(fpath, stbuf);
if(res == -1) return -errno;
return 0;
}
static int xmp_chmod(const char *path, mode_t mode) {
int res;
char fpath[1000];
char direktori[] = "/home/[nama user kalian]/[path bebas]";
sprintf(fpath,"%s%s", direktori, path);
res = chmod(fpath, mode);
if(res == -1) return -errno;
return 0;
}
static int xmp_chown(const char *path, uid_t uid, gid_t gid) {
int res;
char fpath[1000];
sprintf(fpath,"%s%s", dirpath, path);
res = lchown(fpath, uid, gid);
if(res == -1) return -errno;
return 0;
}
static int xmp_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t filler) {
char fpath[1000];
if(strcmp(path,"/") == 0) {
path=dirpath;
sprintf(fpath,"%s",path);
}
else sprintf(fpath, "%s%s",dirpath,path);
int res = 0;
DIR *dp;
struct dirent *de;
dp = opendir(fpath);
if(dp==NULL) return -errno;
while((de = readdir(dp))!=NULL) {
res = filler(h, de->d_name, de->d_type);
if(res!=0) break;
}
closedir(dp);
return res;
}
static int xmp_mkdir(const char *path,mode_t mode) {
int res;
char fpath[1000];
sprintf(fpath,"%s%s",dirpath,path);
res = mkdir (fpath,mode);
if(res == -1)
return -errno;
return 0;
}
static int xmp_symlink(const char *from, const char *to) {
int res;
char ffrom[1000];
char fto[1000];
sprintf(ffrom,"%s%s",dirpath,from);
sprintf(fto,"%s%s",dirpath,to);
res = symlink(ffrom, fto);
if(res == -1) return -errno;
return 0;
}
static int xmp_link(const char *from, const char *to) {
int res;
char ffrom[1000];
char fto[1000];
sprintf(ffrom,"%s%s",dirpath,from);
sprintf(fto,"%s%s",dirpath,to);
res = link(ffrom, fto);
if(res == -1)
return -errno;
return 0;
}
static int xmp_unlink(const char *path) {
int res;
char fpath[1000];
sprintf(fpath,"%s%s", dirpath, path);
res = unlink(fpath);
if(res == -1) return -errno;
return 0;
}
static int xmp_truncate(const char *path, off_t size) {
int res;
char fpath[1000];
sprintf(fpath,"%s%s", dirpath, path);
res = truncate(fpath, size);
if(res == -1) return -errno;
return 0;
}
static int xmp_utime(const char *path, struct utimbuf *buf) {
int res;
char fpath[1000];
sprintf(fpath,"%s%s", dirpath, path);
res = utime(fpath, buf);
if(res == -1) return -errno;
return 0;
}
static int xmp_mknod(const char *path, mode_t mode, dev_t rdev) {
int res;
char fpath[1000];
sprintf(fpath,"%s%s", dirpath, path);
res = mknod(fpath, mode, rdev);
if(res == -1)
return -errno;
return 0;
}
static int xmp_open(const char *path, int flags) {
int res;
char fpath[1000];
sprintf(fpath,"%s%s", dirpath, path);
if(strcmp(fpath,"/home/[nama user kalian]")==0) {
system("zenity --error --text=\"An error occurred!\" --title=\"Warning!\"");
res = open(fpath, flags);
if(res == -1)
return -errno;
close(res);
}
return 0;
}
static int xmp_read(const char *path, char *buf, size_t size, off_t offset) {
int fd;
int res;
char fpath[1000];
sprintf(fpath,"%s%s", dirpath, path);
fd = open(fpath, O_RDONLY);
if(fd == -1) return -errno;
res = pread(fd, buf, size, offset);
if(res == -1) res = -errno;
close(fd);
return res;
}
static int xmp_write(const char *path, const char *buf, size_t size,off_t offset) {
int fd;
int res;
char fpath[1000];
sprintf(fpath,"%s%s", dirpath, path);
fd = open(fpath, O_WRONLY);
if(fd == -1) return -errno;
res = pwrite(fd, buf, size, offset);
if(res == -1) res = -errno;
close(fd);
return res;
}
static int xmp_rename(const char *from, const char *to) {
int res;
char ffrom[1000];
char fto[1000];
system("mkdir /home/[nama user kalian]/[path bebas]");
system("chmod 777 [path bebas]");
char direktori[] = "/home/[nama user kalian]/[path bebas]";
sprintf(ffrom,"%s%s",dirpath,from);
sprintf(fto,"%s%s",direktori,to);
res = rename(ffrom, fto);
if(res == -1) return -errno;
return 0;
}