/* Copyright (c) 2008-2012 Red Hat, Inc. This file is part of GlusterFS. This file is licensed to you under your choice of the GNU Lesser General Public License, version 3 or any later version (LGPLv3 or later), or the GNU General Public License, version 2 (GPLv2), in all cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H #define _CONFIG_H #include "config.h" #endif #include #include #include #include #include "glusterfs.h" #include "xlator.h" #include "meta.h" #include "meta-mem-types.h" static int is_meta_path (const char *path) { while (*path == '/') path++; if (!strncmp (path, ".meta", strlen (".meta"))) return 1; return 0; } struct stat * new_stbuf (void) { static int next_inode = 0; struct stat *stbuf = GF_CALLOC (1, sizeof (struct stat), gf_meta_mt_stat); ERR_ABORT (stbuf); stbuf->st_dev = 0; stbuf->st_ino = next_inode++; stbuf->st_mode = S_IRUSR | S_IRGRP | S_IROTH; stbuf->st_nlink = 1; stbuf->st_uid = 0; stbuf->st_gid = 0; stbuf->st_rdev = 0; stbuf->st_size = 0; stbuf->st_blksize = 0; stbuf->st_blocks = 0; stbuf->st_atime = time (NULL); stbuf->st_atim.tv_nsec = 0; stbuf->st_mtime = stbuf->st_atime; stbuf->st_mtim.tv_nsec = 0; stbuf->st_ctime = stbuf->st_ctime; stbuf->st_ctim.tv_nsec = 0; return stbuf; } /* find an entry among the siblings of an entry */ static meta_dirent_t * find_entry (meta_dirent_t *node, const char *dir) { meta_dirent_t *trav = node; while (trav) { if (!strcmp (trav->name, dir)) return trav; trav = trav->next; } return NULL; } /* * Return the meta_dirent_t corresponding to the pathname. * * If pathname does not exist in the meta tree, try to return * its highest parent that does exist. The part of the * pathname that is left over is returned in the value-result * variable {remain}. * For example, for "/.meta/xlators/brick1/view/foo/bar/baz", * return the entry for "/.meta/xlators/brick1/view" * and set remain to "/bar/baz" */ meta_dirent_t * lookup_meta_entry (meta_dirent_t *root, const char *path, char **remain) { char *_path = gf_strdup (path); if (!is_meta_path (path)) return NULL; meta_dirent_t *trav = root; char *dir = strtok (_path, "/"); dir = strtok (NULL, "/"); while (dir) { meta_dirent_t *ntrav; ntrav = find_entry (trav->children, dir); if (!ntrav) { /* we have reached bottom of the meta tree. Unknown dragons lie further below */ if (remain) { char *piece = dir; while (piece) { char *tmp = *remain; if (*remain) gf_asprintf (remain, "/%s/%s", *remain, piece); else gf_asprintf (remain, "/%s", piece); GF_FREE (tmp); piece = strtok (NULL, "/"); } } return trav; } dir = strtok (NULL, "/"); trav = ntrav; } GF_FREE (_path); return trav; } meta_dirent_t * insert_meta_entry (meta_dirent_t *root, const char *path, int type, struct stat *stbuf, struct xlator_fops *fops) { if (!is_meta_path (path)) return NULL; char *slashpos = strrchr (path, '/'); char *dir = strndup (path, slashpos - path); meta_dirent_t *parent = lookup_meta_entry (root, dir, NULL); if (!dir) return NULL; meta_dirent_t *new = GF_CALLOC (1, sizeof (meta_dirent_t), gf_meta_mt_meta_dirent_t); ERR_ABORT (new); new->name = gf_strdup (slashpos+1); new->type = type; new->parent = parent; new->next = parent->children; parent->children = new; if (stbuf) new->stbuf = stbuf; else new->stbuf = new_stbuf (); new->stbuf->st_mode |= type; new->fops = fops; return new; } int main (void) { meta_dirent_t *root = GF_CALLOC (1, sizeof (meta_dirent_t), gf_meta_mt_meta_dirent_t); ERR_ABORT (root); root->name = gf_strdup (".meta"); insert_meta_entry (root, "/.meta/version", S_IFREG, NULL, NULL); return 0; }