libuvでcat

uvbookのサンプルをベースに複数ファイルを読めるcatを書いてみた

Filesystem — An Introduction to libuv

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

#define BUFSIZE 2048

void on_open(uv_fs_t *);
void on_read(uv_fs_t *);
void on_write(uv_fs_t *);
void on_close(uv_fs_t *);
void do_cat(const char *);

struct cat_t {
    int argc;
    char **argv;
    uv_file file;
    uv_fs_t open_req;
    uv_fs_t read_req;
    uv_fs_t write_req;
    uv_buf_t iov;
    char buffer[BUFSIZE];
} cat;


void on_open(uv_fs_t *req) {
    if (req->result >= 0) {
        cat.argc--;
        cat.argv++;
        cat.file = req->result;
        uv_fs_read(uv_default_loop(), &cat.read_req, cat.file, &cat.iov, 1, -1, on_read);
    } else {
        fprintf(stderr, "open error: %s\n", uv_strerror(req->result));
    }
}

void on_read(uv_fs_t *req) {
    if (req->result < 0) {
        fprintf(stderr, "read error: %s\n", uv_strerror(req->result));
    } else if (req->result == 0) {
        uv_fs_t close_req;
        uv_fs_close(uv_default_loop(), &close_req, cat.file, NULL);

        if (cat.argc > 0)
            do_cat(*cat.argv);
    } else if (req->result > 0) {
        cat.iov.len = req->result;
        uv_fs_write(uv_default_loop(), &cat.write_req, 1, &cat.iov, 1, -1, on_write);
    }
}

void on_write(uv_fs_t *req) {
    if (req->result < 0) {
        fprintf(stderr, "write error: %s\n", uv_strerror(req->result));
    } else {
        uv_fs_read(uv_default_loop(), &cat.read_req, cat.file, &cat.iov, 1, -1, on_read);
    }
}

void on_close(uv_fs_t *req) {
    if (req->result < 0) {
        fprintf(stderr, "close error: %s\n", uv_strerror(req->result));
    }
    uv_fs_req_cleanup(req);
}


void do_cat(const char* filename) {
    uv_fs_open(uv_default_loop(), &cat.open_req, filename, O_RDONLY, 0, on_open);
}

int main(int argc, char **argv) {
    if (argc < 2) {
        fprintf(stderr, "usage: %s [filename ...]\n", argv[0]);
        exit(1);
    }
    cat.argc = --argc;
    cat.argv = ++argv;

    cat.iov = uv_buf_init(cat.buffer, sizeof(cat.buffer));
    do_cat(*cat.argv);
    uv_run(uv_default_loop(), UV_RUN_DEFAULT);

    uv_fs_req_cleanup(&cat.write_req);
    uv_fs_req_cleanup(&cat.read_req);
    uv_fs_req_cleanup(&cat.write_req);
    return 0;
}

メモ

  • uv_fs_openのcallbackのresultはuv_file_t