Unix C Programming - file dir


apue

0x01.API

1.makir()/mkdirat()/rmdkir()

#include <sys/stat.h>
int mkdir (const char *filename, mode_t mode)
int mkdirat (int fd, const char *filename, mode_t mode)
#include <unistd.h>
int rmdir(const char *filename)
                                            - 成功返回:0;失败返回:-1

mkdir()/mkdirat() used to create directory. When df=AT_FDCWD or filemane is positive path, makir() is equal to mkdirat().

Mode Bits for Access Permissionm struct mode_t infomation at: http://homeway.me/2017/03/03/apue-file-stat/#permision

In most other respects, rmdir behaves like unlink.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#define RWRWRW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
int main(int argc, char** argv) {
    if (argc == 1) {
        printf("Usage: %s pathname", argv[0]);
        return 0;
    }
    char cmd[512];
    for (int i = 1; i < argc; ++i) {
        if (mkdir(argv[i], (RWRWRW)) < 0) {
            printf("%s: mkdir error", argv[i]);
        } else {
            printf("%s: mkdir success\n", argv[i]);
            sleep(1);
            sprintf(cmd, "ls -l %s", argv[i]);
            system(cmd);
        }
    }
    for (int i = 1; i < argc; ++i) {
        if (rmdir(argv[i]) < 0) {
            printf("%s: rmdir error", argv[i]);
        } else {
            printf("%s: rmdir success\n", argv[i]);
            sleep(1);
            sprintf(cmd, "ls -l %s", argv[i]);
            system(cmd);
        }
    }
}

➜ $: gcc test.c
➜ $: ./a.out forkme

forkme: mkdir success
forkme: rmdir success
ls: forkme: No such file or directory



2.opendir()/fdopendir()/readdir()/closedir()

#include<dir.h>
DIR * opendir (const char *dirname)
DIR * fdopendir (int fd)
                                            - 成功返回:DIR;失败返回:NULL
#include<dirent.h>
struct dirent * readdir (DIR *dirstream)
                                            - 成功返回:dirent;失败返回:NULL
int closedir (DIR *dirstream)
                                            - 成功返回:0;失败返回:-1

DIR struct represents a directory stream, and use readdir() to read directory information. DIR struct defination in my macos is like this:

/* structure describing an open directory. */
typedef struct {
    int        __dd_fd;        /* file descriptor associated with directory */
    long    __dd_loc;        /* offset in current buffer */
    long    __dd_size;    /* amount of data returned */
    char    *__dd_buf;    /* data buffer */
    int        __dd_len;        /* size of data buffer */
    long    __dd_seek;    /* magic cookie returned */
    long    __dd_rewind;    /* magic cookie for rewinding */
    int        __dd_flags;    /* flags for readdir */
    __darwin_pthread_mutex_t __dd_lock;     /* for thread locking */
    struct _telldir *__dd_td;                 /* telldir position recording */
} DIR;

You shouldn’t ever allocate objects of the struct dirent or DIR data types, since the directory access functions do that for you.

The description of struct dirent:

#define __DARWIN_MAXPATHLEN    1024
struct dirent {
    __uint64_t  d_ino;      /* file number of entry */
    __uint64_t  d_seekoff;  /* seek offset (optional, used by servers) */
    __uint16_t  d_reclen;   /* length of this record */
    __uint16_t  d_namlen;   /* length of string in d_name */
    __uint8_t   d_type;     /* file type, see below */
    char      d_name[__DARWIN_MAXPATHLEN]; /* entry name (up to MAXPATHLEN bytes) */
}

The following contants are defined for d_type:

  • DT_UNKNOWN // The type is unknown.
  • DT_REG // A regular file.
  • DT_DIR // A directory.
  • DT_FIFO // A named pipe, or FIFO.
  • DT_SOCK // A local-domain socket.
  • DT_CHR // A character device.
  • DT_BLK // A block device.
  • DT_LNK // A symbolic link.

And how to check file type, you can see this: http://homeway.me/2017/03/03/apue-file-stat/#stat-type

All directory information is in this struct, and we can read directory data one by one through readdir(). This function reads the next entry from the directory.

From api above, we can write a program to list directory, and read it`s information:

#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>
#include <time.h>
int dir_type(struct stat stat_buff) {
    // check file type from struct stat
    if (S_ISDIR(stat_buff.st_mode)) {
        return 1;
    }
    if (S_ISREG(stat_buff.st_mode)) {
        return 2;
    }
    return 0;        // consider as unknown file type
}
// dfs read directory, pathname can be positive/relative path
void dfs(char* pathname) {
    DIR* dir;
    struct dirent* dp;
    char next[1024];
    if ((dir = opendir(pathname)) == NULL) {
        printf("%s: opendir error", pathname);
        return;
    }
    // read directory info
    while ((dp = readdir(dir)) != NULL) {
        sprintf(next, "%s/%s", pathname, dp->d_name);
        if (strcmp(dp->d_name, ".DS_Store") == 0 || strcmp(dp->d_name, "..") == 0 || strcmp(dp->d_name, ".") == 0) {
            // skip current folder, father folder
            continue;
        }
        struct stat stat_buff;
        if (stat(next, &stat_buff) < 0) {
            printf("%s: stat error", pathname);
            continue;
        }
        // read file type
        int ret_stat = dir_type(stat_buff);
        switch (ret_stat) {
            case 1:
                printf("Dir => %s\n", next);
                dfs(next);        // for directory read child node 
                break;
            case 2:
                printf("File => path = %s; uid = %d; size = %lld; create_time = %s", next, stat_buff.st_uid, stat_buff.st_size, ctime(&(stat_buff.st_mtime)));
                break;
        }
    }
    closedir(dir);
}

int main(int argc, char** argv) {
    if (argc == 1) {
       printf("Usage: %s pathname\n", argv[0]);
        return;
    }
    dfs(argv[1]);
}

➜ $: gcc dir.c
➜ $: ./a.out ..

Dir => ../.git
Dir => ../.git/branches
File => path = ../.git/COMMIT_EDITMSG; uid = 501; size = 7; create_time = Fri Mar  3 20:41:12 2017
.........



3.chdir()/fchdir()/getcwd()

#include <unistd.h>
int chdir(const char* pathname)
int fchdir(int fd)
                                            - 成功返回:0;失败返回:-1
char * getcwd (char *buffer, size_t size)
                                            - 成功返回:cwd path;失败返回:NULL



0x02.ERROR

Error code see here: http://homeway.me/2017/03/02/apue-file-io/#error



Reference:

– Base api information are in book, so in my blog I only write some useful example.



本文出自 夏日小草,转载请注明出处:http://homeway.me/2017/03/04/apue-file-dir/

-by小草

2017-03-04 23:18:34

Fork me on GitHub