chown ve fchown Fonksiyonu
#include <unistd.h>
int chown(const char *path, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group);
int lchown(const char *path, uid_t owner, gid_t group);
Chown fonksiyonu bir dosyanin sahiplik bilgilerini
degistirir. Fonksiyonun prototipi yukaridaki gibidir.
Fonksiyonunlarin birinci parametresi ilfili dosyanin yol
ifadesi yada dosya betimleyicisidir. Ikinci parametresi dosyanin yeni sahibinin
id'sini, ucuncu parametre de dosyanin yeni grubunun id'sini alir. Ancak root
processi bis dosyanin sahiplik bilgisini degistirebilir. Dosyanin sahibinin
sahiplik bilgisini yada grup bilgisini degistirebilmesi bazi unix turevi
sistemlede mumkundur. Bazilarinda ise degildir. POSIX bunu isletim sisteminin
istegine birakmistir. Linux'da default durumda dosyanin sahibi sahipligini
baska birisine devredemez. Fakat genel olarak dosyanin sahibi dosyanin grubunu
degistirmektedir. Ancak dosyanin sahibi dosyanin grubunu POSIX standartlarina
gore herhangi bir grup olarak degistiremez. Kendi etkin grupid'si olarak yada
ek gruplarindan biri olarak degistirebilir.
POSIX Standartlarinda degisik baslik dosyalarinda xxx_t biciminde
typedef edilmis bazi tur isimleri vardir. BU turlerin gercekte hangi tur olarak
typedef edilecegibazi kosullar altinda isletim sistemini yazanlara
birakilmistir. Bunlarin hepsi ayrica bir grup olarak /sys/types.h dosyasi
icinde tanimlanmistir. Tipik xxx_t turleri sunlardir:
-> mode_t, nlink_t, uid_t, gid_t, id_t bir tamsayi olarak typedef edilmek zorundadir.
-> blksize_t, pid_t, ssize_t, blkcnt_t ve off_t isaretli tamsayi olacak bicimde typedef edilmek zorundadir.
-> size_t isaretsiz bir tamsayi turu olarak typedef edilmek zorundadir.
-> time_t ve clock_t tam sayi yada gercek sayio turunden typedef edilmek zorundadir.
-> mode_t, nlink_t, uid_t, gid_t, id_t bir tamsayi olarak typedef edilmek zorundadir.
-> blksize_t, pid_t, ssize_t, blkcnt_t ve off_t isaretli tamsayi olacak bicimde typedef edilmek zorundadir.
-> size_t isaretsiz bir tamsayi turu olarak typedef edilmek zorundadir.
-> time_t ve clock_t tam sayi yada gercek sayio turunden typedef edilmek zorundadir.
stat ve fstat fonksiyonlari
Fonksiyonun prototipi su sekildedir.
#include <sys/stat.h>
int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
Fonksiyonlarin birinci parametreleri bilgisi elde edilecek
olan dosyani yol ifadesini yada betimleyicisini almaktadir. ikinci
parametre sys/types.h dosyasinda bildirilmis olan stat isimli bir yapi turunden
nesnenin adresini alir. Fonksiyon basari durumunda 0 basarisizlik durumunda -1
degerine geri doner.
Stat yapisinin icerisinde su bilgiler vardir.
- Dosyanin
icinde bulundugu aygitin aygit numarasi.
- Dosyanin
inode numarasi
- Dosyanin
erisim bilgileri
- Dosyanin
userid ve groupid bilgileri
- Dosyanin
uzunlugu
- Dosyani
son erisim, son degistirilme, son statu degisimine iliskin tarih ve zaman
bilgisi
- Kopyalama
gibi islemlerdeki etkin tampon buyuklugu
- Bu
dosya icin kac disk blogu tahsis edildigi
Bir dosyanin kac bloktan olustugu bilgisi belirtilirken
bir blogun kac byte uzunlugunda oldugu sistemden sisteme degisebilmektedir.
Block kavrami Linux sistemlerde biraz lastik hale getirilmistir. Stat
fonksiyonunda ise block 512 byei temsil eder,. Halbulki baska yarlerde de
bloack terimi kullanilmaktadir ve baska uzunlugu gostermektedir. Sonuc olarak
linux sistemiinde block terinide karsilasildiginda, o baglamda blogun kac byte
dan olustugu bilgisini de edinmek gerekmektedir.
/*-----------------------------------------------------------------------------------
stat fonksiyonu
------------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
void exitsys(const char *msg);
int main(int argc, char *argv[])
{
struct stat finfo;
struct passwd *pwd;
struct group *grp;
struct tm *ftime;
if (argc != 2) {
fprintf(stderr, "cannot get stat info\n");
exit(EXIT_FAILURE);
}
if (stat(argv[1], &finfo)
< 0)
exitsys("stat");
if ((pwd =
getpwuid(finfo.st_uid)) == NULL)
exitsys("getpwuid");
if ((grp =
getgrgid(finfo.st_gid)) == NULL)
exitsys("getgrgid");
printf("%s\n", argv[1]);
printf("User:
%s(%lu)\n", pwd->pw_name, (unsigned long) finfo.st_uid);
printf("Group:
%s(%lu)\n", grp->gr_name, (unsigned long) finfo.st_gid);
printf("Length:
%lu\n", (unsigned long) finfo.st_size);
ftime =
localtime(&finfo.st_atime);
printf("Access
time: %02d/%02d/%04d %02d:%02d:%02d\n", ftime->tm_mday,
ftime->tm_mon + 1, ftime->tm_year + 1900,ftime->tm_hour,
ftime->tm_min, ftime->tm_sec);
ftime =
localtime(&finfo.st_mtime);
printf("Modification time: %02d/%02d/%04d
%02d:%02d:%02d\n", ftime->tm_mday,
ftime->tm_mon
+ 1, ftime->tm_year + 1900,
ftime->tm_hour,
ftime->tm_min, ftime->tm_sec);
ftime =
localtime(&finfo.st_ctime);
printf("Status
time: %02d/%02d/%04d %02d:%02d:%02d\n", ftime->tm_mday,
ftime->tm_mon
+ 1, ftime->tm_year + 1900,
ftime->tm_hour,
ftime->tm_min, ftime->tm_sec);
return 0;
}
void exitsys(const char *msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
/etc/passwd ve /etc/group dosyalarinin formatlari sistemden
sisteme farkli olacilir/ Bilindigi gibi sistemler icsel olarak hep sayilarla
calisirlar. Ornegin stat fonksiyonundan elde etmis oldugumuz userid ve groupid
degerleri sayisal degerlerdir. Bunlari ancak biz /etc/passwd ve /etc/group
dosyalarina bakarak isme donusturebiliriz. Iste bu isi yapan birkac posix
fonksiyonu bulundurulmustur.
getpwuid ve getgrgid fonksiyonlari parametre olarak bizden
userid ve groupid degerini alir. ve bize passwd ve group isimli yapi adresi ile
geri doner. Bu yapilar, /tec/passwd ve /etc/group dosyalarindaki satirlari
temsil etmektedir. tipik olarak bu fonksiyonlar sayisal userid ve gruopid
degerlerini user ve group isimlerine donusturmek icin kullanilir. Bu islemin
tersini yapan yani isimlerden sayi elde edilmesini saglayan getpwnam ve
getgrnam fonksiyonlari vardi
geri donus degeri pointer olan fonksiyonlarda hata
durrumunda geri donus -1 degil NULL pointerdir. Fonksiyon geri donusunu kontrol
etmek icin NULL olup olmadigina bakmamiz omenlidir.
Stat fonksiyonu ile verilen tarihler bize 1.1.1970
tarihinden gecen saniye sayisi olarak verilmektedir. Stat yapisinin
icerisinde erisim haklari st_mode icerisine bit bit kodlanmistir. Buradan
dosyanin turunu almak icin s_isxxx biciminde makrolar bulundurulmustur. ayrica
ilgili hakkin olup olmadigini anlamak icin daha once gorulmus olan S_IXXXX
sembolik sabitleri ile bit end islem olusturmak gerekir.
/*------------------------------------------------------------------------------------
dosya bilgilerinin ls
-l tarzýnda elde edilmesi
-------------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
void exitsys(const char *msg);
char *getls(const char *path, const struct stat *finfo);
int main(int argc, char *argv[])
{
struct stat finfo;
if (argc != 2) {
fprintf(stderr, "cannot get stat info\n");
exit(EXIT_FAILURE);
}
if (stat(argv[1],
&finfo) < 0)
exitsys("stat");
puts(getls(argv[1],
&finfo));
return 0;
}
char *getls(const char *path, const struct stat *finfo)
{
char static
buf[4096];
int index;
int i;
int aflags[] =
{S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP,
S_IROTH,
S_IWOTH, S_IXOTH};
char *rights =
"rwx";
struct passwd *pwd;
struct group *grp;
char *months[] =
{"Oca", "Þub", "Mar", "Nis",
"May", "Haz", "Tem", "Aðu",
"Eyl", "Eki",
"Kas",
"Ara"};
struct tm *ftime;
index = 0;
if
(S_ISREG(finfo->st_mode))
buf[index] = '-';
else if (S_ISDIR(finfo->st_mode))
buf[index] = 'd';
else if
(S_ISCHR(finfo->st_mode))
buf[index] = 'c';
else if
(S_ISBLK(finfo->st_mode))
buf[index] = 'b';
else if
(S_ISFIFO(finfo->st_mode))
buf[index] = 'p';
else if
(S_ISLNK(finfo->st_mode))
buf[index] = 'l';
else if
(S_ISSOCK(finfo->st_mode))
buf[index] = 's';
++index;
for (i = 0; i < 9;
++i)
buf[index++] = (finfo->st_mode & aflags[i]) ?
rights[i % 3] : '-';
buf[index++] = ' ';
index +=
sprintf(&buf[index], "%lu", (unsigned long) finfo->st_nlink);
buf[index++] = ' ';
if ((pwd =
getpwuid(finfo->st_uid)) == NULL)
index += sprintf(&buf[index], "%lu",
(unsigned long) finfo->st_uid);
else
index += sprintf(&buf[index], "%s",
pwd->pw_name);
buf[index++] = ' ';
if ((grp =
getgrgid(finfo->st_gid)) == NULL)
index += sprintf(&buf[index], "%lu",
(unsigned long) finfo->st_gid);
else
index += sprintf(&buf[index], "%s",
grp->gr_name);
buf[index++] = ' ';
index +=
sprintf(&buf[index], "%ld", (long) finfo->st_size);
buf[index++] = ' ';
ftime =
localtime(&finfo->st_mtime);
index +=
sprintf(&buf[index], "%s %d %02d:%02d %s",
months[ftime->tm_mon],
ftime->tm_mday,ftime->tm_hour,
ftime->tm_min, path);
buf[index] = '\0';
return buf;
}
void exitsys(const char *msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
Dizin icindeki dosyalarin ele gecirilmesi
Bir dizin icerisindeki dosyalarin elde edilmesi su sekilde
yapilir.
Dizin opendir fonksiyonu ile acilir. Fonksiyon basari
durumunda DIR isimli bir yapi turunden handle gorevi yapa bir adres
verir.basarisizlik durumunde NULL adres verir.
#include <dirent.h>
DIR *opendir(const char *name);
DIR *fdopendir(int fd);
Readdir isimli fonksiyon her cagirildiginda bize siradaki
dosyanin isminin ve inode numarasinin bulundugu dirent isimli bir yapinn
adresini verir. Dizinin sonuna gelindiginde fonksiyon NULL adres verir.
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
Nihayet acilmis olan dizin closedir fonksiyonu ile
kapatilir.
#include <dirent.h>
int closedir(DIR *dirp);
bir onceki konuda yapilan ls komutu ornegini dizindeki
dosyalar icin yapilandiralim
/*---------------------------------------------------------------------------------
Dizin içerisindeki
dosyalarýn elde edilmesi
----------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
#include <dirent.h>
void exitsys(const char *msg);
char *getls(const char *path);
int main(int argc, char *argv[])
{
struct stat finfo;
DIR *dir;
struct dirent *dire;
char path[1024];
if (argc != 2) {
fprintf(stderr, "wrong number of
arguments\n");
exit(EXIT_FAILURE);
}
if ((dir =
opendir(argv[1])) == NULL)
exitsys("opendir");
while ((dire =
readdir(dir)) != NULL) {
sprintf(path, "%s/%s", argv[1],
dire->d_name);
printf("%s\n", getls(path));
}
closedir(dir);
return 0;
}
char *getls(const char *path)
{
char static
buf[4096];
struct stat finfo;
int index;
int i;
int aflags[] =
{S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IWGRP,
S_IXGRP,
S_IROTH, S_IWOTH, S_IXOTH};
char *rights =
"rwx";
struct passwd *pwd;
struct group *grp;
char *months[] =
{"Oca", "Þub", "Mar", "Nis",
"May", "Haz",
"Tem",
"Aðu", "Eyl", "Eki", "Kas", "Ara"};
struct tm *ftime;
char *fname;
if (stat(path,
&finfo) < 0)
return NULL;
if ((fname =
strrchr(path, '/')) == NULL)
return NULL;
index = 0;
if
(S_ISREG(finfo.st_mode))
buf[index] = '-';
else if
(S_ISDIR(finfo.st_mode))
buf[index] = 'd';
else if
(S_ISCHR(finfo.st_mode))
buf[index] = 'c';
else if (S_ISBLK(finfo.st_mode))
buf[index] = 'b';
else if
(S_ISFIFO(finfo.st_mode))
buf[index] = 'p';
else if
(S_ISLNK(finfo.st_mode))
buf[index] = 'l';
else if
(S_ISSOCK(finfo.st_mode))
buf[index] = 's';
++index;
for (i = 0; i < 9;
++i)
buf[index++] = (finfo.st_mode & aflags[i]) ?
rights[i % 3] : '-';
buf[index++] = ' ';
index +=
sprintf(&buf[index], "%lu", (unsigned long) finfo.st_nlink);
buf[index++] = ' ';
if ((pwd =
getpwuid(finfo.st_uid)) == NULL)
index += sprintf(&buf[index], "%lu",
(unsigned long) finfo.st_uid);
else
index += sprintf(&buf[index], "%s",
pwd->pw_name);
buf[index++] = ' ';
if ((grp =
getgrgid(finfo.st_gid)) == NULL)
index += sprintf(&buf[index], "%lu",
(unsigned long) finfo.st_gid);
else
index += sprintf(&buf[index], "%s",
grp->gr_name);
buf[index++] = ' ';
index +=
sprintf(&buf[index], "%ld", (long) finfo.st_size);
buf[index++] = ' ';
ftime =
localtime(&finfo.st_mtime);
index +=
sprintf(&buf[index], "%s %d %02d:%02d %s", months[ftime->tm_mon],
ftime->tm_mday,
ftime->tm_hour,
ftime->tm_min, fname + 1);
buf[index] = '\0';
return buf;
}
void exitsys(const char *msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
Recursive olarak bir dizin icindeki bilgilerin elde
edilmesi
Dizin agacini dolasabilmek icin ozyinelemeli (recursive)
bir dolasim gerekmektedir. Tipik islem su sekilde yapilir.Kok dizinden dosyalar
bulunarak ilerlenir. Bulunan dosyanin normal bir dosya mi yoksa bir dizin
dosyasi mi olduguna bakilir. Eger Bir dosya dizin dosyasi ise chdir
fonksiyonu ile prosesin calisma dizini degistirilip fonksiyonun kendisini
cagirmasi saglanir. Dizin bittiginde yine chdir fonksiyonu ile ust dizine
gecilir. Her alt dizin icerisinde nokta (.) ve nokta
nokta (..) isimli iki dizin otomatik olarak olusturulur. bunlarin
dikkate alinmamasi gerekir.
C Programlama icerisinde yer alan recursive algoritmalar
konusuna goz alilmasi gerekmektedir.
sdasd
/*-------------------------------------------------------------------------------------
Dizin
agacinin dolasilmasi
-------------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <dirent.h>
void exitsys(const char *msg);
void walktree(const char *path);
int main(int argc, char *argv[])
{
if
(argc != 2) {
fprintf(stderr,
"wrong number of arguments\n");
exit(EXIT_FAILURE);
}
walktree(argv[1]);
return
0;
}
void walktree(const char *dirpath)
{
struct
stat finfo;
DIR
*dir;
struct
dirent *dire;
char
filepath[1024];
if
((dir = opendir(dirpath)) == NULL) {
perror("opendir");
return;
}
while
((dire = readdir(dir)) != NULL) {
if
(!strcmp(dire->d_name, ".") || !strcmp(dire->d_name,
".."))
continue;
sprintf(filepath,
"%s/%s", dirpath, dire->d_name);
if
(lstat(filepath, &finfo) < 0) {
perror("stat");
continue;
}
printf("%s\n",
filepath);
if
(S_ISDIR(finfo.st_mode))
walktree(filepath);
}
closedir(dir);
}
void exitsys(const char *msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
Dosya Baglari (linkleri)
Dosya baglari siki (hard) ve sembolik olmak uzere ikiye
ayrilmaktadir. Hard link sisteminin anlasilabilmesi icin diskin metadata
formatinin biliniyor olmasi gerekmektedir.
Bir diskte okunabilecek veya yazilabilecek en kucu birim
sektordur. Bir sektor varsayilan olarak 512 byte uzunlugundadir. Ancak isletim
sistemleri diski sektpor temelinde organize etmek yerine block yada cluster
denilen birimler ile organize etmektedir. Bir block yada Cluster ardisil n sektorden
olusmaktadir. Bu sektorun sayisi formatlarken belirlenir. Bir block yada
cluster bis dosyanin parcasi olabilen en kucuk birimdir(ornegin 1 byte
uzunlugunda bir dosya olusturacak olsak sistemda bu dosya icin 1 block yer
ayrilir). Bir volumu ext2, ext3 gibi inode tabanli bir dosya sistemi ile
formatlarsak kabaca diskte 3 bolum olusturulur. Bunlar super block, inode
block, data block bolumleridir.
Super Blok, bolumlerin yerlerini uzunluklarini vesaire tutan
bir blogun kaz sektorden olustugunu tutan bolumdur. Volume'nin kalbidir.
Inode block, inode elemanlarindan olusur. Her inode
elemanina 0'dan baslayarak bir sira numarasi karsilik dusurulmustur. Bir
dosyanin butun bigileri, yani stat fonksiyonu ile aldigimiz bilgiler inode
elemaninda tutulur. Bir dosya yaratildiginda onun icin bir inode
elemani olusturulur. Yani her dosyanin bir inode elemani vardir. Dizinler de
birer dosya gibidir. Onlar icin de birer inode elemani vardir. BIr dosyanin
inode numarasi demek o dosyanin bilgilerinin inode blogunun kacinci inode
elemaninda saklandigi demekdir. dosyanin inode numarasi ls -i ile
goruntulenmektedi
0 Numarali inode elemani kok dizinin elemanidir. Dizinler de
dosyalar gibi bir dizin dosyasinin icerisinde dosya ismi ve inode
numaralarindan olusan kayitlar vardir.
isim
|
inode no
|
isim
|
inode no
|
isim
|
inode no
|
...
|
...
|
Diskin data bolumu ilk blok sifirdan baslayacak sekilde
bloklarla numaralandirilmistir. Her dosya data bolumu icerisinde bloklara
parcalanmis bir bicimde oradaki bloklarda tutulmustur. Bu bloklar ardisil olmak
zorunda degildir. Dosyanin parcalarinin hangi bloklarda oldugu inode
elemaninda tutulmaktadir.
isletim sisteminin dosya sistemi yol ifadelerinden oncelikle
bir bir inode elemani elde etmelidir. Cunku dosyani butun kontrol bilgisi inode
elemanindadir. Genel olarak bir yol ifadesinden o dosyaya iliskin inode
elemaninin elde edilmesi surecine "Pathname resolution"
denilmektedir. Pathname resolution su sekilde gerceklestirilir. Ornegin
/home/csd/test.dat dosyasina erisilmek istensin;
- Sistem
0 numarali inode elemanina gider. Onun bloklarini okur ve orada inode
kayitlari vardir. Orada home isminii arar. Bulursa onun inode numarasini
elde eder,
- Eger
bulunan home ismi bir dizin dosyasina iliskinse ve erisim hakki varsa onun
inode elemanina gide ve onun da bloklarini okur. Orada csd ismini arar ve
onun inode numarasini elde eder.
- Artik
csd'nin inode elemaninda onun bloklarina bakilarak bu kez orada test.dat
aranir. ve nihayet dosyanin bilgisine erisir.
Hardlink nedir?
Hardlink farkli dizin girislerinin ayni inode numarasina
sahip olmasidir. Boylece iki farkli yol ifadesiyle pathname resolution
yapildiginda aslinda ayni dosyaya erisilmis olur.
Ornegin
Goruldugu gibi /home/kaan/b.dat dizin girisi ile
/home/ali/y.dat dizin girisi ayni inode elemanini gostermektedir.
Peki rm gibi bir komutla bu dosyalardan biri silinse ne olur?
Eger dosyanin inode elemani ve inode bloklar free hale
getirilirse diger yol ifadesiyle ardik diger dosyaya erisemiyoruz.iste bunun
icin inode elemaninda isletimsistemi hardlink sayisini tutar. Dosya silinmeye
calisildiginda once dizin girisini siler. Sonra dosyanin inode elemanina
giderek oradaki hardlink sayacini 1 eksiltir. Eger sayac sifira duserse
dosyanin inode numarasini ve o inoda bagli data bloklarini siler(metadata
alanlari silinmis gibi gosterilir).
Inode tabanli dosya sistemlerinde ayrica hangi inode
elemanlarinin bos oldugu ve hangi data bloklarinin bos oldugu disk
uzerinde bir yerlerde tutulmalidir. Suphesiz her blok yada inode elemani icin 1
bit yeterlidir. Ornegin ext2 dosya sisteminde bu bilgiler hemen superblok'tan
asonra block bitmap ve inode bitmap isimleri ile tutulurlar.
Hiç yorum yok:
Yorum Gönder