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