|
Программирование >> Структура ядра и системные вызовы
в ОС UNIX с помошью функции link нельзя создавать жесткие ссылки, указывающие на файлы, которые находятся в других файловых системах. Более того, link можно использовать с каталогами только в том случае, если она вызывается процессом, имеющим права привилегированного пользователя. В ОС UNIX с помошью API link реализована команда In. Вот простая версия программы In, которая не поддерживает опцию s (создание символической ссылки): /* test ln.C */ ♦include <iostream.h> tinclude <stdio.h> ♦include <unistd.h> int main ( int argc, char* argv[] ), { if ( argc!=3 ) { cerr usage: argv[0] <src file> <dest file>\n ; return 0; if ( link ( argvtl], argv[2] ) == -1 ) { perror( link ) ; return 1; return 0; 7.1.9. Функция unlink Функция unlink удаляет ссылку на существующий файл. Эта функция уменьшает значение счетчика жестких ссылок указанного файла и удаляет соответствующую запись из каталога. Если функция выполнена успешно, то к данному файлу уже нельзя будет обращаться с помошью этой ссылки. Файл удаляется из файловой системы, когда счетчик его жестких ссылок становится равным нулю и ни один процесс не использует дескриптор, обозначающий этот файл. Вот прототип функции unlink: #include <unistd.h> int unlink { const char* curjink ); Аргумент curjink - это путевое имя существующего файла. Если вызов успешен, возвращается 0; в противном случае возвращается -1. Неудачный вызов unlink может быть обусловлен неправильным заданием аргумента (файла с таким именем нет), отсутствием у вызывающего процесса разрешения на удаление этого путевого имени и, наконец, прерыванием функции каким-либо сигналом. В ОС UNIX функция unlink может удалить каталог только в том случае, если вызывающему процессу назначены права привилегированного пользователя. В ANSI С определена функция rename, которая выполняет операцию, аналогичную unlink. Если аргументом функции rename Служит пустой каталог, она удаляет его. Прототип функции rename имеет следующий вид: #include <stdio.h> v.: К int rename ( const char* old path name, const char* new path name ); И функция link, и функция rename возвращают код ошибочного завершения, если создаваемая ссылка и исходный файл находятся в разных файловых системах (или в разных разделах диска). В ОС UNIX с помошью API link и unlink можно реализовать команду mv. Ниже приведена простая версия программы mv: ♦include <iostream.h> tinclude <stdio.h> ♦include <unistd.h> int main ( int argc, char* argvl] ) { if ( argc!=3 )!strcmp(argv[1], argv[2]) ) cerr usage: argvfO] <old link> <new link>\n ; else if (link (argv[l], argv[2]) == 0) return unlink(argv[1]); return -1; В командной строке этой программы даны два аргумента: oldlink и new Jink. Сначала программа проверяет, являются ли эти аргументы разными путевыми именами; в этом случае программа просто завершает свою работу, поскольку изменять нечего. Затем программа вызывает функцию link для создания new Jink как новой ссылки на oldjink. Если функция link не выполняется, программа вьщает код возврата -1; в противном случае она вызывает unlink для удаления oldjink и возвращает значение, равное коду возврата функции unlink. 7.1.10. Функции stat и fstat Функции stat и fstat возвращают атрибуты заданного файла. Различие между ними состоит в том, что первый аргумент stat - это путевое имя файла, тогда как первый аргумент fstat является дескриптором файла. Прототипы функций stat и fstat имеют вид: Второй аргумент обеих рассматриваемых функций - это адрес переменной типа struct stat. Тип данных jrac/.yto/определен в заголовке <sys/stat.h>. Объявление этой структуры, одинаковое для UNIX и POSIX.l, выглядит следующим образом: struct stat { dev ts t dev; ino t st ino; mo de t S tmo de; nlink t uid t /* идентификатор файловой системы */ /* номер индексного дескриптора файла */ /* содержит тип файла и флаги доступа */ St nlink; /* значение счетчика жестких ссылок */ st uid; /* идентификатор владельца файла */ gid t st gid; /* идентификатор группы */ dev t st rdev; /* содержит старший и младший номера устройства off~t st size; /* размер файла в байтах */ time t st atime; /* время последнего доступа */ time t st ratime; /* время последней модификации */ time t st ctime; /* время последнего изменения статуса */ int /stat (const char* path name, struct stat* statv); Если вызов stat или fstat успещен, возвращается 0; в противном случае возвращается -1. Неудача вызова stat и fstat может быть обусловлена неправильным заданием путевого имени файла (в stat) или дескриптора (ъ fstat), отсутствием у вызывающего процесса разрещения на доступ к файлу, а также прерыванием функции каким-либо сигналом. Если в качестве путевого имени в stat задана символическая ссылка, stat преобразует ее и обращается к несимволической ссылке. Так же себя ведет, как вы помните, API open. Следовательно, stat и fstat нельзя использовать для получения атрибутов самих символических ссылок. Для решения этой проблемы в BSD UNIX имеется API Istat. Прототип этой функции такой же, как у stat. Функция Istat ведет себя точно так же, как stat с файлами-несимволиче-скими ссылками. Если же аргумент pathjiame в Istat представляет собой символическую ссылку, данная функция возвращает атрибуты этой символической ссылки, а не того файла, на который она указывает. Функция Istat используется также в UNIX System V.3 и V.4, но в POSIX.l не определена. На базе API stat реализована UNIX-команда Is. Применив эту команду с опцией -/, можно, в частности, вывести на экран данные типа struct stat для указанного файла. Приведенная ниже программа testjs. С эмулирует UNIX-команду Is -/: /* Program to emulate the UNIX Is -1 command */ finclude <iostream.h> finclude <syS/types.h> finclude <sys/stat.h> finclude <unistd.h> finclude <pwd.h> finclude <grp.h> Static char xtbl[10] = rwxrwxrwx ; fifndef MAJOR fdefine MINOR BITS 8 fdefine MAJOR(dev) ((unsigned]dev MINOR BITS) fdefine MINOR(dev) ( dev & MINOR BITS) fendif /* показать тип файла в столбце Static void display file type ( ( Switch (st mode&S IFMT] { case S IFDIR: ofs d; case S IFCHR: ofs c; 1 выходной строки */ ostreams ofs, int st mode ) return; return; case S IFBLK! ofs .b,;Return; case ,S IFREGi. ofs Eeiurn; / case S IFLNK: ofS i; return; /> case S IFIFO: ofs p; return; /> каталог */ байт-ориентированный файл устройства */ блок-ориентированный файл устройства */ обычный файл */ символическая ссылка */ FIFO-файл */ /* показать права доступа для владельца, группы и прочих пользователей, а также все специальные флаги */ static void display acceSS perm ( ostreams ofs, int st mode ) char amode[10]; for (int i=0, j=(l 8); i<9; i++, j =l) amode [ i ] = (s t mode & j ) ?xtbl [ i ] : - ; / * установить права доступа * / if (St mode&S ISUID) amode[2] = (amode[2]==x) ? S ; s; if (St mode&S ISGID) amode[5] = (amode[5]==x) ? G : g; if (St modeSS ISVTX) amode[8] = (amode[8]== x) ? T : t; ofs amode /* перечислить атрибуты одного файла * static void long list (ostreami ofs, char* path name) struct stat Struct group Struct passwd statv; *gr p,v *pw p; int Stat (const char* path name, struct stat* statv); int fstat (const int fdesc, struct stat* statv); if (stat (path name,sstatv) perror( path name ); return; clisplay f ile type ( ofs, statv. st mode ); display access perm( ofs, statv.st mode ); ofs statv.st nlink; /* отобразить значение счетчика жестких ссыпок */ gr p = getgrgid(statv. st gid) ; /* преобразовать GID в имяг труппы */ p} p = getpwuid(statv.st uid); /* преобразовать UID в имя пользователя */ ofs pw p->pw name << gr p->gr name ; if ((statv.st mode&S IFMT) == S IFCHR M (statv.st mode&S IFMT)==S IFBLK) ofs MAJOR(statv.st rdev) , MINOR(statv.st rdev); else ofs statv.st size; /* показать размер файла или старший и младший номера устройства */ ofs ctime(Sstatv.st mtime); /* показать время последней , модификации */ ofs path name endl; /* показать имя файла */ /* главный цикл отображения атрибутов для каждого файла */ int main (int argc, char* argv[]) if (argc==l) cerr usage: argv[0] path name>...\n ; else while (-argc = 1) long list( cout, * ++argv) ; return 0; Эта программа принимает в качестве аргументов одно или несколько путевых имен файлов. Для каждого путевого имени она вызывает функцию longjist с целью отображения атрибутов соответствующего файла в формате UNIX-команды Is -/. Атрибуты каждого файла выводятся в одной физической строке, которая организована следующим образом: первое поле (столбец 1): односимвольный код, описывающий тип файла; второе поле (столбцы 2-4): права доступа для чтения, записи и выполнения, предоставляемые владельцу файла; третье поле (столбцы 5-7): права доступа для чтения, записи и выполнения, предоставляемые группе; четвертое поле (столбцы 8-10): права доступа для чтения, записи и выполнения, предоставляемые прочим пользователям; пятое поле: значение счетчика жестких ссылок на файл; шестое поле: имя владельца файла; седьмое поле: имя группы, владеющей файлом; восьмое поле: размер файла в байтах или старший и младший номера .;, устройства, если это файл байт-ориентированного или блок-ориентированного устройства; девятое поле: дата последней модификации файла; десятое поле: имя файла. Переменная stmode в записи struct stat содержит несколько атрибутов: тип файла, права доступа владельца, права доступа группы, права доступа прочих пользователей, флаг смены идентификатора пользователя (set-UID), флаг смены идентификатора группы (set-GID) и бит-липучку (sticky bit). В заголовке <sys/stat.h> определены макросы, с помощью которых можно извлекать все эти поля, как показано в приведенной выше программе. При кодировании типа файла одним символом соблюдаются правила, принятые в UNIX-команде Is -/: d обозначает каталог, с - байт-ориентированный файл устройства, b - блок-ориентированный файл устройства, - - обычный файл, р - FIFO-файл, / - символическую ссылку. Права доступа для всех категорий пользователей всегда указываются в следующем порядке: чтение, запись, выполнение. Эти виды доступа обозначаются соответственно буквами r,wKx. Дефис на месте одной из этих букв означает, что соответствующий вид доступа для данной категории пользователей запрещен. Флаги set-UID, set-GID и sticky-Qm характерны для UNIX. Если флаг set-UID исполняемого файла установлен, то эффеетивный идентификатор пользователя всех процессов, создаваемых в результате выполнения этого файла, будет совпадать с идентификатором владельца файла. Так, если идентификатор владельца файла равен О (в UNIX это идентификатор привилегированного пользователя), у соответствующего процесса будут права привилегированного пользователя. Точно так же, если у файла установлен флаг set-GID, то эффективный идентификатор группы всех процессов, создаваемых в результате выполнения этого файла, будет совпадать с идентификатором группы. Эффективный идентификатор пользователя и эффективный идентификатор группы процесса служат для определения прав доступа процесса к любому файлу. В частности, ядро сначала сверяет эффективный идентификатор пользователя, от имени которого выполняется процесс, с идентификатором владельца файла. Если они совпадают, процессу для доступа к файлу предоставляются права владельца файла. Если эффективный идентификатор процесса отличается от идентификатора владельца файла, но эффективный идентификатор группы процесса совпадает с идентификатором группы, владеющей файлом, процесс получает права доступа, установленные для группы. В случае полного несоответствия предоставляются права доступа по категории прочие пользователи . Флаги set-UID и set-GID оказываются весьма полезными в некоторых UNlX-программах, например, в программе passwd. Для выполнения этих Программ процессам нужны права привилегированного пользователя (например, чтобы программа passwd могла поменять пользовательский пароль
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |