Tutorial Linux Part 6: Fuse pada Linux


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;
}

Tutorial Linux Part 5: Thread dan Implementasinya pada Program C

Selamat datang kembali pada tutorial Linux yang ke-5. Kali ini saya akan membahas sesuatu yang bekerja hampir seperti Process yang telah saya jelaskan sebelumnya. Jika hanya dapat dijalankan sebuah process pada satu waktu, maka berbeda dengan thread  yang dapat dijalankan bersama – sama dalam satu waktu. Thread dapat diartikan sebagai bagian – bagian kecil dari process. Karena sifatnya yang dapat berjalan bersama – sama thread dapat banyak kita manfaatkan untuk menjalankan hal – hal yang kita inginkan dengan lebih mudah. Cara penggunaan thread dibagi menjadi dua, yaitu :

Single Threading
                Sebuah process  yang hanya memliki satu buah thread  di dalamnya. Biasanya hal ini digunakan sebagai pengendali jalannya process.