Unix™ Systems Programming [Electronic resources] : Communication, Concurrency, and Threads نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Unix™ Systems Programming [Electronic resources] : Communication, Concurrency, and Threads - نسخه متنی

Prentice Hall

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید










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 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 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


    / 276