/* Extended attribute handling for AFS. We use xattrs to get and set metadata * instead of providing pioctl(). * * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public Licence * as published by the Free Software Foundation; either version * 2 of the Licence, or (at your option) any later version. */ #include #include #include #include "internal.h" static const char afs_xattr_list[] = "afs.cell\0" "afs.fid\0" "afs.volume"; /* * Retrieve a list of the supported xattrs. */ ssize_t afs_listxattr(struct dentry *dentry, char *buffer, size_t size) { if (size == 0) return sizeof(afs_xattr_list); if (size < sizeof(afs_xattr_list)) return -ERANGE; memcpy(buffer, afs_xattr_list, sizeof(afs_xattr_list)); return sizeof(afs_xattr_list); } /* * Get the name of the cell on which a file resides. */ static int afs_xattr_get_cell(const struct xattr_handler *handler, struct dentry *dentry, struct inode *inode, const char *name, void *buffer, size_t size) { struct afs_vnode *vnode = AFS_FS_I(inode); struct afs_cell *cell = vnode->volume->cell; size_t namelen; namelen = strlen(cell->name); if (size == 0) return namelen; if (namelen > size) return -ERANGE; memcpy(buffer, cell->name, namelen); return namelen; } static const struct xattr_handler afs_xattr_afs_cell_handler = { .name = "afs.cell", .get = afs_xattr_get_cell, }; /* * Get the volume ID, vnode ID and vnode uniquifier of a file as a sequence of * hex numbers separated by colons. */ static int afs_xattr_get_fid(const struct xattr_handler *handler, struct dentry *dentry, struct inode *inode, const char *name, void *buffer, size_t size) { struct afs_vnode *vnode = AFS_FS_I(inode); char text[8 + 1 + 8 + 1 + 8 + 1]; size_t len; len = sprintf(text, "%x:%x:%x", vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique); if (size == 0) return len; if (len > size) return -ERANGE; memcpy(buffer, text, len); return len; } static const struct xattr_handler afs_xattr_afs_fid_handler = { .name = "afs.fid", .get = afs_xattr_get_fid, }; /* * Get the name of the volume on which a file resides. */ static int afs_xattr_get_volume(const struct xattr_handler *handler, struct dentry *dentry, struct inode *inode, const char *name, void *buffer, size_t size) { struct afs_vnode *vnode = AFS_FS_I(inode); const char *volname = vnode->volume->vlocation->vldb.name; size_t namelen; namelen = strlen(volname); if (size == 0) return namelen; if (namelen > size) return -ERANGE; memcpy(buffer, volname, namelen); return namelen; } static const struct xattr_handler afs_xattr_afs_volume_handler = { .name = "afs.volume", .get = afs_xattr_get_volume, }; const struct xattr_handler *afs_xattr_handlers[] = { &afs_xattr_afs_cell_handler, &afs_xattr_afs_fid_handler, &afs_xattr_afs_volume_handler, NULL };