Визначення прав доступу до файлу
Для визначення прав доступу в поле st_mode є 9 біт. Імена цих макросів додержуються форми запису: s_Ipwww, де символ p - режим доступу (R, w або X), a www - кому видане право на цей режим доступу (USR, GRP або OTH).
S_Ixwww де x = R|W|X, www = USR|GRP|OTH
приклади:
S_IRUSR,
S_IWOTH
S_ISUID set-user-id bit is set
S_ISGID set-group-id bit is set
S_ISVTX sticky bit is set
Ці макроси являють собою бітові маски.
Приклад використання.
Розглянемо програму, що друкує інформацію про всіх відкриті нею файлах і каналах. Для цієї мети використовуйте системний виклик
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/param.h>
#include <sys/fcntl.h>
main
{
struct stat st;
int fd;
open(“file”,O_RDONLY);
for(fd=0; fd < NOFILE; fd++ )
if (fstat(fd, &st ==0)
{ printf("File stats\n");
printf(" File size: %ld\n", st.st_size);
printf(" Permission: %o\n", st.st_mode & 0x01ff);
/*шестнадцатеричное число = 0001 1111 1111
Можна так
stat( имяфайла, &st);
кодыдоступа = st.st_mode & 0777;
або S_IRWXU| S_IRWXG| S_IRWXO
*/
printf(" Owner uid: %d\n", st.st_uid);
printf(" Owner gid: %d\n", st.st_gid);
printf("\n");
}
}
}
Програма може використовувати дескриптори файлів з номерами 0..NOFILE-1 (звичайно 0..19). Якщо fstat для якогось fd повернув код помилки (<0), це означає, що даний дескриптор не пов'язаний з відкритим файлом (тобто не використовується). NOFILE визначено в include-файлі <sys/param.h>, що містить різноманітні параметри даної системи.
По відкритому файлі не існує простого способу довідатися його ім'я. Для цього треба сисвызовом fstat довідатися номер пристрою й номер індексного дескриптора, після чого знайти у файловій системі відповідний запис.
3. Додаткові функції маніпулювання даними індексних дескрипторів
Перевірка прав доступу до файлу
access (filename, mode)
char * filename;
int mode;
Функція access перевіряє, чи має процес дозвіл на читання, запис або виконання файлу Якщо pathname є символьним посиланням, то перевіряються права доступу до файлу, на який вона вказує. mode - це маска, що складається з одного або більше прапорів R_OK, W_OK, X_OK і F_OK.
R_OK, W_OK і X_OK використовуються для перевірки, чи існує файл і чи можна його читати, записувати в нього або виконувати, F_OK просто перевіряє наявність файлу.
Повертає 0 у разі успіху, -1 у випадку помилки (код помилки-у змінній errno)
Зміна власника файлу
chown - зміна власника та групи файлу
СИНТАКСИС
int chown (path, owner, group)
char * path;
int owner, group;
ОПИС
Аргумент path є покажчиком на маршрутне ім'я файлу. Ідентифікатори власника та групи зазначеного файлу встановлюються рівними числовим значенням, відповідно, аргументів owner і group.
Тільки root може змінити власника файлу. Власник файлу може змінювати групу файлу на будь-яку групу, до якої він належить. Root може довільно проводити цю заміну.
Зміна прав доступу до файлу
chmod - зміна режиму доступу до файлу
# Include <sys/types.h>
# include <sys/stat.h>
int chmod (const char * path, mode_t mode);
int fchmod (int fildes, mode_t mode);
Можна змінювати коди доступу, відповідні бітової масці
0777 | S_ISUID | S_ISGID | S_ISVTX
Аргумент path є покажчиком на маршрутне ім'я файлу. Системний виклик chmod встановлює режим доступу до вказаного файлу відповідно до бітним шаблоном, що містяться в аргументі mode.
Змінювати права доступу до файлу може тільки процес, що має чинний ідентифікатор користувача, рівний ідентифікатору власника файлу або суперкористувача.
Якщо системні виклики chown і chmod виконуються не суперкористувачем, то біти перевстановлення ідентифікаторів користувача і групи, 04000 і 02000 відповідно, обнуляються.
Зміна системної маски прав доступу
Ми вже згадували про маску, що накладається на набір прав доступу при створенні файлу. Накладення маски виконує системний виклик umask, який рідко використовується де-небудь ще, крім як в команді umask.
Umask - встановлює і повертає маску прав доступу для знову создава ваних файлів.
# Include <sys/stat.h>
mode_t umask (mode_t cmask);
cmask - нова маска
Повертає попереднє значення маски повернення кодів помилок не передбачений
Так як кожен процес має маску і будь-яка комбінація з 9 біт вважається припустимою, umask не передбачає вихід помилково. Він завжди повертає колишнє значення маски. Щоб дізнатися поточне значення маски не змінюючи її, потрібно виконати дві послідовних виклику umask. Перший - щоб отримати поточне значення маски (передавши у виклик будь-яке значення нової маски), другий - щоб відновити її в первісний стан.
4. Отримання даних про відкриті файли
Над дескрипторами файлів теж можна виконувати деякі операції, наприклад, відкривати файли, дублюючи дескриптори відкритих файлів, отримувати або встановлювати прапори, що описують стан дескриптора, захоплювати блоки файлу і так далі Всі ці операції виконуються функцією fcntl.
#include <fcntl.h>
int fcntl (int fd, int cmd, arg)
Функція виконує команду cmd над дескриптором файлу fd.
Деякі команди вимагають завдання додаткових аргументів.
Таблиця 3
Основні команди cmd
F_DUPFD | Дублювання дескриптора файлу. Повертає інший дескриптор, що асоціюється з тим же відкритим файлом; |
F_GETFD | Отримує прапори, що асоціюються з дескриптором; |
F_SETFD | Встановлює прапори, що асоціюються з дескриптором; |
F_GETFL | Отримує прапори, що асоціюються з відкритим файлом; |
F_SETFL | Встановлює прапори, що асоціюються з відкритим файлом; |
F_GETLK | Отримує інформацію про захоплені області файлу; |
F_SETLK | Встановлює або скидає захоплення файлу; |
F_SETLKW | Ідентично F_SETLK, але чекає закінчення виконання; |
F_GETOWN | Отримує процес або групу процесів, яким буде посланий сигнал SIGIO |
F_SETOWN | Встановлює процес або групу процесів, яким буде посланий сигнал SIGIO |
Діагностика
При успішному завершенні системного виклику залежно від операції cmd повертаються наступні значення:
F_DUPFD Новий дескриптор файлу.
F_GETFD Значення прапора (визначений тільки молодший біт).
F_SETFD Значення, відмінне від -1.
F_GETFL Значення прапорів статусу файлу.
F_SETFL Значення, відмінне від -1.
F_GETLK Значення, відмінне від -1.
F_SETLK Значення, відмінне від -1.
F_SETLKW Значення, відмінне від -1.
У разі помилки повертається -1, а змінною errno привласнюється код помилки.
Отримання і установка прапора стану файлу
1) Як по дескриптору файлу дізнатися, відкритий він на читання, запис, читання і запис одночасно?
int flags;
if((flags=fcntl (fd, F_GETFL, NULL)) < 0 )
return NULL; /* fd ймовірно не відкритий */
flags &= O_RDONLY | O_WRONLY | O_RDWR;
switch(flags){
case O_RDONLY: return "r";
case O_WRONLY: return "w";
case O_RDWR: return "r+w";
default: return NULL;
}
2) приклад зміни прапора дескриптора:
int flags = fcntl (fd, F_GETFL, 0);
fcntl (fd, F_SETFL, flags | O_NONBLOCK);
3) установка нового власника
fcntl(fd, F_SETOWN, getpid())
4) setflag (int desc, int value)
{
int oldflags = fcntl (desc, F_GETFL, 0);
/* якщо відбулася помилка, виходимо з програми */
if (oldflags == -1)
return -1;
/* встановлюємо тільки потрібний прапор */
if (value != 0)
oldflags |= O_NONBLOCK;
else
oldflags &= ~O_NONBLOCK;
/* зберігаємо прапор в дескрипторі файлу */
return fcntl (desc, F_SETFL, oldflags);
}
Передається два параметри: дескриптор і індикатор – 0, якщо треба зняти прапор і не 0, якщо встановити.
|= додає ?=~ знімає ~ інвертує
Зберігаємо в дескрипторі, повертаємо в зухвалу процедуру.
Блокування файлів з використанням fcntl
Окрім модифікації файлового дескриптора системний виклик fcntl(2) використовується для блокування файлу. Блокування областей файлу дозволяє декільком програмам спільно працювати з вмістом одного і того ж файлу, не заважаючи один одному.
Прикладом ситуації, в якій може бути корисний захоплення файлу служить бути програма, яка може бути запущена декількома користувачами незалежно, записує протокол роботи у файл. Декілька процесів, що одночасно записують інформацію у файл можуть зміщувати інформацію різних користувачів, що приведе до плутанини. У разі захоплення файлу цього не відбудеться.
В цьому випадку cmd - тип блокуючої операції, а в у arg указується адреса структури flock, в яку записується інформація про блокування. Структура і відповідні макроси описані в заголовному файлі <fcntl.h>.
Таблиця 4
Опис полий структури flock
Поле | Значення |
short l_type | Тип блокування: записи – F_RDLCK, читання – F_WRLCK, скидання – F_UNLCK. |
short l_whence | Адреса початку ділянки, що блокується; дається у вигляді зсуву відносно початку файлу (0), щодо поточної позиції покажчика (1), щодо кінця файлу (2) |
Продовження таблиці 4
Поле | Значення |
long l_start | Зсув в байтах, що інтерпретується відповідно до значення l_whence |
long l_len | Довжина ділянки, що блокується, в байтах. Якщо вказаний 0, блокується ділянка від l_start до кінця файлу |
long l_pid | Ідентифікатор процесу, що встановив блокування (для GETLCK) |
long l_sysid | Ссистемний ідентифікатор процесу, блокуючого файл |
Якщо задана область вже заблокована, fcntl повертає -1.
За допомогою команди F_GETLK можна дізнатися, ідентифікатор процесу, що заблокував дану область.
Ядро автоматично знімає блокування, встановлені процесом, при закритті файлу.
За допомогою цієї функції можна маніпулювати дескрипторами файлів і встановлювати рекомендаційні (advisory) блокування (необов'язкові). В цьому випадку, якщо програма сама не використовує блокувань, блокування, встановлені іншими програмами, не матимуть для неї ніякого ефекту. Існує можливість додати рекомендаційним блокуванням fcntl() обов'язковий характер, але для цього відповідна файлова система повинна бути змонтована із спеціальним ключем.
Базові правила використання блокувань:
− Програми, які хочуть читати з файлу, належний відкрити файл, а потім використовувати fcntl в режимі F_RDLCK
− Програми, які хочуть читати з файлу і записувати у файл повинні відкрити файл, а потім використовувати flock в режимі F_WRLCK.
− Виклик flock блокуватиме файл до тих пір, поки він доступний, в цей час необхідні операції можуть бути виконані з деякою мірою безпеки.
− Після виконання операцій приберіть блокування шляхом закриття файлового дескриптора або за допомогою F_UNLCK