Basic Unix File System Operations

Source: Internet
Author: User

Article transferred from: http://www.ibm.com/developerworks/cn/aix/library/au-unix-readdir.html#listing2

 

Basic Unix File System Operations

 

Document options

Print this page

Sample Code

Level: elementary

Chris herborth(Chrish@pobox.com), Freelance writer, writer

June 26, 2006

Exploitationreaddir()Andstat()The entries in the function browsing directory. Because there are a large number of files and directories in Unix systems, you need to know how to usereaddir()The function processes these directory entries and how to use them.stat()The function extracts information about these entries. In your UNIX program development work, these basic file system operations can provide you with good services, this allows you to easily discover and read files, directories, and symbolic links in UNIX systems.

Introduction

In UnixEverything is a fileThis means that you will always deal with files and directories, regardless of the type of application you are developing. Everything is stored as a file, from data to configuration files, or even devices. After several hours of learning Unix programming, stdio. h. The functions in the system header will be helpful to you.

A problem that often bothers new users of Unix programming is how to browse a directory and process the files, directories, and symbolic links. How can I obtain their lists and determine what they are?

Continue to read this article to learn how to use the dirent. h Function Series (opendir()/readdir()/closedir()) To read the entries in the directory and usestat()Function to determine the content of these entries.



Back to Top

Before getting started

