Aller au contenu

Système de fichiers / Exemples

Error

error.c
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char* argv[])
{
    printf("Test perror vs strerror...\n");

    char* filename = "./error.txt";
    if (argc >= 2) filename = argv[1];

    int fd = open(filename, O_RDWR);

    printf("fd = %d, errno=%d\n", fd, errno);

    printf("\ntest perror...\n");
    perror("Error");

    printf("\ntest strerror_r...\n");
    char estr[100] = "";
    strerror_r(errno, estr, sizeof(estr) - 1);
    fprintf(stderr, "Error: %s\n", estr);

    return 0;
}

File I/O

read.c
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

// dd if=/dev/urandom of=./t.txt bs=4k count=4096

int main(int argc, char* argv[])
{
    const char* fn = "test1.txt";
    if (argc > 1) fn = argv[1];

    int fd = open(fn, O_RDONLY);
    if (fd == -1) {
        printf("file not found!\n");
    }

    while (1) {
        char buf[4096 + 1];
        int ln = read(fd, buf, sizeof(buf) - 1);
        if (ln == -1) {
            if (errno == EINTR) continue;
            break;
        }

        if (ln == 0) break;

        buf[ln] = 0;
        printf("%s\nread length --> %d\n", buf, ln);
    };
    close(fd);

    return 0;
}
write.c
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

static const char* msg1 = "1234567890abcdefghijklmnopqrstuvwxyz\n";

int main(int argc, char* argv[])
{
    const char* fn = "test1.txt";
    if (argc > 1) fn = argv[1];

    int fd = open(fn, O_RDWR | O_CREAT | O_TRUNC, 0666);
    if (fd == -1) {
        printf("can't file!\n");
    }

    for (int i = 0; i < 100; i++) {
        write(fd, msg1, strlen(msg1));
    }
    close(fd);
}
seek.c
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
static const struct {
    off_t pos;
    off_t offset;
    int whence;
} tests[] = {
    {0, 0, SEEK_SET},
    {10, 10, SEEK_SET},
    {21, 10, SEEK_CUR},
    {12, -10, SEEK_CUR},
    {1000, -1, SEEK_END},
};

static const char* i2w[] = {
    [SEEK_SET] = "SEEK_SET",
    [SEEK_CUR] = "SEEK_CUR",
    [SEEK_END] = "SEEK_END",
};

int main(int argc, char* argv[])
{
    const char* fn = "test2.txt";
    if (argc > 1) fn = argv[1];

    int fd = open(fn, O_RDWR | O_CREAT | O_TRUNC, 0664);
    if (fd == -1) {
        printf("can't file!\n");
    }

    // 1st create a file with 1001 entries 0000 - 1000
    char entry[5 + 3];
    for (int i = 0; i <= 1000; i++) {
        snprintf(entry, sizeof(entry) - 1, "%04d\n", i);
        write(fd, entry, strlen(entry));
    }

    for (unsigned i = 0; i < ARRAY_SIZE(tests); i++) {
        off_t pos = lseek(fd, tests[i].offset * 5, tests[i].whence);
        read(fd, entry, 5);
        entry[4] = 0;
        printf("%s: entry=%s, offset: %3ld, pos: %ld/%ld: \n",
               i2w[tests[i].whence],
               entry,
               tests[i].offset,
               tests[i].pos,
               pos / 5);
    }

    close(fd);
}
truncate.c
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

// echo "jslfjsdljslfjsdlfj" > t.txt

int main(int argc, char* argv[])
{
    char* fname = "t.txt";
    off_t len   = 10;
    if (argc > 1) fname = argv[1];

    int fd = open(fname, O_RDWR, 0664);
    if (fd == -1) {
        printf("can't open file: %s\n", fname);
    }
    printf("argv1: %s, fd=%d, errno=%d\n", fname, fd, errno);
    ftruncate(fd, len);
    close(fd);

    return 0;
}
stdio.c
#include <stdio.h>

int main(int argc, char* argv[])
{
    (void)argc;
    char buf[1];
    int c        = 0;
    FILE* stream = fopen(argv[1], "r");
    do {
        c = fread(buf, sizeof(buf), 1, stream);

    } while (c > 0);
    fclose(stream);

    return 0;
}

Directory

list.c
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>

void scan_dir(const char* path)
{
    printf("\n.%s/:\n", path);

    DIR* dir = opendir(path);
    if (dir == 0) return;
    while (dir != 0) {
        struct dirent* entry = readdir(dir);
        if (entry == 0) break;
        printf("%4d - %s\n", entry->d_type, entry->d_name);
    }
    closedir(dir);
}
int main(int argc, char* argv[])
{
    char* path = ".";
    if (argc > 1) path = argv[1];

    scan_dir(path);

    return 0;
}
recursive.c
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>

