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.

Tutorial Linux part 4: Daemon Process

              Daemon process adalah sebuah process yang berjalan di background dan tidak berinteraksi langsung dengan user. Daemon process sendiri dibuat untuk operasi – operasi tertentu atau untuk menangani hal – hal administratif, seperti email, antivirus, firewall, dan lain- lain. Dalam windows, daemon sering disebut System Agents atau Services. Cara membuat daemon memiliki beberapa langkah penting yaitu sebagai berikut.
1.       Forking Parent Process
Untuk membuat sebuah daemon process, awalnya kita harus membuat child process, yang kemudian parent processnya akan dimatikan. Parent process ini akan dimatika atau exit ketika child process berhasil dibuat.

2.       Mengubah Mode File(UMASK)
Untuk menulis atau mengakses file apapun yang dibuat oleh daemon, kita harus mengubah mode file terlebih dahulu dengan fungsi umask. Dengan mengubah umask menjadi 0 maka kita akan memiliki akses penuh pada file yang dibuat oleh daemon.
3.       Membuat Unique Session ID(SID)
Mulai dari sini kita harus membuat Unique Session ID untuk child process yang telah kita buat, jika tidak process tadi akan menjadi orphan process. Sekali lagi, kita lakukan error-checking disini seperti dalam fungsi fork diatas.
4.       Mengubah Direktori yang Bekerja
Direktori yang bekerja harus kita ubah dimana process tersebut akan terus berjalan. Dengan kata lain adalah dalam folder root “/”. Kita gunakan fungsi chdir  disini.

5.       Menutup Standard File Descriptor
Hal terakhir yang paling penting disini adalah menutup File Descriptor untuk memastikan Daemon Process tidak berhubungan dengan User.

6.       Daemon Big Loop
Disinilah kita tulis inti process daemon yang telah kita buat. Atau process utama yang ingin kita lakukan dengan daemon yang kita buat. Kita masukkan process kita dalam while(1).


Demikian sekian tutorial pembuatan Daemon, semoga apa yang saya tulis disini dapat memberi banyak manfaat bagi teman – teman sekalian. Terima kasih.

Tutorial Linux Part 3: Process

                Selamat berjumpa kembali kawan – kawan sekalian, pada kesempatan kali ini saya akan menjelaskan dua hal yang tidak kalah penting dari materi sebelumnya, yaitu process. Process adalah sebuah program atau aplikasi yang sedang dieksekusi di alamat virtual. Process sendiri ada bermacam – macam jenis yaitu :

Tutorial Linux Part 2: Bash Scripting[1], Mencetak dan Membaca input

                Selamat malam teman – teman, jumpa lagi dalam Tutorial Linux yang kedua. Tutorial Linux kali ini akan mengupas hal lebih lanjut yang dapat dilakukan oleh Terminal Linux, yang tidak lain adalah BASH(Bourne-Again-Shell) scripting. Bash script adalah salah satu varian shell yang paling sering digunakan pada Linux. Bash sering digunakan karena fiturnya yang banyak dan portabilitasnya yang tinggi. Nah, untuk awal dari tutorial Bash ini saya akan mengenalkan fitur dasarnya terlebih dahulu. Yaitu membaca input dan mencetak pada terminal. Tapi sebelum itu yang perlu diketahui file bash script disimpan dengan ekstensi “.sh”  , kemudian jika kita ingin menjalankannya kita harus mengubah permissionnya terlebih dahulu yaitu dengan cara “chmod +x [namafile.sh] . Kemudian kita dapat menjalankannya. Berikut cara – caranya :

Tutorial Linux Part 1: Command – Command dasar pada Terminal Linux

Selamat datang dalam tutorial pertama Linux ini. Dalam Linux segala hal terlihat berbeda. Meski terkadang terlihat tidak beda jauh dengan Windows, namun memang semuanya berbeda. Mulai dari lisensi, system file, cara pengembangannya pun berbeda. Terkadang memang untuk sebagian orang awalnya sulit mengoperasikan linux beserta isinya. Oleh karena itu, kali ini saya akan membahas salah satu bagian penting dari linux yaitu “Terminal”. Terminal sepintas terlihat seperti cmd atau command prompt pada Windows. Namun dalam linux, Terminal memiliki peran besar dalam pengoperasiannya.

Berikut beberapa command pada linux beserta fungsinya :
1.       nano
nano adalah command untuk membuat suatu file, entah itu text, script, dan lain – lain. Saat kalian menggunakan command nano, file yang kalian buat akan langsung disimpan di dalam folder root/home.
Format penggunaan perintah nano yang sederhana adalah “nano [namafile.extensifile]. File diatas bernama "baru.txt"
Setelah perintah nano dieksekusi, akan muncul text editor seperti ini
Lalu untuk menyimpannya, tekan Ctrl + X dan Enter.
Untuk membukanya kembali kalian tinggal masukkan nano lagi dengan nama file kalian tadi.
2.       chmod
chmod adalah command untuk mengubah permission dari sebuah file. Perintah ini memiliki beberapa atribut permission sebagai berikut :
Cara penggunaanya pun bermacam - macam, salah satunya jika ingin mengubah permission dari tiga grup, ex :
chmod 777
fungsi diatas berarti kalian mengubah permission dari [User], [Group], dan [World]. Tiga angka 7 mewakili tiga permission tersebut.
3.       Mkdir
mkdir berfungsi untuk membuat folder baru pada direktori saat ini.
Dalam perintah diatas, artinya kita akan membuat folder dengan nama "baru". Format penggunaanya adalah mkdir [namafolder]

4.       Ls
ls berfungsi untuk melihat isi dari direktori saat ini. Contohnya ketika kita memasukkan ls akan muncul tampilan seperti ini
Tulisan - tulisan di bawah perintah tersebut adalah semua file dan folder yang ada pada direktori home(Tidak termasuk subfolder).
5.       Pwd
 pwd berfungsi untuk mencetak alamat dimana user terminal kita sekarang berada. Contohnya sebagai berikut:

Itu artinya kita sedang berada dalam folder /home/reborn/Documents
6.       sudo
sudo berfungsi untuk mengeksekusi suatu perintah dengan Administrator permission. Karena terkadang ada beberapa file ataupun perintah yang hanya dapat dieksekusi sebagai superuser .Kita tinggal menggunakan sudo di depan perintah yang akan kita lakukan. Contoh:
sudo nano /etc/apt/apt.conf
Artinya kita mengedit file apt.conf sebagai Administrator atau superuser

Sekian dulu Tutorial pertama untuk command - command dasar linux. Salah satu yang harus anda perhatikan, semua command dan input dalam terminal adalah case sensitive. Terima kasih