[P&AM Lab] Cat ТЗ
Grigoriy A. Sitkarev
sitkarev на komitex.ru
Вт Фев 15 23:43:11 MSK 2011
15.02.2011 21:18, LonelyRuyK пишет:
> Вроде бы ввёл поправки по основным пунктам.К сожалению пока не тестил на
> 64бит, изза того что с регистрацией на vmware проблемы.
Может быть стоит попробовать не vmware а какой-нибудь bochs или qemu?
Теперь по ходу текста программы замечания (самые важные).
1. Не понятно выходит у нас с BUFSIZE и count. Зачем-то делаем count =
BUFSIZE-1 а потом при аллокации буфера для чтения обратно прибавляем к
count+1.
2. Самый первый цикл while в main удивительно сложный в условии. Вообще,
лучше использовать ф-ю getopt(3) для разбора опций. Раньше её не было
просто в библиотеке, поэтому старые утилиты обходились без неё.
3. В switch лучше case оставить на том же уровне вложенности.
switch (*arg) {
case 'n': {
nflg++;
break;
}
...
4. Долго думал как же расшифровывается имя переменной fsti и так и не
придумал. Наверное нужно выбрать какое-то вменяемое имя.
5. Закрывать файлы если мы делаем exit() в большинстве случаев не нужно.
Потому что exit() их сам закроет и все ресурсы высвободит. Это лишнее.
6. Проверка на блочность сделана не совсем верно. Блочным будет и
простой файл и файл блочного устройства. Т.е. надо:
if (S_ISREG(st.st_mode) || S_ISBLK(st.st_mode)) {
...
Почему? Потому что блочное устройство у нас тоже будет эффективно
читаться блоками.
7. Если я буду cat-ить файл например с флешки, а потом возьму и выдерну
её, то программа будет работать неверно. Она может затереть чужие данные
в куче (heap) потому что read(2) вернёт -1, а проверки там нет. Сейчас
там так:
res = read(fd, buff, count);
buff[res] = '\0';
Мы не проверили, вернул ли read число > 0. Если была ошибка и read(2)
вернул -1, то мы затрём что-то не наше в куче (heap). Для такой
маленькой программы это пройдёт незаметно, но для той которая работает
продолжительное время это однозначно приведёт к падению в SIGSEGV рано
или поздно. Такие ошибки очень трудно искать.
Кроме того, программа может получить сигнал например. Мы сейчас не
обрабатываем сигналы никак и поэтому любой сигнал приведёт к завершению
процесса, но даже теоретически -- надо предусмотреть такой случай.
Здесь наверное нужно было сделать что-то вроде:
for (;;) {
res = read(fd, buff, count);
if (res == -1 && errno == EINTR)
continue;
if (res == 0) {
/* Handle end of file. */
...
} else if (res < 0) {
/* Handle error. */
}
/* Now do something with input. */
...
}
Это практически идиома.
8. Не понятно, почему использован цикл for:
i = 0;
for(; i<res; i++){
...
}
вместо идиоматического:
for (i = 0; i < res; i++) {
...
}
9. printfile() добавляет всегда лишний '\n' в файл. Этого быть не
должно. И вообще, cat он предназначен для работы с любыми файлами,
любыми. Не только текстовыми. Это нужно помнить.
10. Опция -v не обрабатывается, хотя утилита "кушает" её с командной
строки. Это значит что программа не соответствует ТЗ.
Боря, ещё, обрати пожалуйста внимание на стиль. В некоторых местах всё
прыгает, пробелы, скобки, а надо бы всё в удобный приятный вид привести,
чтобы была глазу радость.
Пока вроде бы всё, мелочи потом.
--
Г.А.
Подробная информация о списке рассылки Lab