/**
 * convert filetype to character
 */
char mode2filetype(mode_t mode)
{
    // process file type
    if ((mode & S_IFMT) == S_IFSOCK) return 's';
    if ((mode & S_IFMT) == S_IFLNK) return 'l';
    if ((mode & S_IFMT) == S_IFREG) return '-';
    if ((mode & S_IFMT) == S_IFBLK) return 'b';
    if ((mode & S_IFMT) == S_IFDIR) return 'd';
    if ((mode & S_IFMT) == S_IFCHR) return 'c';
    if ((mode & S_IFMT) == S_IFIFO) return 'f';
    return '-';
}

/**
 * convert file permissions to string
 */
char* mode2str(mode_t mode)
{
    static char buf[1 + 3 * 3 + 1 + 1];

    buf[0] = mode2filetype(mode);

    buf[1] = mode & S_IRUSR ? 'r' : '-';
    buf[2] = mode & S_IWUSR ? 'w' : '-';
    buf[3] = mode & S_IXUSR ? 'x' : '-';

    buf[4] = mode & S_IRGRP ? 'r' : '-';
    buf[5] = mode & S_IWGRP ? 'w' : '-';
    buf[6] = mode & S_IXGRP ? 'x' : '-';

    buf[7] = mode & S_IROTH ? 'r' : '-';
    buf[8] = mode & S_IWOTH ? 'w' : '-';
    buf[9] = mode & S_IXOTH ? 'x' : '-';

    buf[10] = mode & S_ISVTX ? 't' : '-';
    if (mode & S_ISGID) buf[6] = 's';
    if (mode & S_ISUID) buf[3] = 's';

    buf[11] = 0;

    return buf;
}

/**
 * convert file time to string
 */
char* time2str(time_t* time)
{
    static char buf[50];
    char* t          = ctime_r(time, buf);
    t[strlen(t) - 1] = 0;
    return t;
}

/**
 * print file information
 *
 *@param name file name
 *@param stat file status
 */
void print_info(const char* name, struct stat* stat)
{
    printf("%10lu", stat->st_ino);             // print inode number
    printf(" %s", mode2str(stat->st_mode));    // print file type & permissions
    printf(" %3d", stat->st_nlink);            // print number of links
    printf(" %8lu", stat->st_size);            // print file size
    printf(" %s", time2str(&stat->st_mtime));  // print file modification time
    printf(" %s\n", name);                     // print filename
}

/**
 * scan directory for files and subdirectories
 *
 *@param recursively true to scan recursively the directories
 *@param size of root path
 *@param path directory path to scan
 */
void scan_dir(bool recursively, int rootsz, const char* path)
{
    // print relative directory path
    printf("\n.%s/:\n", path);

    // count number of files entries in directory
    DIR* dir = opendir(".");
    if (dir == 0) return;
    int count = 0;
    while (dir != 0) {
        struct dirent* entry = readdir(dir);
        if (entry == 0) break;
        count++;
    }
    closedir(dir);

    // get all file names
    char files[count * 256];
    dir = opendir(".");
    if (dir == 0) return;
    int i = 0;
    while (dir != 0) {
        struct dirent* entry = readdir(dir);
        if (entry == 0) break;

        strcpy(files + i * 256, entry->d_name);
        i++;
    }
    closedir(dir);

    // sort alphabeticaly all files
    qsort(files, count, 256, (int (*)(const void*, const void*))strcmp);

    // print file information
    for (int j = 0; j < count; j++) {
        struct stat status;
        int err = stat(files + j * 256, &status);
        if (err < 0) continue;
        print_info(files + j * 256, &status);
    }

    // process subdirectories if required...
    if (recursively)
        for (int j = 0; j < count; j++) {
            char* file = files + j * 256;
            if (strcmp(file, ".") == 0) continue;
            if (strcmp(file, "..") == 0) continue;

            struct stat status;
            int err = stat(file, &status);
            if (err < 0) continue;
            if (!S_ISDIR(status.st_mode)) continue;

            char p[strlen(path) + 1 + 256];
            strcpy(p, path);
            strcat(p, "/");
            strcat(p, file);
            chdir(file);
            scan_dir(recursively, rootsz, p);
            chdir("..");
        }
}

/**
 * print application usage
 */
