8 ŚRODOWISKO SYSTEMU UNIX_________
Funkcja creat zwraca deskryptor pliku, jeśli mogła utworzyć wskazany plik, a w przeciwnym przypadku zwraca -1. Jeżeli natomiast plik już istnieje, to creat skraca go do zerowej długości, kasując tym samym jego poprzednią zawartość; tworzenie pliku, który już istnieje, nie jest błędem.
Jeśli plik jest całkiem nowy, to creat utworzy go z uprawnieniami określonymi argumentem perms (od ang. permission). W systemie Unix z każdym plikiem w systemie plików jest związane dziewięciobitowe pole przeznaczone na informacje o uprawnieniach. Wartość tego pola określa uprawnienia do czytania, pisania i wykonywania pliku przez właściciela pliku, jego zespół oraz przez resztę użytkowników systemu. Zakres uprawnień najlepiej zatem oddaje trzycyfrowa liczba ósemkowa. Na przykład 0755 nadaje właścicielowi prawo do czytania, pisania i wykonywania, a członkom jego zespołu i wszystkim pozostałym użytkownikom tylko prawo do czytania i wykonywania.
Dla ilustracji prezentujemy uproszczoną wersję jednego z programów narzędziowych systemu Unix - cp, który kopiuje zawartość jednego pliku do innego. Nasza wersja kopiuje tylko jeden plik, nie zezwala, aby drugim argumentem wywołania programu był skorowidz, oraz wymyśla uprawnienia, zamiast je kopiować.
#include <stdio.h>
#include <fcntl.h>
#include "syscalls.h”
#define PERMS 0666 /* czytanie i pisanie dla wszystkich */
void error(char *, ...);
/* cp: kopiuj f1 do f2 */ main(int argc, char *argv[])
int f1, f2, n; char buffBUFSIZ];
if (argc != 3)
error(”Format wywołania: cp skąd dokąd”); if ((f1 = open (argv[1], CLRDONLY, 0)) == -1) error(”cp: nie mogę otworzyć %s”, argv[1 ]); if ((f2 = creat(argv[2], PERMS)) == -1)
error(”cp: nie mogę utworzyć %s z uprawnieniami %03o”, argv[2], PERMS);
while ((n = read(f1, buf, BUFSIZ)) > 0) if (write(f2, buf, n) != n)
error(”cp: błąd pisania do pliku %s”, argv[2J); return 0;
8.3 FUNKCJE OPEN, CREAT, CLOSE, UNLINK_____
Ten program tworzy plik wyjściowy ze stałymi uprawnieniami 066 z odwołania systemowego stat, opisanego w p. 8.6, możemy ustalić uprawnienia istniejącego pliku, a zatem utworzyć jego kopię z tak określonymi uprawnieniami.
Zwróć uwagę na funkcję error, którą - podobnie jak printf - wywołujemy ze zmienną listą argumentów. Realizacja funkcji error ilustruje zastosowanie jeszcze jednego członka rodziny printf: funkcja vprintf z biblioteki standardowej działa jak printf z tym, że zamiast zmiennej listy argumentów obsługuje pojedynczy argument. Ten argument został utworzony w fazie inicjowania listy argumentów funkcji error za pomocą makra va_start. Innymi funkcjami standardowymi z tej rodziny są: vfprintf - odpowiednik funkcji fprintf oraz vsprintf - odpowiednik funkcji sprintf.
#include <stdio.h>
#include <stdarg.h>
I* error: wypisz komunikat i zakończ program */ void error(char *fmt, ...)
va Jist args;
va_start(args, fmt); fprintffstderr, "error: ”); vfprintf(stderr, fmt, args); fprintf(stderr, ”\n”); va_end(args); exit(1);
Systemy operacyjne na ogół ograniczają liczbę jednocześnie otwartych plików w jednym programie (często do 20). Wobec tego każdy program, w którym używa się wielu plików, musi być przystosowany do wielokrotnego korzystania z tych samych de-skryptorów plików. Funkcja close(int fd) zamyka plik, tj. przerywa połączenie między deskryptorem pliku a otwartym plikiem, zwalniając tym samym deskryptor do ponownego użycia z jakimś innym plikiem. Funkcja ta jest odpowiednikiem funkcji fclose z biblioteki standardowej, ale nie ma buforów do opróżniania. Zakończenie wykonywania programu przez funkcję exit lub za pomocą instrukcji return w funkcji main powoduje zamknięcie wszystkich otwartych plików.
Funkcja unlink(char *name) usuwa plik name z systemu plików. Funkcja ta jest odpowiednikiem funkcji remove z biblioteki standardowej.
*
Ćwiczenie 8.1. Zmień program cat z rozdz. 7 używając funkcji read, write, open i close zamiast ich odpowiedników z biblioteki standardowej. Przeprwadź eksperymenty porównujące względne szybkości obu wersji.
231