2018年11月28日水曜日

ファイルのタイムスタンプをナノ秒まで取得

struct stat で st_mtime が struct timespec になってるからそこから取れる。
gcc -E で確認
 # 46 "/usr/include/bits/stat.h" 3 4
struct stat
  {
    __dev_t st_dev;




    __ino_t st_ino;







    __nlink_t st_nlink;
    __mode_t st_mode;

    __uid_t st_uid;
    __gid_t st_gid;

    int __pad0;

    __dev_t st_rdev;




    __off_t st_size;



    __blksize_t st_blksize;
    __blkcnt_t st_blocks;
# 91 "/usr/include/bits/stat.h" 3 4
    struct timespec st_atim;
    struct timespec st_mtim;
    struct timespec st_ctim;
# 106 "/usr/include/bits/stat.h" 3 4
    __syscall_slong_t __unused[3];
# 115 "/usr/include/bits/stat.h" 3 4
  };
 オンラインマニュアルにある st_mtime を使うと st_mtim.tv_sec に変換されてしまうので、ナノ秒をとる場合は st_mtim.tv_nsec と書かなければならない.

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

static void
usage(const char *cmd)
{
    fprintf(stderr, "Usage: %s <file...>\n", cmd);
    exit(1);
}

static void
init(int ac, char *av[])
{  
    int c;
    const char *optstr = "";

    while ((c = getopt(ac, av, optstr)) != -1) {
        switch (c) {
        case '?':
        default:
            usage(av[0]);
            break;
        }
    }
}

int
main(int ac, char *av[])
{
    int i;
    init(ac, av);
    for (i=optind; i<ac; i++) {
        struct stat stbuf;
        if (stat(av[i], &stbuf) < 0) {
            fprintf(stderr, "Stat error[%s]: %d: %s\n", av[i], errno, strerror(errno));
            continue;
        }
        char datestr[256];
        strftime(datestr, sizeof(datestr)-1, "%Y%m%d%H%I%M%S", localtime(&stbuf.st_mtime));
        fprintf(stdout, "%s ... %s.%ld\n", av[i], datestr, stbuf.st_mtim.tv_nsec);      // st_mtime ではなく st_mtim (eがない)  を指定
    }
    return 0;
}