C file operations cheatsheet

Calculate file size via lseek

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc, char *argv[])
{
    int ret = -1;
    int fd = -1;
    size_t s_offset = 0;
    size_t e_offset = -1;
    char *path = NULL;

    if (argc != 2) {
        printf("Usage: PROG file\n");
        goto Error;
    }
    path = argv[1];
    if(0 > (fd = open(path,O_RDONLY))) {
        printf("open failed\n");
        goto Error;
    }
    if (-1 == (s_offset = lseek(fd, 0, SEEK_SET))) {
        printf("lseek error\n");
        goto Error;
    }
    if (-1 == (e_offset = lseek(fd, 0, SEEK_END))) {
        printf("lseek error\n");
        goto Error;
    }
    printf("File Size: %ld byte\n", e_offset - s_offset);
    ret = 0;
Error:
    if (fd>=0) {
        close(fd);
    }
    return ret;
}

output:

$ echo "Hello" > hello.txt
$ ./a.out hello.txt
File Size: 6 byte

Using fstat get file size

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

int main(int argc, char *argv[])
{
    int ret = -1;
    int fd = -1;
    struct stat st = {0};
    char *path = NULL;

    if (argc != 2) {
        printf("Usage: PROG file\n");
        goto Error;
    }
    path = argv[1];
    /* using fstat */
    if (-1 == (fd = open(path, O_RDONLY))) {
        printf("open file get error\n");
        goto Error;
    }
    if (-1 == fstat(fd, &st)) {
        printf("fstat get error\n");
        goto Error;
    }
    printf("File Size: %lld byte\n", st.st_size);
    ret = 0;
Error:
    if (fd>=0) {
        close(fd);
    }
    return ret;
}

output:

$ echo "Hello" > hello.txt
$ ./a.out hello.txt
File Size: 6 byte

Copy all content of a file

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

#define COPY_BUF_SIZE 1024

int main(int argc, char *argv[])
{
    int ret = -1;
    int sfd = -1, dfd = -1;
    mode_t perm = 0;
    char *src = NULL;
    char *dst = NULL;
    char buf[COPY_BUF_SIZE] = {0};
    size_t r_size = 0;
    struct stat st = {0};

    if (argc != 3) {
        printf("Usage: PROG src dst\n");
        goto Error;
    }

    /* open source */
    src = argv[1];
    if (-1 == (sfd = open(src, O_RDONLY))) {
        printf("open source fail\n");
        goto Error;
    }
    /* read source permission */
    if (-1 == (fstat(sfd, &st))) {
        printf("fstat file error\n");
        goto Error;
    }
    /* copy destination */
    dst = argv[2];
    perm = st.st_mode; /* set file permission */
    if (-1 == (dfd = open(dst, O_WRONLY | O_CREAT, perm))) {
        printf("open destination fail\n");
        goto Error;
    }
    while (0 < (r_size = read(sfd, buf, COPY_BUF_SIZE))) {
        if (r_size != write(dfd, buf, r_size)) {
            printf("copy file get error\n");
            goto Error;
        }
    }
    ret = 0;
Error:
    if (sfd >= 0) {
        close(sfd);
    }
    if (dfd >= 0) {
        close(dfd);
    }
    return ret;
}

output:

$ echo "Hello" > hello.txt
$ ./a.out hello.txt hello_copy.txt
$ diff hello.txt hello_copy.txt

Copy some bytes of content to a file

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char *argv[])
{
    int ret = -1;
    int sfd = -1, dfd = -1;
    size_t s_offset = 0;
    size_t d_offset = -1;
    mode_t perm = 0;
    char *src = NULL;
    char *dst = NULL;
    struct stat st = {0};
    char buf[1024] = {0};
    size_t size = 0;
    size_t r_size = 0;

    if (argc != 4) {
        printf("Usage: PROG src dst bytes\n");
        goto Error;
    }
    /* open source file */
    src = argv[1];
    if (0 > (sfd = open(src, O_RDONLY))) {
        printf("open source file error\n");
        goto Error;
    }
    /* get source file permission */
    if (-1 == fstat(sfd, &st)) {
        printf("fstat fail\n");
        goto Error;
    }
    /* open dst file */
    dst = argv[2];
    perm = st.st_mode;
    if (0 > (dfd = open(dst, O_WRONLY | O_CREAT, perm))) {
        printf("open destination file error\n");
        goto Error;
    }
    if (-1 == (d_offset = lseek(dfd, 0, SEEK_END))) {
        printf("lseek get error\n");
        goto Error;
    }
    if (-1 == (s_offset = lseek(sfd, d_offset, SEEK_SET))) {
        printf("lseek get error\n");
        goto Error;
    }
    /* bytes */
    size = atoi(argv[3]);
    if (-1 == (r_size = read(sfd, buf, size))) {
        printf("read content fail\n");
        goto Error;
    }
    if (r_size != write(dfd, buf, r_size)) {
        printf("write content fail\n");
        goto Error;
    }
    ret = 0;
Error:
    if (sfd >= 0) {
        close(sfd);
    }
    if (dfd >= 0) {
        close(dfd);
    }
    return ret;
}

