Обработка ошибок в системных вызовах

Большинство системных вызовов возвращает ноль, если операция выполнена успешно, и ненулевое значение в противном случае. В случае ошибок в глобальную переменную errno записывается дополнительная информация - целое число, идентифицирующее причину ошибки. Если включить в программу <errno.h>, можно ссылаться на ошибки по их символических именам, например, EACCES или EINVAL.

Получить в программе текстовое сообщение об ошибке можно двумя способами:

1) При помощи функции strerror из <string.h>; функция принимает errno и возвращает строку с описанием ошибки.

2) При помощи функции perror из <stdio.h>; функция принимает строку, которую она выводит в качестве префикса перед сообщением об ошибке (например, это может быть имя файла, где произошла ошибка) и выводит описание ошибки в поток stderr.

Пример. В программе делается попытка открыть файл. Системный вызов open возвращает дескриптор файла или -1 в случае ошибки.

Вариант 1. fd = open ("inputfile.txt", O_RDONLY);

if (fd == -1) {

fprintf (stderr, "error opening file: %sn", strerror (errno));

exit (1);

}

Вариант 2. fd = open ("inputfile.txt", O_RDONLY);

if (fd == -1) {

perror("inputfile.txt");

exit (1);

}

 

Обратите внимание, что успешное выполнение системного вызова не приводит к сбросу переменной errno.

 

Задание 6. Модифицируйте приведенную ниже программу copyfile.c копирования файла, добавив в нее комментарии, проверку количества аргументов командной строки (при неверном количестве параметров установите код возврата=1) и обработку ошибок после системных вызовов open (коды возврата 2 и 3), write (код возврата 4). Протестируйте программу для разных ситуаций.

 

#include <sys/stat.h>

#include <fcntl.h>

#include <stdio.h>

#define BUF_SIZE 256

int main (int argc, char *argv [])

{

int input_fd, output_fd;

int bytes_in, bytes_out;

char rec [BUF_SIZE];

input_fd = open (argv [1], O_RDONLY); /* Здесь код возврата=2 */

output_fd = open (argv [2], O_WRONLY | O_CREAT, 0666); /*Код возврата=3 */

while ((bytes_in = read (input_fd, &rec, BUF_SIZE)) > 0) {

bytes_out = write (output_fd, &rec, bytes_in);

/* Здесь код возврата=4, если число прочитанных байтов не равно числу записанных*/

close (input_fd);

close (output_fd);

return 0;

}