4.5   Визначення існування файлу або директорія

При роботі з файлом часто необхідно одержати відповідь на питання: “чи існує файл із заданим ім’ям і які його параметри ‑ розмір, дата, тип?”. Крім того, іноді потрібно змінити ці параметри, наприклад скасувати установку атрибута “файл тільки для читання”, задати потрібний розмір і т.п. Далі розглядаються засоби одержання такої інформації.

Визначити існування регулярного файлу можна, використовуючи функції відкриття fopen(), open() або _open(). Для цього задаються права доступу до файлу “тільки читання” і аналізується повернення при відкритті файлу. Наприклад, задавши у функції fopen() права доступу “r” і отримавши NULL, для середовища MS-DOS можна майже напевно сказати, що файл який відчиняється не існує. Аналогічно, якщо викликається функція open():


open( “myfile.txt”, O_RDONLY );

яка повертає -1, це говорить про відсутність “myfile.txt” у поточному накопичувачі і директорії. Проте такий засіб не завжди надійний. Адже спроба відкриття файлу може зазнати невдачі і по іншим причинам і, насамперед, через досягнення межі, що накладається системою на число одночасно відкритих файлів і префіксів які використовуються для доступу до них.

Перевірку існування заданого директорія можна виконати, спробувавши встановити цей директорій у якості поточного і проаналізувавши повернення функції chdir. Якщо функція повертає -1, то такий маршрут у файлові системі відсутній. Недоліком цього рішення є необхідність зберігати і потім відновлювати поточний маршрут.

Ще одна можливість визначення існування файлу або директорія ‑ це використання функцій пошуку findfirst() і findnext(), розглянутих у пункті 4.3. Таке рішення потребує резервування пам’яті під структурну змінну по шаблону ffblk і дозволяє одержати практично вичерпну інформацію про файл, збережену в директорії. У пункті 4.3 розглянуті засоби повної інтерпретації такої інформації, включаючи визначення дати і часу створення файлу. Проте функції findfirst() і findnext() специфічні для MS-DOS і не підтримуються реалізаціями Сі для ОС UNIX.

Більш кращим є використання спеціальних функцій accees() і fstat(), що не виконують відкриття файлу. Крім перевірки існування файлу, вони дозволяють одержати додаткову інформацію про нього.

#include <io.h>
int access( const char*filename, int amode )

Визначає існування або припустимі права доступу до файлу, на ASCIIZ-рядок специфікації якого вказує filename. Параметр amode вибирається по Табл. 10.

Табл. 10. Завдання запиту про існування і права доступу

Значення amode

Інтерпретація функцій access

00

Перевіряється тільки існування файлу або директорія

02

Перевіряється, чи припускає файл запис

04

Перевіряється, чи припускає файл читання (для MS-DOS усі файли можуть бути читатися, так що 04 аналогічно 00)

06

Перевіряється, чи припускає файл читання і запис (для MS-DOS значення 02 і 06 еквівалентні, тому що право доступу по запису припускає і право доступу по читанню)

Якщо відповідь на питання, задане функції, стверджувальний, вона повертає 0; у протилежному випадку повертається -1 і в зовнішню змінну errno встановлюється код помилки. Якщо не знайдений специфікований параметром filename маршрут або файл, то зовнішня змінна errno буде дорівнювати ENOENT. Якщо файл не має запитаного доступу, errno буде дорівнює EACCES. Якщо filename посилається на директорій, перевіряється існування цього директорія. Функція працює з елементами директорія і тому не враховує додаткові обмеження, що з’являються за рахунок функцій відкриття і створення файлів. Тому що у файлові системі MS-DOS відсутнє таке збережене в байті атрибута право “тільки запис”, значення amode 02 і 06 еквівалентні. Всі файли в MS-DOS можуть читатися і тому аналогічними будуть запити з amode 00 і 04.

Наведена нижче програма визначає існування файлу, ім’я якого задано першим параметром командного рядка, і уточнює, чи є файл тільки що читається:

/*L4_6.C*/
#include <stdio.h>
#include <io.h>
int main( int argc, char **argv) {
  if( argc < 2) { /* чи задані параметри в командному рядку */
    printf(“\аВикористання програми %s <ім’я_файла>\п”, argv[0]);
    return(1);
  }
  if( !access(argv[1], 00)) { /* чи існує файл? */
    fputs(“Файл існує”, stdout);
    if( access(argv[1], 02))
       fputs(“і припускає тільки читання.\п”, stdout);
    else
      fputs(“і припускає як читання, так і запис.\п”, stdout);
  }
  else
    fputs(“Файл не існує\п”, stdout);
}

Ще один мобільний засіб визначення існування файлу або директорія – звернення до функції fstat() (див.4.6). Якщо функція повертає -1, це свідчить про відсутність файла.