is of type mode_t and the value of buf is a pointer to a struct stat structure.

Team-FLY

5.2 Directory Access

Directories should not be accessed with the ordinary open , close and read functions. Instead, they require specialized functions whose corresponding names end with "dir" : opendir , closedir and readdir .

The opendir function provides a handle of type DIR * to a directory stream that is positioned at the first entry in the directory.

  SYNOPSIS  #include <dirent.h>    DIR *opendir(const char *dirname);  POSIX  

If successful, opendir returns a pointer to a directory object. If unsuccessful , opendir returns a null pointer and sets errno . The following table lists the mandatory errors for opendir .

errno

cause

EACCES

search permission on a path prefix of dirname or read permission on dirname is denied

ELOOP

a loop exists in resolution of dirname

ENAMETOOLONG

the length of dirname exceeds PATH_MAX , or a pathname component is longer than NAME_MAX

ENOENT

a component of dirname does not name an existing directory

ENOTDIR

a component of dirname is not a directory

The DIR type, which is defined in dirent.h represents a directory stream . A directory stream is an ordered sequence of all of the directory entries in a particular directory. The order of the entries in a directory stream is not necessarily alphabetical by file name .

The readdir function reads a directory by returning successive entries in a directory stream pointed to by dirp . The readdir returns a pointer to a struct dirent structure containing information about the next directory entry. The readdir moves the stream to the next position after each call.

  SYNOPSIS  #include <dirent.h>    struct dirent *readdir(DIR *dirp);  POSIX  

If successful, readdir returns a pointer to a struct dirent structure containing information about the next directory entry. If unsuccessful, readdir returns a NULL pointer and sets errno . The only mandatory error is EOVERFLOW , which indicates that the value in the structure to be returned cannot be represented correctly. The readdir function also returns NULL to indicate the end of the directory, but in this case it does not change errno .

The closedir function closes a directory stream, and the rewinddir function repositions the directory stream at its beginning. Each function has a dirp parameter that corresponds to an open directory stream.

  SYNOPSIS  #include <dirent.h>    int closedir(DIR *dirp);    void rewinddir(DIR *dirp);  POSIX  

If successful, the closedir function returns 0. If unsuccessful, it returns “1 and sets errno . The closedir function has no mandatory errors. The rewinddir function does not return a value and has no errors defined.

Program 5.3 displays the filenames contained in the directory whose pathname is passed as a command-line argument.

Program 5.3 shownames.c

A program to list files in a directory .

 #include <dirent.h> #include <errno.h> #include <stdio.h> int main(int argc, char *argv[]) {    struct dirent *direntp;    DIR *dirp;    if (argc != 2) {       fprintf(stderr, "Usage: %s directory_name\n", argv[0]);       return 1;    }    if ((dirp = opendir(argv[1])) == NULL) {       perror ("Failed to open directory");       return 1;    }    while ((direntp = readdir(dirp)) != NULL)       printf("%s\n", direntp->d_name);    while ((closedir(dirp) == -1) && (errno == EINTR)) ;    return 0; } 
Exercise 5.7

Run Program 5.3 for different directories. Compare the output with that from running the ls shell command for the same directories. Why are they different?

Answer:

The ls command sorts filenames in alphabetical order. The readdir function displays filenames in the order in which they occur in the directory file.

Program 5.3 does not allocate a struct dirent variable to hold the directory information. Rather, readdir returns a pointer to a static struct dirent structure. This return structure implies that readdir is not thread-safe. POSIX includes readdir_r as part of the POSIX:TSF Extension, to provide a thread-safe alternative.

POSIX only requires that the struct dirent structure have a d_name member, representing a string that is no longer than NAME_MAX . POSIX does not specify where additional information about the file should be stored. Traditionally, UNIX directory entries contain only filenames and inode numbers . The inode number is an index into a table containing the other information about a file. Inodes are discussed in Section 5.3.

5.2.1 Accessing file status information

This section describes three functions for retrieving file status information. The fstat function accesses a file with an open file descriptor. The stat and lstat functions access a file by name.

The lstat and stat functions each take two parameters. The path parameter specifies the name of a file or symbolic link whose status is to be returned. If path does not correspond to a symbolic link, both functions return the same results. When path is a symbolic link, the lstat function returns information about the link whereas the stat function returns information about the file referred to by the link. Section 5.4 explains symbolic links. The buf parameter points to a user -supplied buffer into which these functions store the information.

  SYNOPSIS  #include <sys/stat.h>   int lstat(const char *restrict path, struct stat *restrict buf);   int stat(const char *restrict path, struct stat *restrict buf);  POSIX  

If successful, these functions return 0. If unsuccessful, they return “1 and set errno . The restrict modifier on the arguments specifies that path and buf are not allowed to overlap . The following table lists the mandatory errors for these functions.

errno

cause

EACCES

search permission on a path component denied

EIO

an error occurred while reading from the file system

ELOOP

a loop exists in resolution of path

ENAMETOOLONG

the length of the pathname exceeds PATH_MAX ( lstat ), the length of path exceeds PATH_MAX ( stat ), or a pathname component is longer than NAME_MAX

ENOENT

a component of path does not name an existing file

ENOTDIR

