glusterfs
1/*
2Copyright (c) 2019 Red Hat, Inc. <http://www.redhat.com>
3This file is part of GlusterFS.
4
5This file is licensed to you under your choice of the GNU Lesser
6General Public License, version 3 or any later version (LGPLv3 or
7later), or the GNU General Public License, version 2 (GPLv2), in all
8cases as published by the Free Software Foundation.
9*/
10
11#include <stdlib.h>12#ifdef __FreeBSD__13#include <sys/endian.h>14#else15#include <endian.h>16#endif17#include <stdio.h>18#include <time.h>19#include <string.h>20#include <inttypes.h>21#include <sys/types.h>22#include <sys/xattr.h>23#include <errno.h>24
25typedef struct gf_timespec_disk {26uint64_t tv_sec;27uint64_t tv_nsec;28} gf_timespec_disk_t;29
30/* posix_mdata_t on disk structure */
31typedef struct __attribute__((__packed__)) posix_mdata_disk {32/* version of structure, bumped up if any new member is added */33uint8_t version;34/* flags indicates valid fields in the structure */35uint64_t flags;36gf_timespec_disk_t ctime;37gf_timespec_disk_t mtime;38gf_timespec_disk_t atime;39} posix_mdata_disk_t;40
41/* In memory representation posix metadata xattr */
42typedef struct {43/* version of structure, bumped up if any new member is added */44uint8_t version;45/* flags indicates valid fields in the structure */46uint64_t flags;47struct timespec ctime;48struct timespec mtime;49struct timespec atime;50} posix_mdata_t;51
52#define GF_XATTR_MDATA_KEY "trusted.glusterfs.mdata"53
54/* posix_mdata_from_disk converts posix_mdata_disk_t into host byte order
55*/
56static inline void57posix_mdata_from_disk(posix_mdata_t *out, posix_mdata_disk_t *in)58{
59out->version = in->version;60out->flags = be64toh(in->flags);61
62out->ctime.tv_sec = be64toh(in->ctime.tv_sec);63out->ctime.tv_nsec = be64toh(in->ctime.tv_nsec);64
65out->mtime.tv_sec = be64toh(in->mtime.tv_sec);66out->mtime.tv_nsec = be64toh(in->mtime.tv_nsec);67
68out->atime.tv_sec = be64toh(in->atime.tv_sec);69out->atime.tv_nsec = be64toh(in->atime.tv_nsec);70}
71
72/* posix_fetch_mdata_xattr fetches the posix_mdata_t from disk */
73static int74posix_fetch_mdata_xattr(const char *real_path, posix_mdata_t *metadata)75{
76size_t size = -1;77char *value = NULL;78char gfid_str[64] = {0};79
80char *key = GF_XATTR_MDATA_KEY;81
82if (!metadata || !real_path) {83goto err;84}85
86/* Get size */87size = lgetxattr(real_path, key, NULL, 0);88if (size == -1) {89goto err;90}91
92value = calloc(size + 1, sizeof(char));93if (!value) {94goto err;95}96
97/* Get xattr value */98size = lgetxattr(real_path, key, value, size);99if (size == -1) {100goto err;101}102posix_mdata_from_disk(metadata, (posix_mdata_disk_t *)value);103
104out:105if (value)106free(value);107return 0;108err:109if (value)110free(value);111return -1;112}
113
114int
115main(int argc, char *argv[])116{
117posix_mdata_t metadata;118uint64_t result;119
120if (argc != 3) {121/*122Usage: get_mdata_xattr -c|-m|-a <file-name>
123where -c --> ctime
124-m --> mtime
125-a --> atime
126*/
127printf("-1");128goto err;129}130
131if (posix_fetch_mdata_xattr(argv[2], &metadata)) {132printf("-1");133goto err;134}135
136switch (argv[1][1]) {137case 'c':138result = metadata.ctime.tv_sec;139break;140case 'm':141result = metadata.mtime.tv_sec;142break;143case 'a':144result = metadata.atime.tv_sec;145break;146default:147printf("-1");148goto err;149}150printf("%" PRIu64, result);151fflush(stdout);152return 0;153err:154fflush(stdout);155return -1;156}
157