static void print_usage()
{
    printf(
        "Usage: list [OPTIONs] [PATH]\n"
        "List information about files in directories\n"
        "Options:\n"
        "  -h   this message\n"
        "  -r   recursive to list subdirectories\n"
        "Path:\n"
        "  by default current directory\n");
}

/**
 * main program...
 */
int main(int argc, char* argv[])
{
    printf("List files in directories...\n");

    // parse fonction arguments
    bool recursively = false;
    const char* path = ".";
    while (1) {
        int op = getopt(argc, argv, "hr");
        if (op == -1) break;
        switch (op) {
            case 'h':
                print_usage();
                return 0;
            case 'r':
                recursively = true;
                break;
            default:
                fprintf(stderr, "ERROR: invalid option.\n");
                exit(1);
        }
    }
    int r = argc - optind;
    if (r == 1)
        path = argv[optind];
    else if (r > 1) {
        fprintf(stderr, "ERROR: too many arguments\n");
        exit(1);
    }
    printf("options: r=%d, p=%s\n", recursively, path);

    char* cwd = getcwd(0, 0);
    chdir(path);
    scan_dir(recursively, strlen(cwd), path);
    free(cwd);

    return 0;
}

Inotify

main.c
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <sys/inotify.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

static void print_events(uint32_t mask)
{
    if (mask & IN_ACCESS)        printf(" access       ");
    if (mask & IN_ATTRIB)        printf(" attribute    ");
    if (mask & IN_CLOSE_WRITE)   printf(" close_write  ");
    if (mask & IN_CLOSE_NOWRITE) printf(" close_nowrite");
    if (mask & IN_CREATE)        printf(" create       ");
    if (mask & IN_DELETE)        printf(" delete       ");
    if (mask & IN_DELETE_SELF)   printf(" delete_self  ");
    if (mask & IN_MODIFY)        printf(" modify       ");
    if (mask & IN_MOVE_SELF)     printf(" move_self    ");
    if (mask & IN_MOVED_FROM)    printf(" move_from    ");
    if (mask & IN_MOVED_TO)      printf(" move_to      ");
    if (mask & IN_OPEN)          printf(" open         ");

    if (mask & IN_DONT_FOLLOW)   printf(" dont_follow  ");
    if (mask & IN_EXCL_UNLINK)   printf(" excl_unlink  ");
    if (mask & IN_IGNORED)       printf(" ignored      ");
    if (mask & IN_ISDIR)         printf(" is_dir       ");
    if (mask & IN_Q_OVERFLOW)    printf(" q_overflow   ");
    if (mask & IN_UNMOUNT)       printf(" unmount      ");
    printf("\n");
}

static void process_inotify(int fd)
{
    char buff[10 * (sizeof(struct inotify_event) + NAME_MAX + 1)];
    ssize_t sz = read(fd, buff, sizeof(buff));
    if (sz == -1) {
        perror("ERROR while reading inotify fd");
        if (errno == EINTR) return;
        exit(1);
    }

    printf("inotify event:\n");
    char* p = buff;
    while (sz > 0) {
        struct inotify_event* event = (struct inotify_event*)p;
        printf("  wd:%d, cookie=%d, mask=0x%x",
               event->wd,
               event->cookie,
               event->mask);
        print_events(event->mask);
        event->name[event->len] = 0;
        printf("  name:%s\n\n", event->name);
        p += sizeof(struct inotify_event) + event->len;
        sz -= sizeof(struct inotify_event) + event->len;
    }
}

int main(int argc, char* argv[])
{
    char* path = ".";
    if (argc > 1) path = argv[1];

    int efd = epoll_create1(0);
    if (efd == -1) {
        perror("ERROR while create epoll");
        exit(1);
    }

    int ifd = inotify_init1(0);
    if (ifd == -1) {
        perror("ERROR while creating inotify file descriptor");
        exit(1);
    }
    struct epoll_event event = {
        .events  = EPOLLIN,
        .data.fd = ifd,
    };
    epoll_ctl(efd, EPOLL_CTL_ADD, ifd, &event);

    int wd1 = inotify_add_watch(ifd, path, IN_ALL_EVENTS);
    if (wd1 == -1) {
        perror("ERROR while adding directory to inotify fd");
        exit(1);
    }

    while (1) {
        struct epoll_event events[2];
        int ret = epoll_wait(efd, events, 2, -1);
        if (ret == -1) {
            perror(" --> error...");

        } else if (ret == 0) {
            perror(" --> nothing received...");

        } else {
            for (int i = 0; i < ret; i++) {
                int fd = events[i].data.fd;
                if (fd == ifd)
                    process_inotify(fd);
                else
                    printf("wrong fd..\n");
            }
        }
    }

    return 0;
}