Категории
Самые читаемые
PochitayKnigi » Компьютеры и Интернет » Программное обеспечение » Linux программирование в примерах - Арнольд Роббинс

Linux программирование в примерах - Арнольд Роббинс

Читать онлайн Linux программирование в примерах - Арнольд Роббинс

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 51 52 53 54 55 56 57 58 59 ... 165
Перейти на страницу:

270

271  n = *pairp++;

272  while (--n>=0 && (flags&*pairp++)==0)

273   pairp++;

274  putchar(*pairp);

275 }

Строки 245–275 выдают права доступа к файлу. Код компактен и довольно элегантен, он требует тщательного изучения.

• Строки 245–253: массивы с m1 по m9 кодируют биты прав доступа для проверки вместе с соответствующими буквами для вывода. На каждую выводимую букву режима файла имеется один массив. Первый элемент каждого массива является числом пар (право доступа, буква), закодированных в данном конкретном массиве. Последний элемент является буквой, которая должна быть выведена в случае, если не найден ни один из битов прав доступа.

Обратите также внимание, что права доступа обозначены как 'I_READ>>0', 'I_READ>>3', 'I_READ>>6' и т.д. Отдельные константы для каждого бита (S_IRUSR, S_IRGRP и т.п.) не были еще придуманы. (См. табл. 4.5 в разделе 4 6.1 «Указание начальных прав доступа к файлу».)

• Строка 255: массив m указывает на каждый из массивов с m1 по m9.

• Строки 257–264: функция pmode() сначала устанавливает глобальную переменную flags равной переданному параметру aflag. Затем она просматривает в цикле массив m, передавая каждый элемент функции select(). Переданный элемент представляет один из массивов с m1 по m9.

• Строки 266–275: функция select() понимает структуру каждого из массивов с m1 по m9. n является числом пар в массиве (первый элемент); его устанавливает строка 271. Строки 272–273 ищут биты прав доступа, проверяя установленную ранее в строке 261 глобальную переменную flags.

Обратите внимание на использование оператора ++ как в проверке цикла, так и в теле цикла. Результатом является пропуск пары в массиве, если в flags не обнаружен бит доступа в первом элементе пары.

Когда цикл завершается, либо бит разрешения был найден, в этом случае pairp указывает на второй элемент пары, являющийся нужным для вывода символом, либо он не был найден, в этом случае pairp указывает на символ по умолчанию. В любом случае, строка 274 выводит символ, на который указывает pairp.

Последним стоящим внимания моментом является то, что на С символьные константы (такие как 'x') имеют тип int, а не char[75]. Поэтому проблем с помещением этих констант в массив целых нет; все работает правильно.

277 char* /* char *makename(char *dir, char *file) */

278 makename(dir, file)

279 char *dir, *file;

280 {

281  static char dfile[100];

282  register char *dp, *fp;

283  register int i;

284

285  dp = dfile;

286  fp = dir;

287  while (*fp)

288   *dp++ = *fp++;

289  *dp++ = '/';

290  fp = file;

291  for (i=0; i<DIRSIZ; i++)

292   *dp++ = * fp++;

293  *dp = 0;

294  return(dfile);

295 }

Строки 277–295 определяют функцию makename(). Ее работа заключается в соединении имени каталога с именем файла, разделенным символом косой черты, с образованием строки. Она осуществляет это в static буфере dfile. Обратите внимание, что dfile всего лишь 100 символов длиной и что проверка ошибок не выполняется.

Сам код прост, он копирует по одному символу за раз. makename() используется функцией readdir().

297 readdir(dir) /* void readdir(char *dir) */

298 char *dir;

299 {

300  static struct direct dentry;

301  register int j;

302  register struct lbuf *ep;

303

304  if ((dirf = fopen(dir, "r")) == NULL) {

305   printf("%s unreadablen", dir);

306   return;

307  }

308  tblocks = 0;

309  for(;;) {

310   if (fread((char*)&dentry, sizeof(dentry), 1, dirf) != 1)

311    break;

312   if (dentry.d_ino==0

313    || aflg==0 && dentry.d_name[0]=='.' && (dentry.d_name[1]==''

314    || dentry.d_name[1]=='.' && dentry, d_name[2]==''))

315    continue;

316   ep = gstat(makename(dir, dentry.d_name), 0);

317   if (ep==NULL)

318    continue;

319   if (ep->lnum != -1)

320    ep->lnum = dentry.d_ino;

321   for (j =0; j<DIRSIZ; j++)

322    ep->ln.lname[j] = dentry.d_name[j];

323  }

324  fclose(dirf);

325 }