Sample Code in this article (seeDownloadC/C ++ development tool (CDT) is used in eclipse 3.1. The readdir_demo Project is a managed make project, which is built by using the CDT program to generate rules. You cannot find makefile in this project, but they are very simple. If you need to compile the code outside eclipse, you can easily generate the corresponding makefile.

If you have not tried eclipse, you should try it. It is a very good integrated development environment (IDE), and it becomes more perfect with the continuous update of the release version. It comes from Emacs and makefile-based development tools. SeeReferencesWhich provides links to some good eclipse articles.



Back to Top

Read directory entries

How do I read entries in a directory with a given path? You cannot open a directory like an operating file (Useopen()Orfopen()Function), and even if this can be done, the data obtained may be the dedicated format of the file system you are using, and for unfamiliar programmers, direct access to the data will make the situation worse.

Dirent. H function,opendir(),readdir()Andclosedir()They are exactly what you need. The usage of these functions is similar to that of open, read, and close operations on files, except that for each directory entry,readdir()The function returns a special structure (struct direntType. Generally, browsing a directory is similarListing 1.

Listing 1. Reading contents in the directory

                dir = opendir( "some/path/name" )entry = readdir( dir )while entry is not NULL:    do_something_with( entry )    entry = readdir( dir )closedir( dir )

When a problem occurs,opendir()Andreaddir()The function returns NULL and sets global variables.errnoTo indicate the error. Ifreaddir()Returns NULL, anderrno0 (also known as Eok or enoerror) indicates that no other directory entries exist.

Note that each directory contains "." (reference to this directory) and "." (reference to the parent directory of this directory) entries. Based on your operations, you may need to ignore the processing of these items.

Please note that,readdir()It is not thread-safe, because the returned structure is a static variable stored in the function library. Most modern Unix systems have thread-safereaddir_r()If you are writing thread code, you can use this function as an alternative.



Back to Top

What content does struct dirent contain?

POSIX 1003.1 standard is onlystruct direntDefines a required entry, that ischarArrayd_name. This is the name of the entry ending with null. Any other content in this structure is specific to your UNIX system.

Indeed,struct direntOtherAll ContentAre not portable. Systems that strictly comply with consistency should not include any other content in them. If you have written code that uses an additional structure member, you must mark it as unportable and include a replacement code path to complete the same task, if you think this is especially friendly.

For example, many UNIXd_typeMembers and some additional constants, so that you do not needstat()You can check the type of the directory entries by calling. In addition to reducing other system calls, this portable extension also reduces the overhead of accessing more diverse data from the file system. As we all know, in most UNIX,stat()Function execution is very slow.



Back to Top

Get File Information

In addition to obtaining the name of the entries in the directory, you may need additional information to determine the next operation. At least, you cannot identify file entries Based on the name of the directory entries.

stat()The function will fill in the relevant information of a specific filestruct statStructure, if you get a file descriptor instead of a file name, you can usefstat()Function. If you want to detect symbolic links, you can uselstat().

Andreaddir()Returnedstruct direntDifferent,struct statThere are quite a few standard and required members:

  • st_mode-- File permissions (users, other users, groups) and tags
  • st_ino-- File serial number
  • st_dev-- File device number
  • st_nlink-- File connection count
  • st_uid-- Owner user ID
  • st_gid-- Owner group ID
  • st_size-- File size in bytes (for common files)
  • st_atime-- Last access time
  • st_mtime-- Last modification time
  • st_ctime-- File Creation Time

Pairst_modeMember usageS_*()Macro to find out the type of directory entries you are processing:

  • S_isblk (mode) -- is it a special block file? (Usually a block-based device)
  • S_ischr (mode) -- is it a special character file? (Usually a character-based device)
  • S_isdir (mode) -- is it a directory?
  • S_isfifo (mode) -- is it a special pipe or FIFO file?
  • S_islnk (mode) -- is it a symbolic link?
  • S_isreg (mode) -- is it a common file?

As we all know, in most file systems,stat()Function execution is very slow, so if you plan to use this information again in the future, you may need to cache it.

Symbolic Links

Generally, you do not care about symbolic links. If you call a symbolic linkstat(), You will obtain information about the file to which the link points. This is consistent with the user experience, because controlling the permissions of the target file to interact with the file, rather than the symbolic link itself.

Some applications, suchlsAnd the backup program, you need to be able to display the relevant information of the linked file itself, such as the file it points. When you uselstat()To replacestat()This is also the case when you need to obtain information about the symbolic link itself for a specific purpose, rather than directly dealing with the linked file.



Back to Top

Combine them

Now that you have learned how to usereaddir()Andstat()To find entries in the directory, let's take a look at some actual code that demonstrates these functions.

The code described here will browse one or more Directories specified in the command line and display information about each entry found in the directory. When it finds another directory, it will perform the same processing on the directory. For symbolic links, the target file is displayed, and the size of common files is also displayed. Special files are ignored.

For exampleListing 2As shown in, this simple demo application contains various header files. The program's start block contains the standard part used in most programs, and the following four items are used in the programreaddir()Andstat()Required.

Listing 2. header and constant

                #include <stdio.h>#include <stdlib.h>#include <errno.h>#include <string.h>#include <limits.h>#include <sys/types.h>#include <sys/stat.h>#include <dirent.h>#include <unistd.h>

process_directory()Function (starting fromListing 3, EndedListing 6) Reads the specified directory and displays the information about each entry.opendir()The returned dir pointer correspondsfopen()The returned file pointer is similar. It is an operating system-specific object used to track directory streams. You should ignore the specific content.

Listing 3. processing a directory

                unsigned process_directory( char *theDir ){    DIR *dir = NULL;    struct dirent entry;    struct dirent *entryPtr = NULL;    int retval = 0;    unsigned count = 0;    char pathName[PATH_MAX + 1];    /* Open the given directory, if you can. */      dir = opendir( theDir );    if( dir == NULL ) {        printf( "Error opening %s: %s", theDir, strerror( errno ) );        return 0;    }

After opening the specified directory, callreaddir_r()(SeeListing 4) To obtain information about the first entry, and then callreaddir_r()Will return the next entry until it reaches the end of the directory, andentryPtrSet to null. Here we also usestrncmp()To check the "." and "." entries to skip them. If you do not skip them, you will always be processing directories such as "thedir.

Listing 4. Read a directory entry

                    retval = readdir_r( dir, &entry, &entryPtr );    while( entryPtr != NULL ) {        struct stat entryInfo;                if( ( strncmp( entry.d_name, ".", PATH_MAX ) == 0 ) ||            ( strncmp( entry.d_name, "..", PATH_MAX ) == 0 ) ) {            /* Short-circuit the . and .. entries. */            retval = readdir_r( dir, &entry, &entryPtr );            continue;        }

Now that you have obtained the Directory Entry name, you need to construct a more complete path (seeListing 5), And then calllstat()To obtain information about the entry. Because symbolic links require special processing, we uselstat()Function. You can usereadlink()Function to find the target file.

If the entry is a directory, recursively callprocess_directory()And add the number of items found to the total number of running tasks. If the entry is a file, its name and number of nodes are displayed (struct statOfst_sizeMember ).

Listing 5. Handling entries

                        (void)strncpy( pathName, theDir, PATH_MAX );        (void)strncat( pathName, "/", PATH_MAX );        (void)strncat( pathName, entry.d_name, PATH_MAX );                if( lstat( pathName, &entryInfo ) == 0 ) {            /* stat() succeeded, let's party */            count++;                        if( S_ISDIR( entryInfo.st_mode ) ) {            /* directory */                printf( "processing %s//n", pathName );                count += process_directory( pathName );            } else if( S_ISREG( entryInfo.st_mode ) ) { /* regular file */                printf( "/t%s has %lld bytes/n",                    pathName, (long long)entryInfo.st_size );            } else if( S_ISLNK( entryInfo.st_mode ) ) { /* symbolic link */                char targetName[PATH_MAX + 1];                if( readlink( pathName, targetName, PATH_MAX ) != -1 ) {                    printf( "/t%s -> %s/n", pathName, targetName );                } else {                    printf( "/t%s -> (invalid symbolic link!)/n", pathName );                }            }        } else {            printf( "Error statting %s: %s/n", pathName, strerror( errno ) );        }

InwhileAt the bottom of the loop, read and process another directory entry. If you have processed directory entries, close the currently opened directory and return the number of processed entries.

Listing 6. Read another entry

                        retval = readdir_r( dir, &entry, &entryPtr );    }        /* Close the directory and return the number of entries. */    (void)closedir( dir );    return count;}

Finally,Listing 7Displaysmain()Function. It only calls each parameter passed in the command line.process_directory()Function. A real program should have method-based messages that provide some form of feedback when the user does not specify any parameters, but I leave this content as an exercise for the reader.

Listing 7. Main Line

                /* readdir_demo main() *  * Run through the specified directories, and pass them * to process_directory(). */int main( int argc, char **argv ){    int idx = 0;    unsigned count = 0;        for( idx = 1; idx < argc; idx++ ) {        count += process_directory( argv[idx] );    }        return EXIT_SUCCESS;}

This is the whole program. Although it contains many files, it is not very difficult to process directory entries.



Back to Top

Conclusion

Usereaddir()Andstat()It is very simple to use the function to browse the entries in the directory and determine the extra processing for them. This method may also be used when you need to list the contents in the directory. It is a very practical method, but it is difficult for some inexperienced UNIX developers to grasp. The purpose of this article is to reduce the difficulty so that UNIX developers can make full use of these valuable functions.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.