Saturday, November 28, 2015

Save Edited File : FUSE & File System

Istilah Fuse tidak asing untuk beberapa orang. Istilah Fuse sering digunakan di game untuk istilah menggabungkan sesuatu. Namun Fuse yang digunakan pada sistem operasi berbeda. Fuse disini adalah Filesystem in Userspace (FUSE) yang 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.


Cara mengompile & memasang Fuse :
1. pastikan FUSE sudah terinstal di Linux anda. jika belum, bisa di download di http://fuse.sourceforge.net/
cara install :
a. ekstrak hasil download
b. dari terminal masuk ke direktori hasil download nya
c. ketik ./configure, enter
d. ketik make dan enter
e. ketik make install dan enter

Nah, setelah penjelasan diatas muncul lagi istilah File System. File System adalah struktur logika yang digunakan untuk mengendalikan akses terhadap data yang ada pada harddisk. Terdapat berbagai jenis-jenisnya dan penggunaan algoritma yang berbeda. Semakin baru jenis dari sebuah File System, maka semakin bagus pula kualitas dari File System tersebut. 

Ada beberapa tipe dari File System yaitu:

1. File System Disk
2. File System Flash
3. File System Database
4. File System Transaksional
5. File System Jaringan
6. File System untuk Tujuan Khusus
7. File System Journaling

Salah satu yang bisa kita lakukan dengan fuse adalah mengamankan file kita, misal jika kita ingin membuat suatu fuse yang membuat suatu isi dari folder, jika kita edit filenya. Akan ada folder baru yang membuat file hasil editan langsung berpindah ke folder baru tesebut. Dan file aslinya tidak berubah sama sekali. Kemudian kita amankan file didalamnya agar tidak dapat dibukan dan diubah isinya.

Os yang saya gunakan untuk membuatnya adalah Linux Mint, dan Code Blocks(untuk mempermudah pembuatan file c). File C nya berisi:


#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <errno.h>
#include <sys/statfs.h>
#include <sys/types.h>
#include <sys/stat.h>

static const char *dirpath = "/home/yaukings/Downloads/file";

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/yaukings/Downloads/file/simpanan";
    //sprintf(fpath,"%s%s", dirpath, path);
    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;
    int counter=0;
    char fpath[1000];
    char path2[1000];
    char path3[1000];
    sprintf(fpath,"%s%s", dirpath, path);
    sprintf(path2,"%s%s","/home/yaukings/Downloads/file",path);
    int i;
    for(i=0;i<strlen(path);i++)
    {
        if(path[i]=='/')
        {
            counter++;
        }
    }

    if(counter==2)
    {
        sprintf(path3,"%s%s","chmod 444 ",path2);
        system(path3);
        char temp[]="zenity --info --text=\"";
                strcat(temp,"File Tidak Bisa Dibuka");
                strcat(temp,"\"");
                system(temp);
    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/yaukings/Downloads/file/simpanan");
    //system("chmod 777 /home/yaukings/Downloads/file/simpanan");

    char direktori[] = "/home/yaukings/Downloads/file/simpanan";

    //system("zenity --info --text=\"INI ADALAH INFO: \" --title=\"INFO\"");
    sprintf(ffrom,"%s%s",dirpath,from);
    sprintf(fto,"%s%s",direktori,to);
    res = rename(ffrom, fto);

    if(res == -1)
    return -errno;

    return 0;
}
//system("zenity --error --text=\"An error occurred!\" --title=\"Warning!\"");

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

Setelah dibuat file c nya maka jalankan lewat terminal  dengan menggunakan:

gcc -Wall [nama file].c `pkg-config fuse --cflags --libs` -o [nama file]

Sebelum dijalankan buat dulu folder yang akan dijadikan lokasi atau wadah mountingnya bisa lewat buat create folder biasa atau bisa juga menggunakan mkdir  atau jika sudah ada folder kosong sebelumnya gunakan saja folder kosong tersebut. Untuk eksekusinya dapat langsung dengan ./[nama file] [nama folder kosong]. Setelah itu langsung saja dicoba untuk mengedit file didalam lokasi mounting tadi yang biasanya langsung muncul drive baru, dan lihat hasilnya.

Ada cukup banyak istilah/Fungsi baru disini. tapi mungin untuk awalnya "apa yang kita mounting ke folder baru tadi?". jika kita lihat file c di atas maka ada di variabel dirpath.

Pengertian dari Beberapa Istilah/Fungsi:
getattr : agar memungkinkan FUSE dapat mengakses data-data yang unik seperti angka, karakter, array
getdir : untuk mendapatkan alamat asli dari folder yang di FUSE kan
mknod : untuk membuat file baru (berkas). jika fungsi ini hilang, maka di dalam FUSE tersebut kita tidak bisa membuat file baru
mkdir : untuk membuat folder baru
rmdir : untuk menghapus foler
truncate : mengganti alokasi memory untuk setiap file
open : membuka suatu file (seperti jika klik 2 kali menggunakan mouse\enter-button)
read :  untuk menerima dari pengguna yang nantinya disimpan di memory komputer.
write : untuk menuliskan data hasil READ yang telah disimpan di memory, ke file yang sedang dibuka.
rename : mengganti nama dari file/berkas (rename juga digunakan untuk menyimpan / menyimpan hasil perubahan isi berkas)
chmod : mengganti permisi file
chown : mengganti pemilik berkas
symlink : symbolic link

Sekian penjelasan tentang fuse dan salah satu contoh penerapannya, semoga dapat membantu :)


No comments:

Post a Comment