Строки 297–325 определяют функцию readdir(), чья работа заключается в чтении содержимого каталогов, указанных в командной строке.

Строки 304–307 открывают каталог для чтения, завершая функцию, если fopen() возвращает ошибку. Строка 308 инициализирует глобальную переменную tblocks нулем. Ранее (строки 153–154) это использовалось для вывода общего числа блоков, использованных файлами в каталоге.

Строки 309–323 являются циклом, который читает элементы каталога и добавляет их к массиву flist. Строки 310–311 читают один элемент, выходя из цикла в конце файла.

Строки 312–315 пропускают неинтересные элементы. Если номер индекса равен нулю, этот слот не используется. В противном случае, если не был указан -а и имя файла является '.' или '..', оно пропускается.

Строки 316–318 вызывают gstat() с полным именем файла и вторым аргументом, равным false, указывающим, что он не из командной строки. gstat() обновляет глобальный указатель lastp и массив flist. Возвращаемое значение NULL обозначает какую-нибудь разновидность ошибки.

Строки 319–322 сохраняют номер индекса и имя в struct lbuf. Если ep->lnum возвращается из gstat() установленным в -1, это означает, что операция stat() с файлом завершилась неудачей. Наконец, строка 324 закрывает каталог.

Следующая функция, gstat() (строки 327–398), является центральной функцией для получения и сохранения сведений о файле.

327 struct lbuf * /* struct lbuf *gstat(char *file, int argfl) */

328 gstat(file, argfl)

329 char *file;

330 {

331  extern char *malloc();

332  struct stat statb;

333  register struct lbuf *rep;

334  static int nomocore;

335

336  if (nomocore) /* Ранее была нехватка памяти */

337   return(NULL);

338  rep = (struct lbuf*)malloc(sizeof(struct lbuf));

339  if (rep==NULL) {

340   fprintf(stderr, "ls: out of memoryn");

341   nomocore = 1;

342   return(NULL);

343  }

344  if (lastp >= &flist[NFILES]) { /* Проверить, не дано ли слишком много файлов */

345   static int msg;

346   lastp--;

347   if (msg==0) {

348    fprintf(stderr, "ls: too many filesn");

349    msg++;

350   }

351  }

352  *lastp++ = rep; /* Заполнить сведения */

353  rep->lflags = 0;

354  rep->lnum = 0;

355  rep->ltype = '-'; /* Тип файла по умолчанию */

Статическая переменная nomocore [важно] указывает, что malloc() при предыдущем вызове завершилась неудачей. Поскольку она статическая, она автоматически инициализируется 0 (т.е. false). Если на входе она равна true, gstat() просто возвращает NULL. В противном случае, если malloc() завершается неудачей, ls выводит сообщение об ошибке, устанавливает в nomocore true и возвращает NULL (строки 334–343).

Строки 344–351 гарантируют, что в массиве flist все еще остается место. Если нет, ls выдает сообщение (но лишь однажды; заметьте использование статической переменной msg), а затем повторно использует последний слот flist.

Строка 352 заставляет слот lastp указывать на новую struct lbuf (rep). Это также обновляет lastp, который используется для сортировки в main() (строки 142 и 152). Строки 353–355 устанавливают значения по умолчанию для полей флагов, номеров индексов и типов в struct lbuf.

356  if (argfl || statreq) {

357   if (stat(file, &statb)<0) { /* stat() завершилась неудачей */

358    printf("%s not foundn", file);

359    statb.st_ino = -1;

360    statb.st_size = 0;

361    statb.st_mode = 0;

362    if (argfl) {

363     lastp--;

364     return(0);

365    }

366   }

367   rep->lnum = statb.st_ino; /* stat() OK, копировать сведения */

368   rep->lsize = statb.st_size;

369   switch(statb.st_mode & S_IFMT) {

370

371   case S_IFDIR:

372    rep->ltype = 'd';

373    break;

374

375   case S_IFBLK:

376    rep->ltype = 'b';

377    rep->lsize = statb.st_rdev;

378    break;

379

380   case S_IFCHR:

381    rep->ltype = 'c';

382    rep->lsize = statb.st_rdfev;

383    break;

384   }

385   rep->lflags = statb.st_mode & ~S_IFMT;

386   rep->luid = statb.st_uid;

387   rep->lgid = statb.st_gid;

388   rep->lnl = statb.st_nlink;

389   if (uflg)

390    rep->lmtime = statb.st_atime;

391   else if (cflg)

1 ... 51 52 53 54 55 56 57 58 59 ... 165
Перейти на страницу:
Тут вы можете бесплатно читать книгу Linux программирование в примерах - Арнольд Роббинс.
Комментарии