output:

$ echo "Hello" > hello.txt
$ $ ./a.out hello.txt hello_copy.txt 3
$ cat hello_copy.txt
Hel$./a.out hello.txt hello_copy.txt 3
$ cat hello_copy.txt
Hello
$ diff hello.txt hello_copy.txt

Get lines of a file

// basic API: fopen, getline

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    int ret = -1;
    FILE *f = NULL;
    ssize_t read_size = 0;
    size_t len = 0;
    char *path = NULL;
    char *line = NULL;

    if (argc != 2) {
        printf("Usage: PROG file\n");
        goto Error;
    }

    path = argv[1];
    if (NULL == (f = fopen(path, "r"))) {
        printf("Read file error");
        goto Error;
    }

    while (-1 != getline(&line, &len, f)) {
        printf("%s\n", line);
    }
    ret = 0;
Error:
    if (line) {
        free(line);
        line = NULL;
    }
    if (f) {
        fclose(f);
    }
    return ret;
}

Get lines of a file via std::getline

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>

int main(int argc, char *argv[])
{
    std::ifstream f(argv[1]);
    for (std::string line; std::getline(f, line);) {
        std::cout << line << "\n";
    }
}

Read content into memory from a file

// basick API: fopen, fseek, ftell, rewind, fread
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    int ret = -1;
    FILE *f = NULL;
    char *path = NULL;
    int size = 0;
    int read_size = 0;
    char *buffer = NULL;

    if (argc != 2) {
        printf("Usage: PROG file\n");
        goto Error;
    }

    path = argv[1];
    if (NULL == (f = fopen(path, "r"))) {
        printf("Read %s into memory fail\n", path);
        goto Error;
    }
    fseek(f, 0, SEEK_END);
    size = ftell(f);
    rewind(f);

    if (NULL == (buffer = (char *)calloc(size, sizeof(char)))) {
        printf("malloc file fail\n");
        goto Error;
    }

    read_size = fread(buffer, 1, size, f);
    if (read_size != size) {
        printf("fread %s fail\n", path);
        goto Error;
    }
    buffer[size-1] = '\0';
    printf("%s\n", buffer);
    ret = 0;
Error:
    if (buffer) {
        free(buffer);
        buffer = NULL;
    }
    if (f) {
        fclose(f);
    }
    return ret;
}

Check file types

#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    int ret = -1;
    struct stat st;
    char *path = NULL;

    bzero(&st, sizeof(struct stat));

    if (argc != 2) {
        printf("Usage: PROG file\n");
        goto Error;
    }
    path = argv[1];
    if (-1 == stat(path, &st)) {
        printf("stat %s get error\n", path);
        goto Error;
    }
    /* check file type */
    switch (st.st_mode & S_IFMT) {
        case S_IFBLK: printf("Block device\n"); break;
        case S_IFCHR: printf("Character device\n"); break;
        case S_IFDIR: printf("Directory\n"); break;
        case S_IFIFO: printf("FIFO pipe\n"); break;
        case S_IFLNK: printf("Symbolic link\n"); break;
        case S_IFREG: printf("Regular file\n"); break;
        case S_IFSOCK: printf("Socket\n"); break;
        default: printf("Unknown\n");
    }
    ret = 0;
Error:
    return ret;
}

output:

$ ./a.out /etc/hosts
Regular file
$ ./a.out /usr
Directory
./a.out /dev/tty.Bluetooth-Incoming-Port
Character device

File tree walk

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ftw.h>

#define CHECK_RET(ret, fmt, ...)        \
    do {                                \
        if (ret < 0) {                  \
            printf(fmt, ##__VA_ARGS__); \
            goto End;                   \
        }                               \
    } while(0)

#define CHECK_NULL(ret, fmt, ...)       \
    do {                                \
        if (ret == NULL) {              \
            printf(fmt, ##__VA_ARGS__); \
            goto End;                   \
        }                               \
    } while(0)

int callback(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf)
{
    CHECK_NULL(fpath, "fpath cannot be NULL\n");
    printf("%s\n", fpath);
End:
    return 0;
}

int main(int argc, char *argv[])
{
    int ret = -1;
    char *path = NULL;

    if (argc != 2) {
        perror("Usage: PROG [dirpath]\n");
        goto End;
    }

    path = argv[1];
    ret = nftw(path, callback, 64, FTW_DEPTH | FTW_PHYS);
    CHECK_RET(ret, "nftw(%s) fail. [%s]", path, strerror(errno));
End:
    return ret;
}

output:

$ gcc tree_walk.c
$ ./a.out .
./tree_walk.c
./a.out
.