int link(stara_sciezka, nowa_sciezka) char *stara_sciezka; /* istniejacy plik char *nowa_sciezka; /* nowa pozycja w katalogu /* W przypadku powodzenia zwraca 0, bledu -1 */
Glowna struktura danych na ktorej dokonywane sa operacje dla funkcji link jest sturktura i-wezla (inode).
Oto dokladna definicja struktury inode z pliku include/linux/fs.h:
struct inode {
kdev_t i_dev;
unsigned long i_ino;
umode_t i_mode;
nlink_t i_nlink;
uid_t i_uid;
gid_t i_gid;
kdev_t i_rdev;
off_t i_size;
time_t i_atime;
time_t i_mtime;
time_t i_ctime;
unsigned long i_blksize;
unsigned long i_blocks;
unsigned long i_version;
unsigned long i_nrpages;
struct semaphore i_sem;
struct inode_operations *i_op;
struct super_block *i_sb;
struct wait_queue *i_wait;
struct file_lock *i_flock;
struct vm_area_struct *i_mmap;
struct page *i_pages;
struct dquot *i_dquot[MAXQUOTAS];
struct inode *i_next, *i_prev;
struct inode *i_hash_next, *i_hash_prev;
struct inode *i_bound_to, *i_bound_by;
struct inode *i_mount;
unsigned short i_count;
unsigned short i_flags;
unsigned char i_lock;
unsigned char i_dirt;
unsigned char i_pipe;
unsigned char i_sock;
unsigned char i_seek;
unsigned char i_update;
unsigned short i_writecount;
union {
struct pipe_inode_info pipe_i;
struct minix_inode_info minix_i;
struct ext_inode_info ext_i;
struct ext2_inode_info ext2_i;
struct hpfs_inode_info hpfs_i;
struct msdos_inode_info msdos_i;
struct umsdos_inode_info umsdos_i;
struct iso_inode_info isofs_i;
struct nfs_inode_info nfs_i;
struct xiafs_inode_info xiafs_i;
struct sysv_inode_info sysv_i;
struct affs_inode_info affs_i;
struct ufs_inode_info ufs_i;
struct socket socket_i;
void * generic_ip;
} u;
};
Kod zrodlowy tej funkcji znajduje sie w pliku linux/fs/namei.c,
a czesc zalezaca bezposrednio od konkretnego systemu plikow w jednym
z podkatalogow w katalogu lunux/fs. Opisany nizej algorytm
opiera sie na systemie plikow ext2. I algorytm jest zdefiniowany
w pliku linux/fs/ext2/namei.c.
Procedura sys_link (opisana ponizej) jest wykonywana w trybie
jadra systemu.
DEFINICJA: asmlinkage int sys_link(oldname, newname)
const char *oldname;
const char *newname;
WYNIK: 0 w przypadku sukcesu, -1 wpp.
{
Pobierz i-wezel pliku do ktorego bedzie robione dowiazanie;
Kopiuj plik do wolnej przestrzeni adresowej jadra (getname());
Wywolaj funkcje do_link();
Zwolnij zarezerwowane strony przestrzeni jadra systemu;
}
DEFINICJA: int do_link(oldinode, newname)
struct inode *oldinode;
const char *newname;
WYNIK: 0 w przypadku sukcesu, -1 wpp.
{
Zwroc i-wezel katalogu dla danej nazwy pliku i nazwe
z katalogiem (dir_namei);
Sprawdz czy katalog nie jest przeznaczony tylko do odczytu (IS_RDONLY);
Sprawdz zgodnosc urzadzen (urzadzenia obu katalogow musza byc te same);
Sprawdz czy jest prawo pisania(MAY_WRITE) i wykonywania(MAY_EXEC) w
katalogu docelowym;
Sprawdz czy mozna modyfikowac i-wezel do ktorego robimy dowiazanie (IS_APPEND)
lub czy nie jest modyfikowany(IS_IMMUTABLE;
Sprawdz czy w i-wezle jest zdefiniowane polecenie link;
Zablokuj katalog macierzysty (down(&dir->i_sem));
Wywolaj funkcje charakterystyczna dla danego systemu plikow (w naszym
przypadku ext2_link);
Odblokuj katalog macierzysty (up(&dir->i_sem));
Zwolnij i-wezel katalogu macierzystego;
}
DEFINICJA: int ext2_link(oldinode, dir, name, len)
struct inode *oldinode;
struct inode *dir;
const char *name;
int len;
WYNIK: 0 w przypadku sukcesu, -1 wpp.
{
Sprawdz jezeli katalog, prawa do tworzenia dowiazania;
Sprawdz czy i-wezel do ktorego robimy dowiazania mozna
modyfikowac(IS_APPEND) lub czy nie jest modyfikowany(IS_IMMUTABLE);
Sprawdz czy liczba dowiazan nie przekroczyla maksymalnej ilosci
(EXT2_LINK_MAX);
Szukaj nazwy pliku wynikowego jezeli znaleziony zwroc
blad(ext2_find_entry);
Dodaj plik do danego katalogu (ext2_add_entry);
Ustaw wskaznik do i-wezla w nowym pliku;
Dodaj informacje do katalogu o nowym pliku;
Zaznacz, ze plik jest urzywany;
Zapisz informacje z bufora i czekaj na zakonczenie operacji;
Zwolnij bufor;
Zwolnij i-wezel katalogu macierzystego;
Zmien w starym i-wezle informacje o ilosci dowiazan
i czasie ostatniej modyfikacji;
Zwolnij i-wezel starego pliku;
}