Selamat
datang kembali pada tutorial Linux. Kali ini, saya akan membahas
tentang FUSE yang memliki kepanjang File System User Space. Disini
akan saya tunjukkan bagaimana cara membuat file system sendiri di
Linux dengan menggunakan FUSE. Di bawah ini akan saya tunjukkan
implementasi dasar FUSE pada bahasa C.
#include
<fuse.h>
#include
<stdio.h>
#include
<stdlib.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/user/Documents";
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_readlink(const char *path, char *buf, size_t size)
{
int
res;
char
fpath[1000];
sprintf(fpath,"%s%s",
dirpath, path);
res
= readlink(fpath, buf, size - 1);
if(res
== -1)
return
-errno;
buf[res]
= '\0';
return
0;
}
static
int xmp_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t
filler)
{
char
fpath[1000];
if(strcmp(path,"/")
== 0){ // jika root
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){ // membaca tiap direktori
res
= filler(h, de->d_name, de->d_type);
if(res
!= 0)
break;
}
system("notify-send
Hai_Cintaku");
closedir(dp);
return
res;
}
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_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_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_rmdir(const char *path)
{
int
res;
char
fpath[1000];
sprintf(fpath,"%s%s",
dirpath, path);
res
= rmdir(fpath);
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_rename(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
= rename(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_chmod(const char *path, mode_t mode)
{
int
res;
char
fpath[1000];
sprintf(fpath,"%s%s",
dirpath, 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_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_open(const char *path, int flags)
{
int
res;
char
fpath[1000];
sprintf(fpath,"%s%s",
dirpath, path);
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
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,
};
int
main(int argc, char *argv[])
{
fuse_main(argc,
argv, &xmp_oper);
return
0;
}
Kode
Fuse diatas memiliki semua fungsi – fungsi dari FUSE. Namun jika
kamu ingin tidak membutuh kan beberapa dari fungsi tersebut, kamu
juga bisa menghilangkan beberapa fungsinya. Di bawah ini akan saya
tunjukkan implementasi FUSE yang jika kita meng-copy sebuah file,
maka file yang asli tidak akan bisa dibuka ataupun dicopy lagi. Untuk
membuat file system seperti itu, maka kita dapat memodifikasi fungsi
read dan write nya. Di bawah ini adalah hasil modifikasinya
#ifdef
linux
/*
For pread()/pwrite() */
#define
_XOPEN_SOURCE 500
#endif
#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/fourirakbar/modul4/coba";
char
alamat[1000];
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_readlink(const char *path, char *buf, size_t size)
{
int
res;
char
fpath[1000];
sprintf(fpath,
"%s%s", dirpath, path);
res
= readlink(fpath, buf, size - 1);
if
(res == -1)
return
-errno;
buf[res]
= '\0';
return
0;
}
static
int xmp_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t
filler)
{
DIR
*dp;
struct
dirent *de;
int
res = 0;
char
fpath[1000];
sprintf(fpath,
"%s%s", dirpath, path);
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_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_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_unlink(const char *path) //saat kita melakukan delete
{
int
res,res2;
char
fpath[1000], temp[1000];
sprintf(fpath,
"%s%s", dirpath, path);
strcpy(temp,fpath);
res
= unlink(fpath);
do
{
sprintf(temp, "%s-copy",
fpath); //kita mengecek folder backup nya
res2=unlink(temp);
//jika terdapat folder backup, maka backup tersebut akan
di delete
}
while(res2!=-1);
if(res
== -1)
return
-errno;
return
0;
}
static
int xmp_rmdir(const char *path)
{
int
res;
char
fpath[1000];
sprintf(fpath,
"%s%s", dirpath, path);
res
= rmdir(fpath);
if(res
== -1)
return
-errno;
return
0;
}
static
int xmp_symlink(const char *from, const char *to)
{
int
res;
char
from1[1000];
char
to1[1000];
sprintf(from1,"%s%s",
dirpath, from);
sprintf(to1,"%s%s",
dirpath, to);
res
= symlink(from, to);
if(res
== -1)
return
-errno;
return
0;
}
static
int xmp_rename(const char *from, const char *to)
{
int
res;
char
from1[1000];
char
to1[1000];
sprintf(from1,"%s%s",
dirpath, from);
sprintf(to1,"%s%s.copy",
dirpath, to);
res
= rename(from1, to1);
if
(res == -1)
return
-errno;
return
0;
}
static
int xmp_link(const char *from, const char *to)
{
int
res;
char
from1[1000];
char
to1[1000];
sprintf(from1,"%s%s",
dirpath, from);
sprintf(to1,"%s%s",
dirpath, to);
res
= link(from, to);
if(res
== -1)
return
-errno;
return
0;
}
static
int xmp_chmod(const char *path, mode_t mode)
{
int
res;
char
fpath[1000];
sprintf(fpath,
"%s%s", dirpath, 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_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_open(const char *path, int flags)
{
int
res;
char
fpath[1000];
sprintf(fpath,
"%s%s", dirpath, path);
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);
strcpy(alamat,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)
//saat write file
{
int
fd;
int
res;
int
res1;
char
fpath[1000],temp1[1000];
char
newname[]= "barucopy";
sprintf(fpath,
"%s%s", dirpath, path);
fd
= open(fpath, O_WRONLY);
sprintf(temp1,
"%s%s", dirpath, alamat);
res1
= chmod(temp1, 0000);
if(res1
== -1)
res1
= -errno;
if(fd
== -1)
return
-errno;
res
= pwrite(fd, buf, size, offset);
if(res
== -1)
res
= -errno;
close(fd);
rename(path,newname);
return
res;
}
static
int xmp_release(const char *path, int flags)
{
char
fpath[1000];
sprintf(fpath,
"%s%s", dirpath, path);
(void)
fpath;
(void)
flags;
return
0;
}
static
int xmp_fsync(const char *path, int isdatasync)
{
char
fpath[1000];
sprintf(fpath,
"%s%s", dirpath, path);
(void)
fpath;
(void)
isdatasync;
return
0;
}
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, // delete
.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
};
int
main(int argc, char *argv[])
{
fuse_main(argc,
argv, &xmp_oper);
return
0;
}