a component of the path prefix is not a directory

EOVERFLOW

the file size in bytes, the number of blocks allocated to file or the file serial number cannot be represented in the structure pointed to by buf

The struct stat structure, which is defined in sys/stat.h , contains at least the following members .

 dev_t     st_dev;       /* device ID of device containing file */ ino_t     st_ino;       /* file serial number */ mode_t    st_mode;      /* file mode */ nlink_t   st_nlink;     /* number of hard links */ uid_t     st_uid;       /* user ID of file */ gid_t     st_gid;       /* group ID of file */ off_t     st_size;      /* file size in bytes (regular files) */                         /* path size (symbolic links) */ time_t    st_atime;     /* time of last access */ time_t    st_mtime;     /* time of last data modification */ time_t    st_ctime;     /* time of last file status change */ 
Example 5.8 printaccess.c

The following function displays the time that the file path was last accessed.

 #include <stdio.h> #include <time.h> #include <sys/stat.h> void printaccess(char *path) {    struct stat statbuf;    if (stat(path, &statbuf) == -1)       perror("Failed to get file status");    else       printf("%s last accessed at %s", path, ctime(&statbuf.st_atime)); } 
Exercise 5.9 printaccessmodbad.c

What is wrong with the following function that attempts to print both the access time and the time of modification of a file? How would you fix it?

 #include <stdio.h> #include <time.h> #include <sys/stat.h> void printaccessmodbad(char *path) {    struct stat statbuf;    if (stat(path, &statbuf) == -1)       perror("Failed to get file status");    else      printf("%s accessed: %s modified: %s", path,             ctime(&statbuf.st_atime), ctime(&statbuf.st_mtime)); } 

Answer:

The string returned by ctime ends with a newline, so the result is displayed on 2 lines. More importantly, ctime uses static storage to hold the generated string, so the second call to ctime will probably write over the string containing the access time. To solve the problem, save the access time in a buffer before calling ctime the second time, as in the following code. An alternative would be to use two separate print statements. After the strncpy call, the string is terminated at the position that would have contained the newline.

printaccessmod.c

 #include <stdio.h> #include <string.h> #include <time.h> #include <sys/stat.h> #define CTIME_SIZE 26 void printaccessmod(char *path) {    char atime[CTIME_SIZE];   /* 26 is the size of the ctime string */    struct stat statbuf;    if (stat(path, &statbuf) == -1)       perror("Failed to get file status");    else {       strncpy(atime, ctime(&statbuf.st_atime), CTIME_SIZE - 1);       atime[CTIME_SIZE - 2] = 0;       printf("%s accessed: %s modified: %s", path, atime,                ctime(&statbuf.st_mtime));    } } 

The fstat function reports status information of a file associated with the open file descriptor fildes . The buf parameter points to a user-supplied buffer into which fstat writes the information.

  SYNOPSIS  #include <sys/stat.h>   int fstat(int fildes, struct stat *buf);  POSIX  

If successful, fstat returns 0. If unsuccessful, fstat returns “1 and sets errno . The following table lists the mandatory errors for fstat .

errno

cause

EBADF

fildes is not a valid file descriptor

EIO

an I/O error occurred while reading from the file system

EOVERFLOW

the file size in bytes, the number of blocks allocated to file or the file serial number cannot be represented in the structure pointed to by buf

5.2.2 Determining the type of a file

The file mode member st_mode specifies the access permissions of the file and the type of file. Table 4.1 on page 105 lists the POSIX symbolic names for the access permission bits. POSIX specifies the macros of Table 5.1 for testing the st_mode member for the type of file. A regular file is a randomly accessible sequence of bytes with no further structure imposed by the system. UNIX stores data and programs as regular files. Directories are files that associate filenames with locations, and special files specify devices. Character special files represent devices such as terminals; block special files represent disk devices. The ISFIFO tests for pipes and FIFOs that are used for interprocess communication.Chapter 6 discusses special files, and Chapter 14 discusses interprocess communication based on message queues, semaphores and shared memory.

Example 5.10 isdirectory.c

The isdirectory function returns true (nonzero) if path is a directory, and false (0) otherwise .

 #include <stdio.h> #include <time.h> #include <sys/stat.h> int isdirectory(char *path) {    struct stat statbuf;    if (stat(path, &statbuf) == -1)       return 0;    else       return S_ISDIR(statbuf.st_mode); } 
Table 5.1. POSIX macros for testing for the type of file. Here m is of type mode_t and the value of buf is a pointer to a struct stat structure.

macro

tests for

S_ISBLK ( m )

block special file

S_ISCHR ( m )

character special file

S_ISDIR ( m )

directory

S_ISFIFO ( m )

pipe or FIFO special file

S_ISLNK ( m )

symbolic link

S_ISREG ( m )

regular file

S_ISSOCK ( m )

socket

S_TYPEISMQ ( buf )

message queue

S_TYPEISSEM ( buf )

semaphore

S_TYPEISSHM ( buf )

shared memory object

Team-FLY


Unix Systems Programming
UNIX Systems Programming: Communication, Concurrency and Threads
ISBN: 0130424110
EAN: 2147483647
Year: 2003
Pages: 274

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net