Jądro systemu operacyjnego UNIX udostępnia nam dwie podstawowe operacje zapis i odczyt , przy pomocy funkcji systemowych write i read .Trzeba wiedzieć ,że plik traktowany jest jako tablica bajtów dzięki temu możemy operować na nim z dokładnością co do bajtu.
Aby móc wykonywać operacje na pliku trzeba najpierw go otworzyć ,do tego celu posłuży nam funkcja open. Zwraca ona deskryptor pliku,zapytacie pewnie czym jest ów "deskryptor" . Jest to liczba ,która "opisuje" , a mówiąc bardziej precyzyjnie identyfikuje plik. Standardowo deskryptory 0, 1, 2 przydzielone są standardowemu wejściu,wyjściu i wyjściu diagnostycznemu.
Przy otwieraniu pliku przekazywany jest tryb otwarcia , który określa dopuszczalne operacje jakie można wykonać w związku z tym otwarciem (tylko zapis, tylko odczyt etc.)
Poniżej zamieszczam definicje najważniejszych funkcji systemowych:
int creat(const char *pathname, mode_t mode)
Wartości zwracane:
poprawne wykonanie funkcji: deskryptor otwartego pliku
zakończenie błędne: - 1
Argumenty funkcji:
pathname – wskaźnik do napisu zawierającego nazwę ścieżki pliku, który ma być otwarty
mode – prawa dostępu (np. 0640)
Opis:
Funkcja tworzy nowy plik, którego lokalizacja zależy od parametru pathname , a prawa dostępu od parametru mode .
int open(const char *pathname, int flags[, mode_t mode])
Wartości zwracane:
poprawne wykonanie funkcji: deskryptor otwartego pliku
zakończenie błędne: - 1
Argumenty funkcji:
pathname – wskaźnik do napisu zawierającego nazwę ścieżki pliku, który ma być otwarty
flags – metoda dostępu
• O_RDONLY – otwarcie w trybie tylko do odczytu
• O_WRONLY – otwarcie w trybie tylko do zapisu
• O_RDWR –- otwarcie w trybie do odczytu i do zapisu
Argument flags może być połączony bitowym OR z jedną (lub więcej) z następujących wartości:
• O_CREAT – utworzenie pliku, jeśli plik jeszcze nie istnieje,
• O_TRUNC – obcięcie pliku, jeśli plik istnieje i otwierany jest w trybie
O_WRONLY lub O_RDWR,
• O_EXCL – powoduje zgłoszenie błędu jeśli plik już istnieje i otwierany jest z flagą O_CREAT
• O_APPEND – operacje pisania odbywają się na końcu pliku.
mode – prawa dostępu, jest to argument opcjonalny
Opis:
Parametr wejściowy pathname jest nazwą (w szczególności pełną nazwą ścieżkową) pliku, parametr wejściowy flags oznacza tryb otwarcia pliku pliku i może mieć następujące wartości: O_RDONLY, O_WRONLY, O_RDWR .
int close(int fd)
Wartości zwracane:
poprawne wykonanie funkcji: 0
zakończenie błędne: - 1
Argumenty funkcji:
fd – deskryptor zamykanego pliku
Opis:
Funkcja zamyka deskryptor pliku przekazany przez parametr fd .
int read(inf fd, void *buf, size_t count)
Wartości zwracane:
poprawne wykonanie funkcji: rzeczywista liczba bajtów, jaką udało się odczytać
zakończenie błędne: - 1
Argumenty funkcji:
fd – deskryptor pliku z którego mają zostać odczytane dane
buf – adres bufora znajdującego się w segmencie danych procesu, do którego zostaną przekazane dane odczytane z pliku w wyniku wywołania funkcji read
count – ilość bajtów do odczytania
Opis:
Odczyt danych z pliku. Funkcja powoduje odczyt count bajtów z otwartego pliku, identyfikowanego przez deskryptor fd , począwszy od bieżącej pozycji wskaźnika do pliku i umieszczenie ich pod adresem buf w przestrzeni adresowej procesu. Funkcja zwraca liczbę bajtów na której udało się wykonać operację (zero oznacza koniec pliku). Odczyt powoduje zmianę wskaźnika bieżącej pozycji w pliku. Po otwarciu pliku wskaźnik ten ustawiony jest na 0, czyli na początek pliku, a po kolejnych operacjach przesuwa się w kierunku końca pliku o tyle bajtów ile udało się odczytać.
int write(inf fd, void *buf, size_t count)
Wartości zwracane:
poprawne wykonanie funkcji: rzeczywista liczba bajtów, jaką udało się zapisać
zakończenie błędne: - 1
Argumenty funkcji:
fd – deskryptor pliku do którego mają zostać zapisane dane
buf – adres bufora znajdującego się w segmencie danych procesu, z którego zostaną pobrane dane zapisane przez funkcję write
count – ilość bajtów do zapisania
Opis:
Funkcja powoduje zapis count bajtów do otwartego pliku, identyfikowanego
przez deskryptor fd , począwszy od bieżącej pozycji wskaźnika do pliku i umieszczenie ich pod
adresem buf w przestrzeni adresowej procesu. Funkcja zwraca liczbę bajtów na której udało się
wykonać operację.
Podobnie jak dla funkcji read zapis powoduje zmianę wskaźnika bieżącej pozycji w pliku.
Czas na praktykę. Napiszemy prosty program , którego zadaniem będzie
kopiowanie pliku podanego przez użytkownika:
#include fcntl.h
#include stdio.h
#define BUF_SIZE 1024
int main(int argc, char* argv[]){
char buf[BUF_SIZE];
int desc_1,desc_2;
int odczytano=0;
if (argc<3){
fprintf(stderr, "Zla ilosc argumentow !!");
exit(1);
}
desc_1 = open(argv[1], O_RDONLY);
if (desc_1 == -1){
perror("Blad otwarcia pliku zrodlowego");
exit(1);
}
desc_1 = creat(argv[2], 0640);
if (desc_1 == -1){
perror("Blad utworzenia pliku docelowego");
exit(1);
}
while((odczytano = read(desc_1, BUF_SIZE, MAX)) > 0){
if (write(desc_2, buf, lbajt) == -1){
perror("Blad zapisu pliku docelowego");
exit(1);
}
}
if (odczytano== -1){
perror("Blad odczytu pliku zrodlowego");
exit(1);
}
if (close(desc_1) == -1 || close(desc_2) == -1){
perror("Blad zamkniecia pliku");
exit(1);
}
exit(0);
}