Duzo tego wyszlo o tej funkcji, ale nie trzeba w to sie wgryzac. Wystarczy, moim zdaniem, wiedziec, ze zeby zmienic wlasciciela pliku, trzeba byc superuserem dla systemu plikow (fsuid=0), wlasciciel nie moze komus pliku swojego oddac. Moze on sie nim za to bawic zmieniajac wlasciciela na siebie - funkcja nie zwroci bledu. Do grupy tyczy sie to samo, jednak z kodu zrodlowego to tak latwo nie wynika. Jest to troche namieszane, dlatego ze zmieniajac grupe, funkcja chown zmienia tez czas modyfikacji, i o ile do samej zmiany grupy nie musimy byc wlascicielem, to zeby zmieniac czas, musimy. Wiec zasady sa tylko dwie: dotychczasowy wlascicel lub superuser moze zmieniac grupe pliku, z tym, ze jesli to wlasciciel, to musi jeszcze nalezec do grupy, na ktora zmienia.
W Linuxie pewne pliki moga miec szczegolne wlasciwosci, o ktorych mowi pole inode->flags. Naleza do nich:
struct iattr {
unsigned int ia_valid; /* bity mowia, co chcemy zmienic */
umode_t ia_mode; /* nowy tryb dostepu dla i-wezla */
uid_t ia_uid; /* nowy uid */
gid_t ia_gid; /* nowy gid */
... (i inne, np. czas dostepu i modyfikacji i-wezla)
};
Ta struktura sluzy do wymiany atrybutow i-wezla miedzy funkcjami wirtualnego (np. chown), a konkretnego file-systemu (np. notify_change).
DEFINICJA: int chown (const char *filename, uid_t user, gid_t group);
DZIALANIE: zmiana wlasciciela i grupy dla pliku (inode->uid, inode-> gid). Dzialanie jej jest kilkupoziomowe. Najpierw przypisujemy wszystkie nowe atrybuty do struktury iattr , zaznaczamy w niej co chcemy zmieniac i wywolujemy notify_change, ktora wywoluje funkcje sprawdzajace prawa i dokonujace wlasciwych zmian.
ARGUMENTY: nazwa pliku, nowy uid i gid dla pliku
WYNIK: blad
ALGORYTM:
{
Przeksztalc nazwe sciezkowa pliku w i-wezel;
Jesli
to: zwolnij i wezel (pobrany w namei) - funkcja iput - i wyjdz;
Jesli user=-1, to wez starego wlasciciela;
Jesli group=-1, to wez stara grupe;
Podstaw tryb dostepu (pobrany z i-wezla), user oraz group do struktury iattr;
Zaznacz w niej, ze chcemy zmienic te rzeczy i czas (dostepu i modyfikacji pliku);
Jesli podales nowego wlasciciela (a nie dotychczasowego), to usuwamy bit setuid;
Jesli podales nowa grupe i jest prawo wykonywania dla grupy, i jest ustawiony bit setgid, to usun ten ostatni bit (na razie w polu iattr->ia_mode - potem, o ile mamy odpowiednie uprawnienia, zmiana dokona sie w i-wezle). Z tym bitem setgid chodzi o to, zeby nie zniszczyc kandydata na obowiazkowe blokowanie (mandatory locking) - a jest on wtedy, gdy nie ma prawa wykonywania dla grupy, ale jest ustawiony bit setgid.;
Zaznacz i-wezel na brudny;
Jesli system z quota'mi, to:
Jesli system bez quot, to zrob tylko notify_change;
Zwolnij i-wezel (iput).
}
Zeby bylo wiadomo, jak to Linux robi, trzeba jeszcze wyjasnic:
DEFINICJA: int notify_change (inode *inode, struct iattr *iattr);
DZIALANIE: sprawdzenie uprawnien procesu wolajacego, zmiana atrybutow i-wezla.
ARGUMENTY: i-wezel i nowe dla niego atrybuty.
WYNIK: blad
ALGORYTM:
{
Ustaw czas ostatniej modyfikacji i-wezla (iattr->ia_ctime) na obecny;
Jesli konkretny file-system ma swoje notify_change, to je wykonaj i wyjdz. Inaczej (by default) wykonaj nastepne kroki:
Sprawdz, czy mozna zmienic prawa, wykonujac funkcje:
{
}
Zmien i-wezel wykonujac procedure:
{
}
}
Tylko pliki zrodlowe Linuxa:
Odpowiednie funkcje z tych plikow, z moim komentarzem do prawie kazdej linijki znajdziecie tu:
No problems detected.
(ogolne pytania p. Raczunasa sa na stronie write).
tego samego autora: funkcja write.