You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

442 lines
10 KiB

/*
Filename: extattr.h
Simple routines for dealing with extended attributes on OS X and FreeBSD
https://github.com/bfoz/pocket/blob/3978b7461cf5f46ce394adc6b7000c17f96af639/extattr.h
Created June 19, 2005 Brandon Fosdick
*/
#ifndef XATTR_H
#define XATTR_H
#if defined(__APPLE__) && defined(__MACH__)
#include <sys/xattr.h>
#endif
#if defined(__linux__)
/*
#include <sys/types.h>
*/
#include <attr/xattr.h>
#endif
#if defined(__FreeBSD__)
#include <sys/extattr.h>
#endif
#include <algorithm>
#include <vector>
typedef std::pair<std::string, std::string> ext_attr_t;
typedef std::vector<std::string> attr_names_t;
typedef std::vector<ext_attr_t> ext_attrs_t;
/*
inline int setxattr(int fd, const std::string &name, const std::string &value, int options=0)
{
#if defined(__APPLE__) && defined(__MACH__)
return fsetxattr(fd, name.c_str(), value.data(), value.length(), 0, options);
#endif
#if defined(__linux__)
return fsetxattr(fd, name.c_str(), value.data(), value.length(), 0);
#endif
#if defined(__FreeBSD__)
return extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, name.c_str(), value.data(), value.length());
#endif
}
*/
inline int setxattr(const std::string path, const std::string &name, const std::string &value, int options=0)
{
#if defined(__APPLE__) && defined(__MACH__)
return setxattr(path.c_str(), name.c_str(), value.data(), value.length(), 0, options);
#endif
#if defined(__linux__)
/* By default (i.e., options flags is zero), the extended attribute will be
* created if it does not exist, or the value will be replaced if the attribute exists.*/
if (options == 0){
return setxattr(path.c_str(), name.c_str(), value.data(), value.length(), 0);
} else {
return lsetxattr(path.c_str(), name.c_str(), value.data(), value.length(), 0);
}
#endif
#if defined(__FreeBSD__)
return extattr_set_file(path.c_str(), EXTATTR_NAMESPACE_USER, name.c_str(), value.data(), value.length());
#endif
}
inline ssize_t getxattrsize(const std::string path, const std::string &name, int options=0)
{
#if defined(__APPLE__) && defined(__MACH__)
return getxattr(path.c_str(), name.c_str(), NULL, 0, 0, options);
#endif
#if defined(__linux__)
if (options == 0){
return getxattr(path.c_str(), name.c_str(), NULL, 0);
} else{
return lgetxattr(path.c_str(), name.c_str(), NULL, 0);
}
#endif
#if defined(__FreeBSD__)
return extattr_get_file(path.c_str(), EXTATTR_NAMESPACE_USER, name.c_str(), NULL, 0);
#endif
}
inline std::string getxattr(const std::string path, const std::string &name, int options=0)
{
ssize_t size = getxattrsize(path, name, options);
char *buf;
if( size <= 0 )
return "";
buf = new char[size];
#if defined(__APPLE__) && defined(__MACH__)
getxattr(path.c_str(), name.c_str(), buf, size, 0, options);
#endif
#if defined(__linux__)
if (options == 0){
getxattr(path.c_str(), name.c_str(), buf, size);
} else{
lgetxattr(path.c_str(), name.c_str(), buf, size);
}
#endif
#if defined(__FreeBSD__)
extattr_get_file(path.c_str(), EXTATTR_NAMESPACE_USER, name.c_str(), buf, size);
#endif
return std::string(buf, size);
}
// ***** List attributes
// Return the size of the list of extended attributes
inline ssize_t listxattrsize(const std::string path, int options=0)
{
#if defined(__APPLE__) && defined(__MACH__)
return listxattr(path.c_str(), NULL, 0, options);
#endif
#if defined(__linux__)
if (options == 0){
return listxattr(path.c_str(), NULL, 0);
} else{
return llistxattr(path.c_str(), NULL, 0);
}
#endif
#if defined(__FreeBSD__)
return extattr_list_file(path.c_str(), EXTATTR_NAMESPACE_USER, NULL, 0);
#endif
}
//Read the extended attributes into one long string
// *** The FreeBSD version returns an array of [length, data]
// *** The OS X Tiger version returns an array of null terminated strings
inline size_t _listxattr(const std::string path, char *buf, const size_t size, int options=0)
{
#if defined(__APPLE__) && defined(__MACH__)
return listxattr(path.c_str(), buf, size, options);
#endif
#if defined(__linux__)
if (options == 0){
return listxattr(path.c_str(), buf, size);
} else{
return llistxattr(path.c_str(), buf, size);
}
#endif
#if defined(__FreeBSD__)
return extattr_list_file(path.c_str(), EXTATTR_NAMESPACE_USER, buf, size);
#endif
}
#define MIN(a,b) ((a<b)?a:b)
#if defined(__FreeBSD__)
//Return a list of attributes in a container, one attribute per element
inline attr_names_t listxattr(const std::string path, int options=0)
{
ssize_t size = listxattrsize(path, options);
char *buf;
int i=0;
int s;
attr_names_t v;
// std::cout << "0list size = " << size << std::endl;
if( size <= 0 )
return v;
buf = new char[size];
_listxattr(path, buf, size);
while(i<size)
{
s = buf[i]; //Get the string size
// std::cout << "string size = " << s << std::endl;
++i;
v.push_back(std::string(&(buf[i]), s));
i += s;
}
return v;
}
//Return a list of attributes in a container, one attribute per element
// Only return the elements that begin with prefix
inline attr_names_t listxattr(const std::string path, const std::string &prefix, int options=0)
{
ssize_t size = listxattrsize(path, options);
char *buf;
ssize_t i=0;
int s;
attr_names_t v;
// std::cout << "1list size = " << size << std::endl;
if( size <= 0 )
return v;
buf = new char[size];
_listxattr(path, buf, size);
while(i<size)
{
s = buf[i]; //Get the string size
// std::cout << "string size = " << s << std::endl;
++i;
if( memcmp(&(buf[i]), prefix.data(), MIN(s, prefix.length())) == 0)
v.push_back(std::string(&(buf[i]), s));
i += s;
}
return v;
}
#endif
#if defined(__APPLE__) && defined(__MACH__)
//Return a list of attributes in a container, one attribute per element
inline attr_names_t listxattr(const std::string path, int options=0)
{
ssize_t size = listxattrsize(path, options);
char *buf;
ssize_t i=0;
attr_names_t v;
if( size <= 0 )
return v;
buf = new char[size];
_listxattr(path, buf, size, options);
while(i<size)
{
v.push_back(std::string(&(buf[i])));
i += (v.back()).length() + 1;
}
return v;
}
//Return a list of attributes in a container, one attribute per element
// Only return the elements that begin with prefix
inline attr_names_t listxattr(const std::string path, const std::string &prefix, int options=0)
{
ssize_t size = listxattrsize(path, options);
char *buf;
// char *p;
ssize_t i=0;
int s;
attr_names_t v;
int j=0;
if( size <= 0 )
return v;
buf = new char[size];
_listxattr(path, buf, size, options);
// p = buf;
while(i<size)
{
/* s = strlen(p);
if( strncmp(p, prefix.data(), MIN(s, prefix.length())) == 0)
{
v.push_back(std::string(p, s));
++j;
}
p += s + 1;
i += s + 1;
*/
s = strlen(&(buf[i]));
if( strncmp(&(buf[i]), prefix.data(), MIN(s, prefix.length())) == 0)
{
v.push_back(std::string(&(buf[i])));
++j;
}
i += s + 1;
}
return v;
}
#endif
#if defined(__linux__)
//Return a list of attributes in a container, one attribute per element
inline attr_names_t listxattr(const std::string path, int options=0)
{
ssize_t size = listxattrsize(path, options);
char *buf;
ssize_t i=0;
attr_names_t v;
if( size <= 0 )
return v;
buf = new char[size];
_listxattr(path, buf, size, options);
while(i<size)
{
v.push_back(std::string(&(buf[i])));
i += (v.back()).length() + 1;
}
return v;
}
//Return a list of attributes in a container, one attribute per element
// Only return the elements that begin with prefix
inline attr_names_t listxattr(const std::string path, const std::string &prefix, int options=0)
{
ssize_t size = listxattrsize(path, options);
char *buf;
// char *p;
ssize_t i=0;
int s;
attr_names_t v;
int j=0;
if( size <= 0 )
return v;
buf = new char[size];
_listxattr(path, buf, size, options);
// p = buf;
while(i<size)
{
/* s = strlen(p);
if( strncmp(p, prefix.data(), MIN(s, prefix.length())) == 0)
{
v.push_back(std::string(p, s));
++j;
}
p += s + 1;
i += s + 1;
*/
s = strlen(&(buf[i]));
if( strncmp(&(buf[i]), prefix.data(), MIN(s, prefix.length())) == 0)
{
v.push_back(std::string(&(buf[i])));
++j;
}
i += s + 1;
}
return v;
}
#endif
/*
//Return a list of attributes in a container, one attribute per element
// Only return the elements that begin with prefix
inline attr_names_t listxattr(const std::string path, const std::string &prefix, int options=0)
{
std::istringstream S;
std::string a;
attr_names_t v;
S.str(_listxattr(path, options, size));
while(S)
{
getline(S, a);
if( search(a.begin(), a.end(), prefix.begin(), prefix.end()) == prefix.begin() );
v.push_back(a);
}
return v;
}
*/
//Remove the specified attribute
inline int removexattr(const std::string path, const std::string name, int options=0)
{
#if defined(__APPLE__) && defined(__MACH__)
return removexattr(path.c_str(), name.c_str(), options);
#endif
#if defined(__linux__)
if (options == 0){
return removexattr(path.c_str(), name.c_str());
} else{
return lremovexattr(path.c_str(), name.c_str());
}
#endif
#if defined(__FreeBSD__)
return extattr_delete_file(path.c_str(), EXTATTR_NAMESPACE_USER, name.c_str());
#endif
}
//Remove all XA
inline bool removexattr(const std::string path, int options=0)
{
attr_names_t names = listxattr(path);
if(names.size() == 0)
return false;
for(attr_names_t::iterator i = names.begin(); i != names.end(); ++i )
{
removexattr(path, (*i));
}
return true;
}
//Remove all XA that begin with prefix
inline bool remove_xattr(const std::string path, const std::string &prefix, int options=0)
{
attr_names_t names = listxattr(path, prefix);
if(names.size() == 0)
return false;
for(attr_names_t::iterator i = names.begin(); i != names.end(); ++i )
{
removexattr(path, (*i));
}
return true;
}
// -----
inline ext_attrs_t getxattrs(const std::string path, const std::string &prefix, int options=0)
{
attr_names_t names = listxattr(path, prefix);
std::string s;
ext_attrs_t attrs;
// int j = 0;
// std::cout << " names.size => " << names.size() << std::endl;
for(attr_names_t::iterator i = names.begin(); i != names.end(); ++i)
{
s = getxattr(path, (*i));
// std::cout << (*i) << " => " << s << std::endl;
attrs.push_back(ext_attr_t((*i), s));
}
return attrs;
}
#endif