|
Программирование >> Структура ядра и системные вызовы
аргумента buf. В случае успешного выполнения readlink возврашает количество символов путевого имени, помешенного в аргумент buf а в случае неудачи возврашает -1. Возможные причины неудачи: путевое имя symjink не является символической ссылкой, аргумент /)и/представляет собой неверный адрес, у вызывающего процесса нет прав доступа к символической ссылке. Следующая функция принимает в качестве аргумента путевое имя символической ссылки и многократно вызывает readlink для получения имени файла, на который указывает эта ссылка. Цикл while завершается, когда 1 readlink возвращает -1, при этом переменная buf содержит путевое имя реального файла, которое затем направляется на стандартный вывод: finclude <iostream.h> finclude <sys/types.h> finclude <unistd.h> finclude <string.h> int resolve link( const char* sym link ) { char* buf[256), tname[256}; strcpy(tname, sym link); while ( readlink( tname, buf, sizeof ( buf ) ) > 0 ) strcpy( tname, buf ); cout sym limk => buf endl; Функция Istat используется для получения атрибутов файлов символических ссылок. Она необходима по той причине, что функции stat и fstat сообщают атрибуты только несимволических ссылок. Прототип и возвращаемые значения функции Istat - такие же, как и у функции stat. Более того, Istat можно использовать и с несимволическими ссылками, поскольку она работает как stat. UNIX-команда Is -I использует Istat для отображения информации о файлах всех типов, включая символические ссьшки. Ниже приведена программа test symln.C, которая эмулирует UNIX-ko-манду In. Основное назначение этой программы - создание ссылок на файл. Имена исходного файла и новой ссылки являются аргументами. Если опция -5 не указана, программа создает жесткую ссылку, в противном случае - символическую: finclude <iostream.h> finclude <sys/types.h> finclude <unistd.h> finclude <string.h> /* Эмуляция UNIX-команды In */ int main (int argc, char* argv[]) { char* buf[256], tname[256}; if ((argc< 3 && argc > 4) (argc==4 && strcmp(argv[1}, -s ))) { cout usage: argv[0] [-s] <orig file> <new link>\n ; return 1; if (argc==4) return symlink( argv[2], argv[3]); /* создает символическую ссылку */ else return link(argv[l], argv[2]); /* создает жесткую осыпку */ return 0; 7.7. Общий класс для файлов Класс fstream в языке С++ служит для определения объектов, которые служат для представления файлов. В частности, класс fstream содержит функции-члены open, close, read, write, tellg и seekg, которые построены на API open, read, write и Iseek. Таким образом, любая прикладная программа может определить объекты класса fstream, предназначенные для чтения и записи файлов. Следует отметить, однако, что в классе fstream нет никаких средств для выполнения функций stat, chmod, chown, utime и link с его объектами. Кроме того, здесь могут создаваться только обычные файлы. Таким оЬщзои, fstream не обеспечивает выполнения полного набора характерных для POSIX- и UNIX-систем функций, предназначенных для работы с файловыми объектами. Чтобы устранить этот недостаток, ниже определяется новый класс, filebase, который обладает свойствами класса fstream и содержит дополнительные функции, позволяющие пользователям получать атрибуты файловых объектов, изменять их и создавать жесткие ссьшки: fifndef FILEBASE H fdefine FILEBASE Н /* filebase.h header */ finclude <iostream.h> finclude <fstream.h> finclude <sys/types.h> finclude <sys/stat.h> finclude <unistd.h> finclude <utime.h> finclude <fcntl.h> finclude <string.h> typedef enum { REG FILE=r, BLK FILE=b DIR FILE=dCHAR FILE=C, PIPE FiLE=p, SyM FILE=s, UNKNOWN FILE=?) FILE TyPE ENUM; /* Базовый класс, инкапсутофукщий свойства файловых о&ьектов Ю31Х и UNIX */ class filebase: public , fstream protected: char* filename; friend ostreams operator (ostreams os, filebases fobj) /* Вывести атрибуты файла в формате UNIX-команды Is -1 */ return OS; public: filebaseO {;); filebase(const char* fn, int flags, int prot=filebuf::openprot) : fstreamffn,flags,prot) filename = new char[strlen (fn)+1]; strcpy(filename,fn); virtual -filebaseO { delete filename; }; int fileno0 ( return rdbuf()->fd{); ); virtual int create( const char* fn, mode t mode) { return ::creat(fn, mode); }; int chmod(mode t mode) { return ::chmod (filename, mode); ); int chown( uid t uid, gid t gid ) { return ::chown(filename, uid, gid); ); int utime(const struct utimbuf *timbuf Ptr) { return ::utime(filename,timbuf Ptr); }; int linlc( const char* new linlc) s l { return :: linlc (filename, new lin)c); ) ; virtual int remove( ) { return : :unlinlc (filename) ; ); Запросить тип файла для объекта классёг filebase FILE TYPE ENUM file type() ( struct stat statv; if (stat(filename,Sstatv)==0) switch (statv.st mode S S IFMT) case S IFREG: return REG FILE; case S IFDIR: return DIR FILE; case S IFCHR: return CHAR FILE; case S IFIFO: return PIPE FILE; case S IFLNK: return SYM FILE; обычный файл каталог байт-ориентированный файл устройства блок-ориентированный файл устройства символическая ссылка return UNKNOWN FILE; #endif /* filebase.h */ Конструктор filebase передает свои аргументы конструктору своего над-класса fstream для соединения (с заданным режимом доступа) объекта с файлом, указанным в аргументе fn. Затем конструктор автоматически выделяет динамический буфер для хранения путевого имени fn в закрытой переменной filename. Переменная filename используется в других функциях-членах, таких как chmod, link, remove и т.д. Деструктор filebase освобождает динамический буфер filename, а затем с помощью деструктора fstream отсоединяет объект от файла, заданного аргументом filename. Функция-член fileno возвращает дескриптор файла, которым управляет объект класса filebase. Функция-член chmod помогает пользователям изменить права доступа к файлу, соединенному с объектом класса filebase. Аргумент mode - такой же, как у функции chmod стандарта POSIX. 1, а переменная filename определяет, права доступа к какому файлу нужно изменить. Функция-член chown помогает пользователям изменить идентификатор владельца и идентификатор группы для файла, соединенного с объектом класса filebase. Аргументы uid и gid - те же, что у функции chown стандарта POSIX. 1; переменная filename показывает, принадлежность какого файла нужно изменить. Функция-член utime помогает пользователям изменить дату и время доступа и модификации файла, соединенного с объектом класса filebase. Аргумент timbuf Ptr - такой же, как у функции utime стандарта POSIX. 1, а переменная filename определяет, у какого файла нужно изменить эти атрибуты. Функция-член link позволяет пользователям создать жесткую ссылку на файл, соединенный с объектом класса filebase. Аргумент newjink содержит имя новой ссылки. Первоначальная ссылка на файл, соединенный с объектом, берется из переменной filename данного объекта. Для создания новой жесткой ссылки эта функция вызывает функцию link стандарта POSIX. 1. Функция-член create создает файл с заданным именем. Для этого ей необходимо вызвать функцию API creat. Функция-член create применима только к обычным файлам. Функция-член remove удаляет ссылку, заданную переменной filename объекта. При успешном завершении такого вызова ни один процесс не сможет обращаться к данному файлу по этому путевому имени. Перегруженная операция в ostream используется для вывода атрибутов файла, соединенного с объектом класса filebase. Эта функция может вызывать функцию longlist (см. раздел 7.1.10) для определения свойств файла, юля которого задано закрытой переменной filename. Функция filejtype определяет тип объекта класса filebase. Она вызывает API stat для заданного filename и определяет тип соответствующего файлового объекта. Эта функция возвращает данные типа FILE TYPE ENUM (номер, соответствующий типу файла). Если вызов stat неудачен или если тип файла объекта не определен, эта функция возвращает значение UNKNOWN FILE. В противном случае она возвращает значение REG FILE, DIR FILE или какое-либо другое. Ниже приведена программа testJilebase.C, которая иллюстрирует использование класса filebase. Здесь определяется объект класса filebase с именем rfile, который необходимо связать для чтения с файлом /usr/text/unix.doc. Затем программа выдает атрибуты файла на стандартный вывод и заменяет идентификатор пользователя и идентификатор группы файла соответственно на 15 и 30. Далее программа изменяет время доступа и модификации файла на текущее и создает жесткую ссылку /home/jon/hdink. Наконец, удаляется первоначальная ссылка /usr/text/unix.doc. finclude filebase.h int main() ( определить объект filebase rfile( /ust/tejct/unix.doc ,ios::in); .ci 01-:. <Л\ cout rfile endjiH- jR вывести атрибуты файла;, rfile. chown (15, 30); jj / изменить UID и GID rfile.,utime(0); U изменить время доступа* rfile.linl<( /home/jon/hdlnk ) ; создать жесткую ссылку . rfile. remove С); .5ff; y удалить старую ссьшку return 0; } т . В классе filebase определяются родовые функции для всех типов файлов, допустимых в POSIX и UNIX. Следует отметить, однако, что здесь нет никаких средств для создания файлов, отличных от обычных, и не осуществляется поддержка операций, зависящих от типа файла (например, не поддерживается блокировка файлов). Чтобы устранить эти недостатки, были созданы новые подклассы ьсласса filebase, которые обеспечивают полную инкапсуляцию данных для файлов UNIX и POSIX различных типов. Эти подклассы описаны в следующих разделах, 7.8. Класс regfile для обычных файлов Класс filebase инкапсулирует больщинство свойств и функций, необходимых для представления обычных файловых объектов в POSIX- и UNIX-системах, за исключением блокировки файлов. Класс гефк определяется как подкласс класса filebase, но включает функции блокировки файлов. Таким образом, объекты класса гефк могут выполнять все операции над обычными файлами, допустимые в POSIX и UNIX. \ Класс regfile определяется следующим o6pa30fttis;: fifndef REGFILE H Ч! fdefine REGFILE H finclude filebase.h /* Класс, инкапсулирующий свойства обычных файловых объектов POSIX и UNIX */ . class regfile: public filebase I public: regfile( const char*fnm, int mode, int prot) : filebase(fnm,mode,prot) . . {}; -regjEile.O , {}; int lock( int lck type, off t len, int cmd=F 5ETLK) . ( struct flock flck; if ((lck type&ios::in) == ios::in) flck.l type - F RDLCK; else if ((lck type S ios::out)==ios::out) flck.l type = F WRLCK; else return -1; flck.l whence = SEEK CUR; flck.l start = (off t)0; flck.l len = len; return fcntl(fileno 0,cmd,Sflck); int lockw( int lck type, off t len) ( return lock(lck type, len, F SETLKW); }; int unlock( off t len) ( struct flock flck; flck.l type = F UNLCK; flck.l whence = SEEK CUR; flck.l start = (off t)0; flck.l len = len; return fcntl(fileno(),F SETLK,&flck); int getlock( int Icktype, off t len, struct flocks flck) { if ( (lck typeSios : :inf) == ios:: in) ,flck.l type = F RDLCK; else if ((lck type s ios::out)==ios::out) , flck.l type~= F WRLCK; C else return -1; flck.l whence = SEEK CUR; flck.l start = (off t)0; flck.l len = len; return fcntl(fileno0,F GEtLK,&fIck); fendif /* regfile.h */ Функция regfile:.-lock устанавливает блокировку чтения (lck type = ios::in) или блокировку записи {lck type = ios::out) на область файла, связанного с объектом класса regfile. Начальным адресом блокируемой области является текущий указатель позиции в файле. Его можно установить функцией fstream::seekg. Размер блокируемой области в байтах задается аргументом len. Функция regfile::lock по умолчанию не блокирует вызывающий процесс (т.е. является неблокирующей). Если задать аргумент cmd как F SETLKW или вызвать эту функцию из функции regfile::tockw, функция будет блокирующей. Возвращаемое значение функции regflle:.iock то же самое, что и для функции fcntl в операции блокировки файла. Функция regfile::lockw - это оболочка функции regfile::lock. Она работает в блокирующем режиме. Возвращаемое ею значение совпадает с возвращаемым значением функции regfile::tock.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |