Ілюстрація до обробки помилок: sv

Тепер напишемо програму під назвою sv (схожу на cp), яка копіює набір файлів в каталог, але при цьому перезаписує файл призначення, тільки якщо він не існує або є більш

старим, ніж вихідний файл Назва sv походить від англійського слова save (зберегти) – ідея в тому, що sv Не перекривати більш нові версії файлів Команда sv враховує більше інформації з індексного дескриптора, ніж checkmail

Будемо запускати sv наступним чином:

$ sv  file1 file2 .. dir

Ця команда повинна копіювати file1 в dir/file1, file2 в dir/file2 і т д, за винятком тих випадків, коли файл призначення новіше відповідного вихідного файлу – в цьому випадку копія не робиться і видається попередження Для того щоб уникнути багаторазового копіювання посилань, програма sv не дозволяє використовувати / в іменах вихідних файлів

/ * Sv: зберігає нові файли * /

#include &ltstdioh&gt

#include &ltsys/typesh&gt

#include &ltsys/dirh&gt

#include  &ltsys/stath&gt char  *progname

main(argc,  argv) int  argc

char  *argv[]

{

int i

struct stat stbuf

char  *dir  = argv[argc–1]

progname  =  argv[0] if  (argc  &lt=  2)

error(&quotUsage: %s  files.. dir&quot, progname)

if (stat(dir, &ampstbuf)  == –1)

error(&quotcant  access  directory  %s&quot, dir) if  ((stbufst_mode  &amp  S_IFMT)  =  S_IFDIR)

error(&quot%s  is  not  a  directory&quot,  dir) for  (i =  1  i &lt argc–1  i++)

sv(argv[i],  dir) exit(0)

}

Значення часу в індексному дескрипторі задаються в секундах після 0:00 GMT 1 січня 1970, так що більш старі файли мають менші значення в поле st_mtime

sv (file, dir) / * зберігає file в dir * / char * file, * dir

{

struct  stat  sti,  sto int  fin,  fout,  n

char  target[BUFSIZ],  buf[BUFSIZ],  *index() sprintf(target,  &quot%s/%s&quot, dir,  file)

if (index (file, /) = NULL) / * strchr () у деяких системах * / error (wont handle / s in% s, file)

if (stat(file,  &ampsti) == –1)

error(&quotcant stat %s&quot, file)

if (stat (target, & sto) == -1) / * файл призначення не існує * / stost_mtime = 0 / * Нехай він буде старіше * /

if (stist_mtime

fprintf(stderr,  &quot%s:  %s  not  copied\n&quot, progname,  file)

else if ((fin  =  open(file,  0))  ==  –1) error(&quotcant  open file  %s&quot,  file)

else if ((fout  =  creat(target,  stist_mode)) == –1) error(&quotcant create  %s&quot,  target)

else

while ((n  =  read(fin, buf,  sizeof buf))  &gt  0) if  (write(fout,  buf,  n)  =  n)

error(&quoterror  writing  %s&quot,  target)

close(fin) close(fout)

}

Замість стандартних функцій вводу-виводу використана creat для того, щоб sv мала можливість зберегти код прав доступу вихідного файлу (Зверніть увагу на те, що index і strchr – це різні назви однієї і тієї ж процедури подивіться в керівництві опис string (3), щоб дізнатися, яке імя використовує ваша система)

Незважаючи на те що sv – це спеціалізована програма, вона ілюструє кілька важливих ідей Є безліч програм, хоча і не є «системними», але проте здатних використовувати інформацію, збережену операційною системою, до якої мож отримати доступ за допомогою системних викликів Для таких програм ключовим моментом є те, що системні типи даних визначені тільки в стандартних заголовних файлах, таких як stath і dirh, і програма включає в себе ці файли, а не використовує власні визначення типів У такого коду набагато більше шансів виявитися стерпним з однієї системи в іншу

Не дивуйтеся, що як мінімум дві третини коду програми sv – це перевірка помилок На початкових етапах написання програми є спокуса заощадити на обробці помилок, так як це не входить в постановку основного завдання А коли програма «запрацює», вже не вистачає ентузіазму для того, щоб повернутися назад і вставити перевірки, які перетворять приватну програму в стійко працюючий продукт

Програма sv не захищена від усіх можливих нещасть, наприклад вона не обробляє переривання в незручний час, але вона більш осто-

рожна, ніж більшість програм Зупинимося буквально на одному моменті – розглянемо останній оператор write Рідко трапляється, що write не виконується успішно, тому багато програми ігнорують таку можливість Але на дисках закінчується вільне місце користувачі перевищують квоти відбуваються обриви ліній звязку Всі ці обставини можуть послужити причиною помилок запису, і буде набагато краще, якщо користувач дізнається про це, замість того щоб програма мовчки робила вигляд, що все добре

Мораль в тому, що перевірка помилок нудна і втомлює, але надзвичайно важлива Через обмеженого простору і бажання сконцентрувати увагу на найцікавіших питаннях автори опускали цю частину у багатьох програмах, розглянутих в даній книзі Але в справжніх програмних продуктах ви не можете дозволити собі ігнорувати помилки

Вправа 710Змініть checkmail таким чином, щоб ідентифікувати відправника листа в повідомленні You have mail (Ви підлозі чилі лист) Підказка: sscanf, lseek ~

Вправа 711Змініть checkmail так, щоб каталог не змінювався на поштову до входу в цикл Чи буде це мати значення для продуктивності (Сложнее) Чи можете ви написати версію checkma-il, якій був потрібний б тільки один процес для оповіщення всіх користувачів ~

Вправа 712Напишіть програму watchfile, яка перевіряє файл і друкує його з початку кожного разу, коли він змінюється Де можна використовувати таку програму ~

Вправа 713Програма sv не володіє гнучкістю в обробці помилок Змініть її так, щоб вона тривала навіть у тому випадку, коли вона не може обробити деякі файли ~

Вправа 714Зробіть sv рекурсивної: якщо один з вихідних файлів – це каталог, нехай каталог і файли з нього обробляються однаково Зробіть cp рекурсивної Подумайте, чи повинні cp і sv бути однією і тією ж програмою, так щоб cp-v не створювала копію в тому випадку, коли файл призначення більш новий ~

Вправа 715 Напишіть програму random:

$ random імя5файла

яка виводить один рядок, випадковим чином вибрану з фай ла Якщо random обробляє файл з іменами, то вона може бути використана в програмі scapegoat, яка допомагає знайти винуватого:

$ cat  scapegoat

echo &quotIt’s all ‘random  people‘’s fault&quot

$ scapegoat

It’s all Ken’s  fault

$

Переконайтеся, що random працює правильно незалежно від розподілу довжин рядків ~

Вправа 716У індексному дескрипторі міститься і інша інформація, як, наприклад, адреси на диску, в яких розташовані блоки файлів Дослідіть файл sys / inoh, а потім напишіть програму icat, яка буде читати файли, що визначаються за індексному дескриптору і дискового пристрою (Природно, вона буде працювати тільки за умови, що розглянутий диск читаємо) За яких умов корисна icat ~

Джерело: Керниган Б, Пайк Р, UNIX Програмне оточення – Пер з англ – СПб: Символ-Плюс, 2003 – 416 с, Мул

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*