| File: | xattr.c |
| Warning: | line 632, column 20 PyObject ownership leak with reference count of 1 |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* | |||
| 2 | xattr - a python module for manipulating filesystem extended attributes | |||
| 3 | ||||
| 4 | Copyright (C) 2002, 2003, 2006, 2008, 2012, 2013, 2015 | |||
| 5 | Iustin Pop <iustin@k1024.org> | |||
| 6 | ||||
| 7 | This library is free software; you can redistribute it and/or | |||
| 8 | modify it under the terms of the GNU Lesser General Public | |||
| 9 | License as published by the Free Software Foundation; either | |||
| 10 | version 2.1 of the License, or (at your option) any later version. | |||
| 11 | ||||
| 12 | This library is distributed in the hope that it will be useful, | |||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| 15 | Lesser General Public License for more details. | |||
| 16 | ||||
| 17 | You should have received a copy of the GNU Lesser General Public | |||
| 18 | License along with this library; if not, write to the Free Software | |||
| 19 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |||
| 20 | 02110-1301 USA | |||
| 21 | ||||
| 22 | */ | |||
| 23 | ||||
| 24 | #define PY_SSIZE_T_CLEAN | |||
| 25 | #include <Python.h> | |||
| 26 | #if defined(__APPLE__) || defined(__linux__1) | |||
| 27 | #include <sys/xattr.h> | |||
| 28 | #endif | |||
| 29 | #include <stdio.h> | |||
| 30 | ||||
| 31 | #define ITEM_DOC":param item: a string representing a file-name, a file-like\n" " object, a file descriptor, or (in Python 3.6+) a path-like\n" " object; this represents the file on which to act\n" \ | |||
| 32 | ":param item: a string representing a file-name, a file-like\n" \ | |||
| 33 | " object, a file descriptor, or (in Python 3.6+) a path-like\n" \ | |||
| 34 | " object; this represents the file on which to act\n" | |||
| 35 | ||||
| 36 | #define NOFOLLOW_DOC":param nofollow: if true and if\n" " the file name given is a symbolic link, the\n" " function will operate on the symbolic link itself instead\n" " of its target; defaults to false\n" ":type nofollow: boolean, optional\n" \ | |||
| 37 | ":param nofollow: if true and if\n" \ | |||
| 38 | " the file name given is a symbolic link, the\n" \ | |||
| 39 | " function will operate on the symbolic link itself instead\n" \ | |||
| 40 | " of its target; defaults to false\n" \ | |||
| 41 | ":type nofollow: boolean, optional\n" \ | |||
| 42 | ||||
| 43 | #define NS_DOC":param namespace: if given, the attribute must not contain the\n" " namespace, but instead it will be taken from this parameter\n" ":type namespace: bytes\n" \ | |||
| 44 | ":param namespace: if given, the attribute must not contain the\n" \ | |||
| 45 | " namespace, but instead it will be taken from this parameter\n" \ | |||
| 46 | ":type namespace: bytes\n" | |||
| 47 | ||||
| 48 | #define NAME_GET_DOC":param string name: the attribute whose value to retrieve;\n" " usually in the form of ``system.posix_acl`` or ``user.mime_type``\n" \ | |||
| 49 | ":param string name: the attribute whose value to retrieve;\n" \ | |||
| 50 | " usually in the form of ``system.posix_acl`` or ``user.mime_type``\n" | |||
| 51 | ||||
| 52 | #define NAME_SET_DOC":param string name: the attribute whose value to set;\n" " usually in the form of ``system.posix_acl`` or ``user.mime_type``\n" \ | |||
| 53 | ":param string name: the attribute whose value to set;\n" \ | |||
| 54 | " usually in the form of ``system.posix_acl`` or ``user.mime_type``\n" | |||
| 55 | ||||
| 56 | #define NAME_REMOVE_DOC":param string name: the attribute to remove;\n" " usually in the form of ``system.posix_acl`` or \n" " ``user.mime_type``\n" \ | |||
| 57 | ":param string name: the attribute to remove;\n" \ | |||
| 58 | " usually in the form of ``system.posix_acl`` or \n" \ | |||
| 59 | " ``user.mime_type``\n" | |||
| 60 | ||||
| 61 | #define VALUE_DOC":param string value: possibly with embedded NULLs; note that there\n" " are restrictions regarding the size of the value, for\n" " example, for ext2/ext3, maximum size is the block size\n" \ | |||
| 62 | ":param string value: possibly with embedded NULLs; note that there\n" \ | |||
| 63 | " are restrictions regarding the size of the value, for\n" \ | |||
| 64 | " example, for ext2/ext3, maximum size is the block size\n" \ | |||
| 65 | ||||
| 66 | #define FLAGS_DOC":param flags: if 0 or omitted the attribute will be\n" " created or replaced; if :const:`XATTR_CREATE`, the attribute\n" " will be created, giving an error if it already exists;\n" " if :const:`XATTR_REPLACE`, the attribute will be replaced,\n" " giving an error if it doesn't exist;\n" ":type flags: integer\n" \ | |||
| 67 | ":param flags: if 0 or omitted the attribute will be\n" \ | |||
| 68 | " created or replaced; if :const:`XATTR_CREATE`, the attribute\n" \ | |||
| 69 | " will be created, giving an error if it already exists;\n" \ | |||
| 70 | " if :const:`XATTR_REPLACE`, the attribute will be replaced,\n" \ | |||
| 71 | " giving an error if it doesn't exist;\n" \ | |||
| 72 | ":type flags: integer\n" | |||
| 73 | ||||
| 74 | #define NS_CHANGED_DOC".. versionchanged:: 0.5.1\n" " The namespace argument, if passed, cannot be None anymore; to\n" " explicitly specify an empty namespace, pass an empty\n" " string (byte string under Python 3)." \ | |||
| 75 | ".. versionchanged:: 0.5.1\n" \ | |||
| 76 | " The namespace argument, if passed, cannot be None anymore; to\n" \ | |||
| 77 | " explicitly specify an empty namespace, pass an empty\n" \ | |||
| 78 | " string (byte string under Python 3)." | |||
| 79 | ||||
| 80 | ||||
| 81 | /* The initial I/O buffer size for list and get operations; if the | |||
| 82 | * actual values will be smaller than this, we save a syscall out of | |||
| 83 | * two and allocate more memory upfront than needed, otherwise we | |||
| 84 | * incur three syscalls (get with ENORANGE, get with 0 to compute | |||
| 85 | * actual size, final get). The test suite is marginally faster (5%) | |||
| 86 | * with this, so it seems worth doing. | |||
| 87 | */ | |||
| 88 | #define ESTIMATE_ATTR_SIZE1024 1024 | |||
| 89 | ||||
| 90 | typedef enum {T_FD, T_PATH, T_LINK} target_e; | |||
| 91 | ||||
| 92 | typedef struct { | |||
| 93 | target_e type; | |||
| 94 | union { | |||
| 95 | const char *name; | |||
| 96 | int fd; | |||
| 97 | }; | |||
| 98 | PyObject *tmp; | |||
| 99 | } target_t; | |||
| 100 | ||||
| 101 | /* Cleans up a tgt structure */ | |||
| 102 | static void free_tgt(target_t *tgt) { | |||
| 103 | if (tgt->tmp != NULL((void*)0)) { | |||
| 104 | Py_DECREF(tgt->tmp)_Py_DECREF(((PyObject*)(tgt->tmp))); | |||
| 105 | } | |||
| 106 | } | |||
| 107 | ||||
| 108 | /* Used for cpychecker: */ | |||
| 109 | /* The checker automatically defines this preprocessor name when creating | |||
| 110 | the custom attribute: */ | |||
| 111 | #if defined(WITH_CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION_ATTRIBUTE) | |||
| 112 | #define CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION \ | |||
| 113 | __attribute__((cpychecker_negative_result_sets_exception)) | |||
| 114 | #else | |||
| 115 | #define CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION | |||
| 116 | #endif | |||
| 117 | ||||
| 118 | static int convert_obj(PyObject *myobj, target_t *tgt, int nofollow) | |||
| 119 | CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; | |||
| 120 | ||||
| 121 | static int merge_ns(const char *ns, const char *name, | |||
| 122 | const char **result, char **buf) | |||
| 123 | CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; | |||
| 124 | ||||
| 125 | ||||
| 126 | /** Converts from a string, file or int argument to what we need. | |||
| 127 | * | |||
| 128 | * Returns -1 on failure, 0 on success. | |||
| 129 | */ | |||
| 130 | static int convert_obj(PyObject *myobj, target_t *tgt, int nofollow) { | |||
| 131 | int fd; | |||
| 132 | tgt->tmp = NULL((void*)0); | |||
| 133 | if((fd = PyObject_AsFileDescriptor(myobj)) != -1) { | |||
| 134 | tgt->type = T_FD; | |||
| 135 | tgt->fd = fd; | |||
| 136 | return 0; | |||
| 137 | } | |||
| 138 | // PyObject_AsFileDescriptor sets an error when failing, so clear | |||
| 139 | // it such that further code works; some method lookups fail if an | |||
| 140 | // error already occured when called, which breaks at least | |||
| 141 | // PyOS_FSPath (called by FSConverter). | |||
| 142 | PyErr_Clear(); | |||
| 143 | ||||
| 144 | if(PyUnicode_FSConverter(myobj, &(tgt->tmp))) { | |||
| 145 | tgt->type = nofollow ? T_LINK : T_PATH; | |||
| 146 | tgt->name = PyBytes_AS_STRING(tgt->tmp)(((void) (0)), (((PyBytesObject *)(tgt->tmp))->ob_sval) ); | |||
| 147 | return 0; | |||
| 148 | } else { | |||
| 149 | // Don't set our own exception type, since we'd ignore the | |||
| 150 | // FSConverter-generated one. | |||
| 151 | tgt->type = T_PATH; | |||
| 152 | tgt->name = NULL((void*)0); | |||
| 153 | return -1; | |||
| 154 | } | |||
| 155 | } | |||
| 156 | ||||
| 157 | /* Combine a namespace string and an attribute name into a | |||
| 158 | fully-qualified name */ | |||
| 159 | static int merge_ns(const char *ns, const char *name, | |||
| 160 | const char **result, char **buf) { | |||
| 161 | if(ns != NULL((void*)0) && *ns != '\0') { | |||
| 162 | int cnt; | |||
| 163 | /* The value of new_size is related to/must be kept in-sync | |||
| 164 | with the format string below */ | |||
| 165 | size_t new_size = strlen(ns) + 1 + strlen(name) + 1; | |||
| 166 | if((*buf = PyMem_Malloc(new_size)) == NULL((void*)0)) { | |||
| 167 | PyErr_NoMemory(); | |||
| 168 | return -1; | |||
| 169 | } | |||
| 170 | cnt = snprintf(*buf, new_size, "%s.%s", ns, name)__builtin___snprintf_chk (*buf, new_size, 2 - 1, __builtin_object_size (*buf, 2 > 1), "%s.%s", ns, name); | |||
| 171 | if((size_t) cnt >= new_size || cnt < 0) { | |||
| 172 | PyErr_SetString(PyExc_ValueError, | |||
| 173 | "unexpected: can't format the attribute name"); | |||
| 174 | PyMem_Free(*buf); | |||
| 175 | return -1; | |||
| 176 | } | |||
| 177 | *result = *buf; | |||
| 178 | } else { | |||
| 179 | *buf = NULL((void*)0); | |||
| 180 | *result = name; | |||
| 181 | } | |||
| 182 | return 0; | |||
| 183 | } | |||
| 184 | ||||
| 185 | #if defined(__APPLE__) | |||
| 186 | static inline ssize_t _listxattr(const char *path, char *namebuf, size_t size)listxattr(const char *path, char *namebuf, size_t size) { | |||
| 187 | return listxattr(path, namebuf, size, 0); | |||
| 188 | } | |||
| 189 | static inline ssize_t _llistxattr(const char *path, char *namebuf, size_t size)llistxattr(const char *path, char *namebuf, size_t size) { | |||
| 190 | return listxattr(path, namebuf, size, XATTR_NOFOLLOW); | |||
| 191 | } | |||
| 192 | static inline ssize_t _flistxattr(int fd, char *namebuf, size_t size)flistxattr(int fd, char *namebuf, size_t size) { | |||
| 193 | return flistxattr(fd, namebuf, size, 0); | |||
| 194 | } | |||
| 195 | ||||
| 196 | static inline ssize_t _getxattr (const char *path, const char *name, void *value, size_t size)getxattr(const char *path, const char *name, void *value, size_t size) { | |||
| 197 | return getxattr(path, name, value, size, 0, 0); | |||
| 198 | } | |||
| 199 | static inline ssize_t _lgetxattr (const char *path, const char *name, void *value, size_t size)lgetxattr(const char *path, const char *name, void *value, size_t size) { | |||
| 200 | return getxattr(path, name, value, size, 0, XATTR_NOFOLLOW); | |||
| 201 | } | |||
| 202 | static inline ssize_t _fgetxattr (int filedes, const char *name, void *value, size_t size)fgetxattr(int filedes, const char *name, void *value, size_t size ) { | |||
| 203 | return fgetxattr(filedes, name, value, size, 0, 0); | |||
| 204 | } | |||
| 205 | ||||
| 206 | // [fl]setxattr: Both OS X and Linux define XATTR_CREATE and XATTR_REPLACE for the last option. | |||
| 207 | static inline int _setxattr(const char *path, const char *name, const void *value, size_t size, int flags)setxattr(const char *path, const char *name, const void *value , size_t size, int flags) { | |||
| 208 | return setxattr(path, name, value, size, 0, flags); | |||
| 209 | } | |||
| 210 | static inline int _lsetxattr(const char *path, const char *name, const void *value, size_t size, int flags)lsetxattr(const char *path, const char *name, const void *value , size_t size, int flags) { | |||
| 211 | return setxattr(path, name, value, size, 0, flags | XATTR_NOFOLLOW); | |||
| 212 | } | |||
| 213 | static inline int _fsetxattr(int filedes, const char *name, const void *value, size_t size, int flags)fsetxattr(int filedes, const char *name, const void *value, size_t size, int flags) { | |||
| 214 | return fsetxattr(filedes, name, value, size, 0, flags); | |||
| 215 | } | |||
| 216 | ||||
| 217 | static inline int _removexattr(const char *path, const char *name)removexattr(const char *path, const char *name) { | |||
| 218 | return removexattr(path, name, 0); | |||
| 219 | } | |||
| 220 | static inline int _lremovexattr(const char *path, const char *name)lremovexattr(const char *path, const char *name) { | |||
| 221 | return removexattr(path, name, XATTR_NOFOLLOW); | |||
| 222 | } | |||
| 223 | static inline int _fremovexattr(int filedes, const char *name)fremovexattr(int filedes, const char *name) { | |||
| 224 | return fremovexattr(filedes, name, 0); | |||
| 225 | } | |||
| 226 | ||||
| 227 | #elif defined(__linux__1) | |||
| 228 | #define _listxattr(path, list, size)listxattr(path, list, size) listxattr(path, list, size) | |||
| 229 | #define _llistxattr(path, list, size)llistxattr(path, list, size) llistxattr(path, list, size) | |||
| 230 | #define _flistxattr(fd, list, size)flistxattr(fd, list, size) flistxattr(fd, list, size) | |||
| 231 | ||||
| 232 | #define _getxattr(path, name, value, size)getxattr(path, name, value, size) getxattr(path, name, value, size) | |||
| 233 | #define _lgetxattr(path, name, value, size)lgetxattr(path, name, value, size) lgetxattr(path, name, value, size) | |||
| 234 | #define _fgetxattr(fd, name, value, size)fgetxattr(fd, name, value, size) fgetxattr(fd, name, value, size) | |||
| 235 | ||||
| 236 | #define _setxattr(path, name, value, size, flags)setxattr(path, name, value, size, flags) setxattr(path, name, value, size, flags) | |||
| 237 | #define _lsetxattr(path, name, value, size, flags)lsetxattr(path, name, value, size, flags) lsetxattr(path, name, value, size, flags) | |||
| 238 | #define _fsetxattr(fd, name, value, size, flags)fsetxattr(fd, name, value, size, flags) fsetxattr(fd, name, value, size, flags) | |||
| 239 | ||||
| 240 | #define _removexattr(path, name)removexattr(path, name) removexattr(path, name) | |||
| 241 | #define _lremovexattr(path, name)lremovexattr(path, name) lremovexattr(path, name) | |||
| 242 | #define _fremovexattr(fd, name)fremovexattr(fd, name) fremovexattr(fd, name) | |||
| 243 | ||||
| 244 | #endif | |||
| 245 | ||||
| 246 | typedef ssize_t (*buf_getter)(target_t *tgt, const char *name, | |||
| 247 | void *output, size_t size); | |||
| 248 | ||||
| 249 | static ssize_t _list_obj(target_t *tgt, const char *unused, void *list, | |||
| 250 | size_t size) { | |||
| 251 | ssize_t ret; | |||
| 252 | ||||
| 253 | Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread();; | |||
| 254 | if(tgt->type == T_FD) | |||
| 255 | ret = _flistxattr(tgt->fd, list, size)flistxattr(tgt->fd, list, size); | |||
| 256 | else if (tgt->type == T_LINK) | |||
| 257 | ret = _llistxattr(tgt->name, list, size)llistxattr(tgt->name, list, size); | |||
| 258 | else | |||
| 259 | ret = _listxattr(tgt->name, list, size)listxattr(tgt->name, list, size); | |||
| 260 | Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); }; | |||
| 261 | return ret; | |||
| 262 | } | |||
| 263 | ||||
| 264 | static ssize_t _get_obj(target_t *tgt, const char *name, void *value, | |||
| 265 | size_t size) { | |||
| 266 | ssize_t ret; | |||
| 267 | Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread();; | |||
| 268 | if(tgt->type == T_FD) | |||
| 269 | ret = _fgetxattr(tgt->fd, name, value, size)fgetxattr(tgt->fd, name, value, size); | |||
| 270 | else if (tgt->type == T_LINK) | |||
| 271 | ret = _lgetxattr(tgt->name, name, value, size)lgetxattr(tgt->name, name, value, size); | |||
| 272 | else | |||
| 273 | ret = _getxattr(tgt->name, name, value, size)getxattr(tgt->name, name, value, size); | |||
| 274 | Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); }; | |||
| 275 | return ret; | |||
| 276 | } | |||
| 277 | ||||
| 278 | static int _set_obj(target_t *tgt, const char *name, | |||
| 279 | const void *value, size_t size, int flags) { | |||
| 280 | int ret; | |||
| 281 | Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread();; | |||
| 282 | if(tgt->type == T_FD) | |||
| 283 | ret = _fsetxattr(tgt->fd, name, value, size, flags)fsetxattr(tgt->fd, name, value, size, flags); | |||
| 284 | else if (tgt->type == T_LINK) | |||
| 285 | ret = _lsetxattr(tgt->name, name, value, size, flags)lsetxattr(tgt->name, name, value, size, flags); | |||
| 286 | else | |||
| 287 | ret = _setxattr(tgt->name, name, value, size, flags)setxattr(tgt->name, name, value, size, flags); | |||
| 288 | Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); }; | |||
| 289 | return ret; | |||
| 290 | } | |||
| 291 | ||||
| 292 | static int _remove_obj(target_t *tgt, const char *name) { | |||
| 293 | int ret; | |||
| 294 | Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread();; | |||
| 295 | if(tgt->type == T_FD) | |||
| 296 | ret = _fremovexattr(tgt->fd, name)fremovexattr(tgt->fd, name); | |||
| 297 | else if (tgt->type == T_LINK) | |||
| 298 | ret = _lremovexattr(tgt->name, name)lremovexattr(tgt->name, name); | |||
| 299 | else | |||
| 300 | ret = _removexattr(tgt->name, name)removexattr(tgt->name, name); | |||
| 301 | Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); }; | |||
| 302 | return ret; | |||
| 303 | } | |||
| 304 | ||||
| 305 | /* Perform a get/list operation with appropriate buffer size, | |||
| 306 | * determined dynamically. | |||
| 307 | * | |||
| 308 | * Arguments: | |||
| 309 | * - getter: the function that actually does the I/O. | |||
| 310 | * - tgt, name: passed to the getter. | |||
| 311 | * - buffer: pointer to either an already allocated memory area (in | |||
| 312 | * which case size contains its current size), or NULL to | |||
| 313 | * allocate. In all cases (success or failure), the caller should | |||
| 314 | * deallocate the buffer, using PyMem_Free(). | |||
| 315 | * - size: either size of current buffer (if non-NULL), or size for | |||
| 316 | * initial allocation; zero means use a hardcoded initial buffer | |||
| 317 | * size (ESTIMATE_ATTR_SIZE). The value will be updated upon return | |||
| 318 | * with the current buffer size. | |||
| 319 | * - io_errno: if non-NULL, the actual errno will be recorded here; if | |||
| 320 | * zero, the call was successful and the output/size/nval are valid. | |||
| 321 | * | |||
| 322 | * Return value: if positive or zero, buffer will contain the read | |||
| 323 | * value. Otherwise, io_errno will contain the I/O errno, or zero | |||
| 324 | * to signify a Python-level error. In all cases, the Python-level | |||
| 325 | * error is set to the appropriate value. | |||
| 326 | */ | |||
| 327 | static ssize_t _generic_get(buf_getter getter, target_t *tgt, | |||
| 328 | const char *name, | |||
| 329 | char **buffer, | |||
| 330 | size_t *size, | |||
| 331 | int *io_errno) | |||
| 332 | CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION; | |||
| 333 | ||||
| 334 | static ssize_t _generic_get(buf_getter getter, target_t *tgt, | |||
| 335 | const char *name, | |||
| 336 | char **buffer, | |||
| 337 | size_t *size, | |||
| 338 | int *io_errno) { | |||
| 339 | ssize_t res; | |||
| 340 | /* Clear errno for now, will only set it when it fails in I/O. */ | |||
| 341 | if (io_errno != NULL((void*)0)) { | |||
| 342 | *io_errno = 0; | |||
| 343 | } | |||
| 344 | ||||
| 345 | #define EXIT_IOERROR() \ | |||
| 346 | { \ | |||
| 347 | if (io_errno != NULL((void*)0)) { \ | |||
| 348 | *io_errno = errno(*__errno_location ()); \ | |||
| 349 | } \ | |||
| 350 | PyErr_SetFromErrno(PyExc_IOError); \ | |||
| 351 | return -1; \ | |||
| 352 | } | |||
| 353 | ||||
| 354 | /* Initialize the buffer, if needed. */ | |||
| 355 | if (*buffer == NULL((void*)0)) { | |||
| 356 | if (*size == 0) | |||
| 357 | *size = ESTIMATE_ATTR_SIZE1024; | |||
| 358 | if((*buffer = PyMem_Malloc(*size)) == NULL((void*)0)) { | |||
| 359 | PyErr_NoMemory(); | |||
| 360 | return -1; | |||
| 361 | } | |||
| 362 | } | |||
| 363 | // Try to get the value, while increasing the buffer if too small. | |||
| 364 | while((res = getter(tgt, name, *buffer, *size)) == -1) { | |||
| 365 | if(errno(*__errno_location ()) == ERANGE34) { | |||
| 366 | ssize_t realloc_size_s = getter(tgt, name, NULL((void*)0), 0); | |||
| 367 | /* ERANGE + proper size _should_ not fail, but... */ | |||
| 368 | if(realloc_size_s == -1) { | |||
| 369 | EXIT_IOERROR(); | |||
| 370 | } | |||
| 371 | size_t realloc_size = (size_t) realloc_size_s; | |||
| 372 | char *tmp_buf; | |||
| 373 | if((tmp_buf = PyMem_Realloc(*buffer, realloc_size)) == NULL((void*)0)) { | |||
| 374 | PyErr_NoMemory(); | |||
| 375 | return -1; | |||
| 376 | } | |||
| 377 | *buffer = tmp_buf; | |||
| 378 | *size = realloc_size; | |||
| 379 | continue; | |||
| 380 | } else { | |||
| 381 | /* else we're dealing with a different error, which we | |||
| 382 | don't know how to handle nicely, so we return */ | |||
| 383 | EXIT_IOERROR(); | |||
| 384 | } | |||
| 385 | } | |||
| 386 | return res; | |||
| 387 | #undef EXIT_IOERROR | |||
| 388 | } | |||
| 389 | ||||
| 390 | /* | |||
| 391 | Checks if an attribute name matches an optional namespace. | |||
| 392 | ||||
| 393 | If the namespace is NULL or an empty string, it will return the | |||
| 394 | name itself. If the namespace is non-NULL and the name matches, it | |||
| 395 | will return a pointer to the offset in the name after the namespace | |||
| 396 | and the separator. If however the name doesn't match the namespace, | |||
| 397 | it will return NULL. | |||
| 398 | ||||
| 399 | */ | |||
| 400 | const char *matches_ns(const char *ns, const char *name) { | |||
| 401 | size_t ns_size; | |||
| 402 | if (ns == NULL((void*)0) || *ns == '\0') | |||
| 403 | return name; | |||
| 404 | ns_size = strlen(ns); | |||
| 405 | ||||
| 406 | if (strlen(name) > (ns_size+1) && !strncmp(name, ns, ns_size) && | |||
| 407 | name[ns_size] == '.') | |||
| 408 | return name + ns_size + 1; | |||
| 409 | return NULL((void*)0); | |||
| 410 | } | |||
| 411 | ||||
| 412 | /* Wrapper for getxattr */ | |||
| 413 | static char __pygetxattr_doc__[] = | |||
| 414 | "getxattr(item, attribute[, nofollow=False])\n" | |||
| 415 | "Get the value of a given extended attribute (deprecated).\n" | |||
| 416 | "\n" | |||
| 417 | ITEM_DOC":param item: a string representing a file-name, a file-like\n" " object, a file descriptor, or (in Python 3.6+) a path-like\n" " object; this represents the file on which to act\n" | |||
| 418 | NAME_GET_DOC":param string name: the attribute whose value to retrieve;\n" " usually in the form of ``system.posix_acl`` or ``user.mime_type``\n" | |||
| 419 | NOFOLLOW_DOC":param nofollow: if true and if\n" " the file name given is a symbolic link, the\n" " function will operate on the symbolic link itself instead\n" " of its target; defaults to false\n" ":type nofollow: boolean, optional\n" | |||
| 420 | "\n" | |||
| 421 | ".. deprecated:: 0.4\n" | |||
| 422 | " this function has been deprecated\n" | |||
| 423 | " by the :func:`get` function.\n" | |||
| 424 | ; | |||
| 425 | ||||
| 426 | static PyObject * | |||
| 427 | pygetxattr(PyObject *self, PyObject *args) | |||
| 428 | { | |||
| 429 | PyObject *myarg; | |||
| 430 | target_t tgt; | |||
| 431 | int nofollow = 0; | |||
| 432 | char *attrname = NULL((void*)0); | |||
| 433 | char *buf = NULL((void*)0); | |||
| 434 | ssize_t nret; | |||
| 435 | size_t nalloc = 0; | |||
| 436 | PyObject *res; | |||
| 437 | ||||
| 438 | /* Parse the arguments */ | |||
| 439 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "Oet|i", &myarg, NULL((void*)0), &attrname, &nofollow)) | |||
| 440 | return NULL((void*)0); | |||
| 441 | if(convert_obj(myarg, &tgt, nofollow) < 0) { | |||
| 442 | res = NULL((void*)0); | |||
| 443 | goto free_arg; | |||
| 444 | } | |||
| 445 | ||||
| 446 | nret = _generic_get(_get_obj, &tgt, attrname, &buf, &nalloc, NULL((void*)0)); | |||
| 447 | if (nret == -1) { | |||
| 448 | res = NULL((void*)0); | |||
| 449 | goto free_buf; | |||
| 450 | } | |||
| 451 | /* Create the string which will hold the result */ | |||
| 452 | res = PyBytes_FromStringAndSize(buf, nret); | |||
| 453 | ||||
| 454 | free_buf: | |||
| 455 | /* Free the buffer, now it is no longer needed */ | |||
| 456 | PyMem_Free(buf); | |||
| 457 | free_tgt(&tgt); | |||
| 458 | free_arg: | |||
| 459 | PyMem_Free(attrname); | |||
| 460 | ||||
| 461 | /* Return the result */ | |||
| 462 | return res; | |||
| 463 | } | |||
| 464 | ||||
| 465 | /* Wrapper for getxattr */ | |||
| 466 | static char __get_doc__[] = | |||
| 467 | "get(item, name[, nofollow=False, namespace=None])\n" | |||
| 468 | "Get the value of a given extended attribute.\n" | |||
| 469 | "\n" | |||
| 470 | "Example:\n" | |||
| 471 | " >>> xattr.get('/path/to/file', 'user.comment')\n" | |||
| 472 | " 'test'\n" | |||
| 473 | " >>> xattr.get('/path/to/file', 'comment', namespace=xattr.NS_USER)\n" | |||
| 474 | " 'test'\n" | |||
| 475 | "\n" | |||
| 476 | ITEM_DOC":param item: a string representing a file-name, a file-like\n" " object, a file descriptor, or (in Python 3.6+) a path-like\n" " object; this represents the file on which to act\n" | |||
| 477 | NAME_GET_DOC":param string name: the attribute whose value to retrieve;\n" " usually in the form of ``system.posix_acl`` or ``user.mime_type``\n" | |||
| 478 | NOFOLLOW_DOC":param nofollow: if true and if\n" " the file name given is a symbolic link, the\n" " function will operate on the symbolic link itself instead\n" " of its target; defaults to false\n" ":type nofollow: boolean, optional\n" | |||
| 479 | NS_DOC":param namespace: if given, the attribute must not contain the\n" " namespace, but instead it will be taken from this parameter\n" ":type namespace: bytes\n" | |||
| 480 | ":return: the value of the extended attribute (can contain NULLs)\n" | |||
| 481 | ":rtype: string\n" | |||
| 482 | ":raises EnvironmentError: caused by any system errors\n" | |||
| 483 | "\n" | |||
| 484 | ".. versionadded:: 0.4\n" | |||
| 485 | NS_CHANGED_DOC".. versionchanged:: 0.5.1\n" " The namespace argument, if passed, cannot be None anymore; to\n" " explicitly specify an empty namespace, pass an empty\n" " string (byte string under Python 3)." | |||
| 486 | ; | |||
| 487 | ||||
| 488 | static PyObject * | |||
| 489 | xattr_get(PyObject *self, PyObject *args, PyObject *keywds) | |||
| 490 | { | |||
| 491 | PyObject *myarg; | |||
| 492 | target_t tgt; | |||
| 493 | int nofollow = 0; | |||
| 494 | char *attrname = NULL((void*)0), *namebuf; | |||
| 495 | const char *fullname; | |||
| 496 | char *buf = NULL((void*)0); | |||
| 497 | const char *ns = NULL((void*)0); | |||
| 498 | ssize_t nret; | |||
| 499 | size_t nalloc = 0; | |||
| 500 | PyObject *res = NULL((void*)0); | |||
| 501 | static char *kwlist[] = {"item", "name", "nofollow", "namespace", NULL((void*)0)}; | |||
| 502 | ||||
| 503 | /* Parse the arguments */ | |||
| 504 | if (!PyArg_ParseTupleAndKeywords_PyArg_ParseTupleAndKeywords_SizeT(args, keywds, "Oet|iy", kwlist, | |||
| 505 | &myarg, NULL((void*)0), &attrname, &nofollow, &ns)) | |||
| 506 | return NULL((void*)0); | |||
| 507 | res = NULL((void*)0); | |||
| 508 | if(convert_obj(myarg, &tgt, nofollow) < 0) { | |||
| 509 | goto free_arg; | |||
| 510 | } | |||
| 511 | ||||
| 512 | if(merge_ns(ns, attrname, &fullname, &namebuf) < 0) { | |||
| 513 | goto free_tgt; | |||
| 514 | } | |||
| 515 | ||||
| 516 | nret = _generic_get(_get_obj, &tgt, fullname, &buf, &nalloc, NULL((void*)0)); | |||
| 517 | if(nret == -1) { | |||
| 518 | goto free_buf; | |||
| 519 | } | |||
| 520 | ||||
| 521 | /* Create the string which will hold the result */ | |||
| 522 | res = PyBytes_FromStringAndSize(buf, nret); | |||
| 523 | ||||
| 524 | /* Free the buffers, they are no longer needed */ | |||
| 525 | free_buf: | |||
| 526 | PyMem_Free(buf); | |||
| 527 | PyMem_Free(namebuf); | |||
| 528 | free_tgt: | |||
| 529 | free_tgt(&tgt); | |||
| 530 | free_arg: | |||
| 531 | PyMem_Free(attrname); | |||
| 532 | ||||
| 533 | /* Return the result */ | |||
| 534 | return res; | |||
| 535 | } | |||
| 536 | ||||
| 537 | /* Wrapper for getxattr */ | |||
| 538 | static char __get_all_doc__[] = | |||
| 539 | "get_all(item[, nofollow=False, namespace=None])\n" | |||
| 540 | "Get all the extended attributes of an item.\n" | |||
| 541 | "\n" | |||
| 542 | "This function performs a bulk-get of all extended attribute names\n" | |||
| 543 | "and the corresponding value.\n" | |||
| 544 | "Example:\n" | |||
| 545 | "\n" | |||
| 546 | " >>> xattr.get_all('/path/to/file')\n" | |||
| 547 | " [('user.mime-type', 'plain/text'), ('user.comment', 'test'),\n" | |||
| 548 | " ('system.posix_acl_access', '\\x02\\x00...')]\n" | |||
| 549 | " >>> xattr.get_all('/path/to/file', namespace=xattr.NS_USER)\n" | |||
| 550 | " [('mime-type', 'plain/text'), ('comment', 'test')]\n" | |||
| 551 | "\n" | |||
| 552 | ITEM_DOC":param item: a string representing a file-name, a file-like\n" " object, a file descriptor, or (in Python 3.6+) a path-like\n" " object; this represents the file on which to act\n" | |||
| 553 | ":keyword namespace: an optional namespace for filtering the\n" | |||
| 554 | " attributes; for example, querying all user attributes can be\n" | |||
| 555 | " accomplished by passing namespace=:const:`NS_USER`\n" | |||
| 556 | ":type namespace: string\n" | |||
| 557 | NOFOLLOW_DOC":param nofollow: if true and if\n" " the file name given is a symbolic link, the\n" " function will operate on the symbolic link itself instead\n" " of its target; defaults to false\n" ":type nofollow: boolean, optional\n" | |||
| 558 | ":return: list of tuples (name, value); note that if a namespace\n" | |||
| 559 | " argument was passed, it (and the separator) will be stripped from\n" | |||
| 560 | " the names returned\n" | |||
| 561 | ":rtype: list\n" | |||
| 562 | ":raises EnvironmentError: caused by any system errors\n" | |||
| 563 | "\n" | |||
| 564 | ".. note:: Since reading the whole attribute list is not an atomic\n" | |||
| 565 | " operation, it might be possible that attributes are added\n" | |||
| 566 | " or removed between the initial query and the actual reading\n" | |||
| 567 | " of the attributes; the returned list will contain only the\n" | |||
| 568 | " attributes that were present at the initial listing of the\n" | |||
| 569 | " attribute names and that were still present when the read\n" | |||
| 570 | " attempt for the value is made.\n" | |||
| 571 | ".. versionadded:: 0.4\n" | |||
| 572 | NS_CHANGED_DOC".. versionchanged:: 0.5.1\n" " The namespace argument, if passed, cannot be None anymore; to\n" " explicitly specify an empty namespace, pass an empty\n" " string (byte string under Python 3)." | |||
| 573 | ; | |||
| 574 | ||||
| 575 | static PyObject * | |||
| 576 | get_all(PyObject *self, PyObject *args, PyObject *keywds) | |||
| 577 | { | |||
| 578 | PyObject *myarg, *res; | |||
| 579 | int nofollow=0; | |||
| 580 | const char *ns = NULL((void*)0); | |||
| 581 | char *buf_list = NULL((void*)0), *buf_val = NULL((void*)0); | |||
| 582 | const char *s; | |||
| 583 | size_t nalloc = 0; | |||
| 584 | ssize_t nlist, nval; | |||
| 585 | PyObject *mylist; | |||
| 586 | target_t tgt; | |||
| 587 | static char *kwlist[] = {"item", "nofollow", "namespace", NULL((void*)0)}; | |||
| 588 | int io_errno; | |||
| 589 | ||||
| 590 | /* Parse the arguments */ | |||
| 591 | if (!PyArg_ParseTupleAndKeywords_PyArg_ParseTupleAndKeywords_SizeT(args, keywds, "O|iy", kwlist, | |||
| ||||
| 592 | &myarg, &nofollow, &ns)) | |||
| 593 | return NULL((void*)0); | |||
| 594 | if(convert_obj(myarg, &tgt, nofollow) < 0) | |||
| 595 | return NULL((void*)0); | |||
| 596 | ||||
| 597 | res = NULL((void*)0); | |||
| 598 | /* Compute first the list of attributes */ | |||
| 599 | nlist = _generic_get(_list_obj, &tgt, NULL((void*)0), &buf_list, | |||
| 600 | &nalloc, &io_errno); | |||
| 601 | if (nlist == -1) { | |||
| 602 | /* We can't handle any errors, and the Python error is already | |||
| 603 | set, just bail out. */ | |||
| 604 | goto free_tgt; | |||
| 605 | } | |||
| 606 | ||||
| 607 | /* Create the list which will hold the result. */ | |||
| 608 | mylist = PyList_New(0); | |||
| 609 | if(mylist == NULL((void*)0)) { | |||
| 610 | goto free_buf_list; | |||
| 611 | } | |||
| 612 | ||||
| 613 | nalloc = 0; | |||
| 614 | /* Create and insert the attributes as strings in the list */ | |||
| 615 | for(s = buf_list; s - buf_list < nlist; s += strlen(s) + 1) { | |||
| 616 | PyObject *my_tuple; | |||
| 617 | const char *name; | |||
| 618 | ||||
| 619 | if((name = matches_ns(ns, s)) == NULL((void*)0)) | |||
| 620 | continue; | |||
| 621 | /* Now retrieve the attribute value */ | |||
| 622 | nval = _generic_get(_get_obj, &tgt, s, &buf_val, &nalloc, &io_errno); | |||
| 623 | if (nval == -1) { | |||
| 624 | if (io_errno == ENODATA61) { | |||
| 625 | PyErr_Clear(); | |||
| 626 | continue; | |||
| 627 | } else { | |||
| 628 | Py_DECREF(mylist)_Py_DECREF(((PyObject*)(mylist))); | |||
| 629 | goto free_buf_val; | |||
| 630 | } | |||
| 631 | } | |||
| 632 | my_tuple = Py_BuildValue_Py_BuildValue_SizeT("yy#", name, buf_val, nval); | |||
| ||||
| 633 | if (my_tuple == NULL((void*)0)) { | |||
| 634 | Py_DECREF(mylist)_Py_DECREF(((PyObject*)(mylist))); | |||
| 635 | goto free_buf_val; | |||
| 636 | } | |||
| 637 | if(PyList_Append(mylist, my_tuple) < 0) { | |||
| 638 | Py_DECREF(mylist)_Py_DECREF(((PyObject*)(mylist))); | |||
| 639 | goto free_buf_val; | |||
| 640 | } | |||
| 641 | Py_DECREF(my_tuple)_Py_DECREF(((PyObject*)(my_tuple))); | |||
| 642 | } | |||
| 643 | ||||
| 644 | /* Successful exit */ | |||
| 645 | res = mylist; | |||
| 646 | ||||
| 647 | free_buf_val: | |||
| 648 | PyMem_Free(buf_val); | |||
| 649 | ||||
| 650 | free_buf_list: | |||
| 651 | PyMem_Free(buf_list); | |||
| 652 | ||||
| 653 | free_tgt: | |||
| 654 | free_tgt(&tgt); | |||
| 655 | ||||
| 656 | /* Return the result */ | |||
| 657 | return res; | |||
| 658 | } | |||
| 659 | ||||
| 660 | ||||
| 661 | static char __pysetxattr_doc__[] = | |||
| 662 | "setxattr(item, name, value[, flags=0, nofollow=False])\n" | |||
| 663 | "Set the value of a given extended attribute (deprecated).\n" | |||
| 664 | "\n" | |||
| 665 | "Be careful in case you want to set attributes on symbolic\n" | |||
| 666 | "links, you have to use all the 5 parameters; use 0 for the \n" | |||
| 667 | "flags value if you want the default behaviour (create or " | |||
| 668 | "replace)\n" | |||
| 669 | "\n" | |||
| 670 | ITEM_DOC":param item: a string representing a file-name, a file-like\n" " object, a file descriptor, or (in Python 3.6+) a path-like\n" " object; this represents the file on which to act\n" | |||
| 671 | NAME_SET_DOC":param string name: the attribute whose value to set;\n" " usually in the form of ``system.posix_acl`` or ``user.mime_type``\n" | |||
| 672 | VALUE_DOC":param string value: possibly with embedded NULLs; note that there\n" " are restrictions regarding the size of the value, for\n" " example, for ext2/ext3, maximum size is the block size\n" | |||
| 673 | FLAGS_DOC":param flags: if 0 or omitted the attribute will be\n" " created or replaced; if :const:`XATTR_CREATE`, the attribute\n" " will be created, giving an error if it already exists;\n" " if :const:`XATTR_REPLACE`, the attribute will be replaced,\n" " giving an error if it doesn't exist;\n" ":type flags: integer\n" | |||
| 674 | NOFOLLOW_DOC":param nofollow: if true and if\n" " the file name given is a symbolic link, the\n" " function will operate on the symbolic link itself instead\n" " of its target; defaults to false\n" ":type nofollow: boolean, optional\n" | |||
| 675 | "\n" | |||
| 676 | ".. deprecated:: 0.4\n" | |||
| 677 | " this function has been deprecated\n" | |||
| 678 | " by the :func:`set` function.\n" | |||
| 679 | ; | |||
| 680 | ||||
| 681 | /* Wrapper for setxattr */ | |||
| 682 | static PyObject * | |||
| 683 | pysetxattr(PyObject *self, PyObject *args) | |||
| 684 | { | |||
| 685 | PyObject *myarg, *res; | |||
| 686 | int nofollow = 0; | |||
| 687 | char *attrname = NULL((void*)0); | |||
| 688 | char *buf = NULL((void*)0); | |||
| 689 | Py_ssize_t bufsize_s; | |||
| 690 | size_t bufsize; | |||
| 691 | int nret; | |||
| 692 | int flags = 0; | |||
| 693 | target_t tgt; | |||
| 694 | ||||
| 695 | /* Parse the arguments */ | |||
| 696 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "Oetet#|ii", &myarg, NULL((void*)0), &attrname, | |||
| 697 | NULL((void*)0), &buf, &bufsize_s, &flags, &nofollow)) | |||
| 698 | return NULL((void*)0); | |||
| 699 | ||||
| 700 | if (bufsize_s < 0) { | |||
| 701 | PyErr_SetString(PyExc_ValueError, | |||
| 702 | "negative value size?!"); | |||
| 703 | res = NULL((void*)0); | |||
| 704 | goto free_arg; | |||
| 705 | } | |||
| 706 | bufsize = (size_t) bufsize_s; | |||
| 707 | ||||
| 708 | if(convert_obj(myarg, &tgt, nofollow) < 0) { | |||
| 709 | res = NULL((void*)0); | |||
| 710 | goto free_arg; | |||
| 711 | } | |||
| 712 | ||||
| 713 | /* Set the attribute's value */ | |||
| 714 | nret = _set_obj(&tgt, attrname, buf, bufsize, flags); | |||
| 715 | ||||
| 716 | free_tgt(&tgt); | |||
| 717 | ||||
| 718 | if(nret == -1) { | |||
| 719 | res = PyErr_SetFromErrno(PyExc_IOError); | |||
| 720 | goto free_arg; | |||
| 721 | } | |||
| 722 | ||||
| 723 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
| 724 | res = Py_None(&_Py_NoneStruct); | |||
| 725 | ||||
| 726 | free_arg: | |||
| 727 | PyMem_Free(attrname); | |||
| 728 | PyMem_Free(buf); | |||
| 729 | ||||
| 730 | /* Return the result */ | |||
| 731 | return res; | |||
| 732 | } | |||
| 733 | ||||
| 734 | static char __set_doc__[] = | |||
| 735 | "set(item, name, value[, flags=0, namespace=None])\n" | |||
| 736 | "Set the value of a given extended attribute.\n" | |||
| 737 | "\n" | |||
| 738 | "Example:\n" | |||
| 739 | "\n" | |||
| 740 | " >>> xattr.set('/path/to/file', 'user.comment', 'test')\n" | |||
| 741 | " >>> xattr.set('/path/to/file', 'comment', 'test'," | |||
| 742 | " namespace=xattr.NS_USER)\n" | |||
| 743 | "\n" | |||
| 744 | ITEM_DOC":param item: a string representing a file-name, a file-like\n" " object, a file descriptor, or (in Python 3.6+) a path-like\n" " object; this represents the file on which to act\n" | |||
| 745 | NAME_SET_DOC":param string name: the attribute whose value to set;\n" " usually in the form of ``system.posix_acl`` or ``user.mime_type``\n" | |||
| 746 | VALUE_DOC":param string value: possibly with embedded NULLs; note that there\n" " are restrictions regarding the size of the value, for\n" " example, for ext2/ext3, maximum size is the block size\n" | |||
| 747 | FLAGS_DOC":param flags: if 0 or omitted the attribute will be\n" " created or replaced; if :const:`XATTR_CREATE`, the attribute\n" " will be created, giving an error if it already exists;\n" " if :const:`XATTR_REPLACE`, the attribute will be replaced,\n" " giving an error if it doesn't exist;\n" ":type flags: integer\n" | |||
| 748 | NOFOLLOW_DOC":param nofollow: if true and if\n" " the file name given is a symbolic link, the\n" " function will operate on the symbolic link itself instead\n" " of its target; defaults to false\n" ":type nofollow: boolean, optional\n" | |||
| 749 | NS_DOC":param namespace: if given, the attribute must not contain the\n" " namespace, but instead it will be taken from this parameter\n" ":type namespace: bytes\n" | |||
| 750 | ":returns: None\n" | |||
| 751 | ":raises EnvironmentError: caused by any system errors\n" | |||
| 752 | "\n" | |||
| 753 | ".. versionadded:: 0.4\n" | |||
| 754 | NS_CHANGED_DOC".. versionchanged:: 0.5.1\n" " The namespace argument, if passed, cannot be None anymore; to\n" " explicitly specify an empty namespace, pass an empty\n" " string (byte string under Python 3)." | |||
| 755 | ; | |||
| 756 | ||||
| 757 | /* Wrapper for setxattr */ | |||
| 758 | static PyObject * | |||
| 759 | xattr_set(PyObject *self, PyObject *args, PyObject *keywds) | |||
| 760 | { | |||
| 761 | PyObject *myarg, *res; | |||
| 762 | int nofollow = 0; | |||
| 763 | char *attrname = NULL((void*)0); | |||
| 764 | char *buf = NULL((void*)0); | |||
| 765 | Py_ssize_t bufsize_s; | |||
| 766 | size_t bufsize; | |||
| 767 | int nret; | |||
| 768 | int flags = 0; | |||
| 769 | target_t tgt; | |||
| 770 | const char *ns = NULL((void*)0); | |||
| 771 | char *newname; | |||
| 772 | const char *full_name; | |||
| 773 | static char *kwlist[] = {"item", "name", "value", "flags", | |||
| 774 | "nofollow", "namespace", NULL((void*)0)}; | |||
| 775 | ||||
| 776 | /* Parse the arguments */ | |||
| 777 | if (!PyArg_ParseTupleAndKeywords_PyArg_ParseTupleAndKeywords_SizeT(args, keywds, "Oetet#|iiy", | |||
| 778 | kwlist, &myarg, NULL((void*)0), &attrname, NULL((void*)0), | |||
| 779 | &buf, &bufsize_s, &flags, &nofollow, &ns)) | |||
| 780 | return NULL((void*)0); | |||
| 781 | ||||
| 782 | if (bufsize_s < 0) { | |||
| 783 | PyErr_SetString(PyExc_ValueError, | |||
| 784 | "negative value size?!"); | |||
| 785 | res = NULL((void*)0); | |||
| 786 | goto free_arg; | |||
| 787 | } | |||
| 788 | bufsize = (size_t) bufsize_s; | |||
| 789 | ||||
| 790 | if(convert_obj(myarg, &tgt, nofollow) < 0) { | |||
| 791 | res = NULL((void*)0); | |||
| 792 | goto free_arg; | |||
| 793 | } | |||
| 794 | ||||
| 795 | if(merge_ns(ns, attrname, &full_name, &newname) < 0) { | |||
| 796 | res = NULL((void*)0); | |||
| 797 | goto free_arg; | |||
| 798 | } | |||
| 799 | ||||
| 800 | /* Set the attribute's value */ | |||
| 801 | nret = _set_obj(&tgt, full_name, buf, bufsize, flags); | |||
| 802 | ||||
| 803 | PyMem_Free(newname); | |||
| 804 | ||||
| 805 | free_tgt(&tgt); | |||
| 806 | ||||
| 807 | if(nret == -1) { | |||
| 808 | res = PyErr_SetFromErrno(PyExc_IOError); | |||
| 809 | goto free_arg; | |||
| 810 | } | |||
| 811 | ||||
| 812 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
| 813 | res = Py_None(&_Py_NoneStruct); | |||
| 814 | ||||
| 815 | free_arg: | |||
| 816 | PyMem_Free(attrname); | |||
| 817 | PyMem_Free(buf); | |||
| 818 | ||||
| 819 | /* Return the result */ | |||
| 820 | return res; | |||
| 821 | } | |||
| 822 | ||||
| 823 | ||||
| 824 | static char __pyremovexattr_doc__[] = | |||
| 825 | "removexattr(item, name[, nofollow])\n" | |||
| 826 | "Remove an attribute from a file (deprecated).\n" | |||
| 827 | "\n" | |||
| 828 | ITEM_DOC":param item: a string representing a file-name, a file-like\n" " object, a file descriptor, or (in Python 3.6+) a path-like\n" " object; this represents the file on which to act\n" | |||
| 829 | NAME_REMOVE_DOC":param string name: the attribute to remove;\n" " usually in the form of ``system.posix_acl`` or \n" " ``user.mime_type``\n" | |||
| 830 | NOFOLLOW_DOC":param nofollow: if true and if\n" " the file name given is a symbolic link, the\n" " function will operate on the symbolic link itself instead\n" " of its target; defaults to false\n" ":type nofollow: boolean, optional\n" | |||
| 831 | "\n" | |||
| 832 | ".. deprecated:: 0.4\n" | |||
| 833 | " this function has been deprecated by the :func:`remove` function.\n" | |||
| 834 | ; | |||
| 835 | ||||
| 836 | /* Wrapper for removexattr */ | |||
| 837 | static PyObject * | |||
| 838 | pyremovexattr(PyObject *self, PyObject *args) | |||
| 839 | { | |||
| 840 | PyObject *myarg, *res; | |||
| 841 | int nofollow = 0; | |||
| 842 | char *attrname = NULL((void*)0); | |||
| 843 | int nret; | |||
| 844 | target_t tgt; | |||
| 845 | ||||
| 846 | /* Parse the arguments */ | |||
| 847 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "Oet|i", &myarg, NULL((void*)0), &attrname, &nofollow)) | |||
| 848 | return NULL((void*)0); | |||
| 849 | ||||
| 850 | if(convert_obj(myarg, &tgt, nofollow) < 0) { | |||
| 851 | res = NULL((void*)0); | |||
| 852 | goto free_arg; | |||
| 853 | } | |||
| 854 | ||||
| 855 | /* Remove the attribute */ | |||
| 856 | nret = _remove_obj(&tgt, attrname); | |||
| 857 | ||||
| 858 | free_tgt(&tgt); | |||
| 859 | ||||
| 860 | if(nret == -1) { | |||
| 861 | res = PyErr_SetFromErrno(PyExc_IOError); | |||
| 862 | goto free_arg; | |||
| 863 | } | |||
| 864 | ||||
| 865 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
| 866 | res = Py_None(&_Py_NoneStruct); | |||
| 867 | ||||
| 868 | free_arg: | |||
| 869 | PyMem_Free(attrname); | |||
| 870 | ||||
| 871 | /* Return the result */ | |||
| 872 | return res; | |||
| 873 | } | |||
| 874 | ||||
| 875 | static char __remove_doc__[] = | |||
| 876 | "remove(item, name[, nofollow=False, namespace=None])\n" | |||
| 877 | "Remove an attribute from a file.\n" | |||
| 878 | "\n" | |||
| 879 | "Example:\n" | |||
| 880 | "\n" | |||
| 881 | " >>> xattr.remove('/path/to/file', 'user.comment')\n" | |||
| 882 | "\n" | |||
| 883 | ITEM_DOC":param item: a string representing a file-name, a file-like\n" " object, a file descriptor, or (in Python 3.6+) a path-like\n" " object; this represents the file on which to act\n" | |||
| 884 | NAME_REMOVE_DOC":param string name: the attribute to remove;\n" " usually in the form of ``system.posix_acl`` or \n" " ``user.mime_type``\n" | |||
| 885 | NOFOLLOW_DOC":param nofollow: if true and if\n" " the file name given is a symbolic link, the\n" " function will operate on the symbolic link itself instead\n" " of its target; defaults to false\n" ":type nofollow: boolean, optional\n" | |||
| 886 | NS_DOC":param namespace: if given, the attribute must not contain the\n" " namespace, but instead it will be taken from this parameter\n" ":type namespace: bytes\n" | |||
| 887 | ":returns: None\n" | |||
| 888 | ":raises EnvironmentError: caused by any system errors\n" | |||
| 889 | "\n" | |||
| 890 | ".. versionadded:: 0.4\n" | |||
| 891 | NS_CHANGED_DOC".. versionchanged:: 0.5.1\n" " The namespace argument, if passed, cannot be None anymore; to\n" " explicitly specify an empty namespace, pass an empty\n" " string (byte string under Python 3)." | |||
| 892 | ; | |||
| 893 | ||||
| 894 | /* Wrapper for removexattr */ | |||
| 895 | static PyObject * | |||
| 896 | xattr_remove(PyObject *self, PyObject *args, PyObject *keywds) | |||
| 897 | { | |||
| 898 | PyObject *myarg, *res; | |||
| 899 | int nofollow = 0; | |||
| 900 | char *attrname = NULL((void*)0), *name_buf; | |||
| 901 | const char *ns = NULL((void*)0); | |||
| 902 | const char *full_name; | |||
| 903 | int nret; | |||
| 904 | target_t tgt; | |||
| 905 | static char *kwlist[] = {"item", "name", "nofollow", "namespace", NULL((void*)0)}; | |||
| 906 | ||||
| 907 | /* Parse the arguments */ | |||
| 908 | if (!PyArg_ParseTupleAndKeywords_PyArg_ParseTupleAndKeywords_SizeT(args, keywds, "Oet|iy", kwlist, | |||
| 909 | &myarg, NULL((void*)0), &attrname, &nofollow, &ns)) | |||
| 910 | return NULL((void*)0); | |||
| 911 | ||||
| 912 | if(convert_obj(myarg, &tgt, nofollow) < 0) { | |||
| 913 | res = NULL((void*)0); | |||
| 914 | goto free_arg; | |||
| 915 | } | |||
| 916 | ||||
| 917 | if(merge_ns(ns, attrname, &full_name, &name_buf) < 0) { | |||
| 918 | res = NULL((void*)0); | |||
| 919 | goto free_arg; | |||
| 920 | } | |||
| 921 | ||||
| 922 | /* Remove the attribute */ | |||
| 923 | nret = _remove_obj(&tgt, full_name); | |||
| 924 | ||||
| 925 | PyMem_Free(name_buf); | |||
| 926 | ||||
| 927 | free_tgt(&tgt); | |||
| 928 | ||||
| 929 | if(nret == -1) { | |||
| 930 | res = PyErr_SetFromErrno(PyExc_IOError); | |||
| 931 | goto free_arg; | |||
| 932 | } | |||
| 933 | ||||
| 934 | Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct)))); | |||
| 935 | res = Py_None(&_Py_NoneStruct); | |||
| 936 | ||||
| 937 | free_arg: | |||
| 938 | PyMem_Free(attrname); | |||
| 939 | ||||
| 940 | /* Return the result */ | |||
| 941 | return res; | |||
| 942 | } | |||
| 943 | ||||
| 944 | static char __pylistxattr_doc__[] = | |||
| 945 | "listxattr(item[, nofollow=False])\n" | |||
| 946 | "Return the list of attribute names for a file (deprecated).\n" | |||
| 947 | "\n" | |||
| 948 | ITEM_DOC":param item: a string representing a file-name, a file-like\n" " object, a file descriptor, or (in Python 3.6+) a path-like\n" " object; this represents the file on which to act\n" | |||
| 949 | NOFOLLOW_DOC":param nofollow: if true and if\n" " the file name given is a symbolic link, the\n" " function will operate on the symbolic link itself instead\n" " of its target; defaults to false\n" ":type nofollow: boolean, optional\n" | |||
| 950 | "\n" | |||
| 951 | ".. deprecated:: 0.4\n" | |||
| 952 | " this function has been deprecated by the :func:`list` function.\n" | |||
| 953 | ; | |||
| 954 | ||||
| 955 | /* Wrapper for listxattr */ | |||
| 956 | static PyObject * | |||
| 957 | pylistxattr(PyObject *self, PyObject *args) | |||
| 958 | { | |||
| 959 | char *buf = NULL((void*)0); | |||
| 960 | int nofollow = 0; | |||
| 961 | ssize_t nret; | |||
| 962 | size_t nalloc = 0; | |||
| 963 | PyObject *myarg; | |||
| 964 | PyObject *mylist; | |||
| 965 | Py_ssize_t nattrs; | |||
| 966 | char *s; | |||
| 967 | target_t tgt; | |||
| 968 | ||||
| 969 | /* Parse the arguments */ | |||
| 970 | if (!PyArg_ParseTuple_PyArg_ParseTuple_SizeT(args, "O|i", &myarg, &nofollow)) | |||
| 971 | return NULL((void*)0); | |||
| 972 | if(convert_obj(myarg, &tgt, nofollow) < 0) | |||
| 973 | return NULL((void*)0); | |||
| 974 | ||||
| 975 | nret = _generic_get(_list_obj, &tgt, NULL((void*)0), &buf, &nalloc, NULL((void*)0)); | |||
| 976 | if (nret == -1) { | |||
| 977 | mylist = NULL((void*)0); | |||
| 978 | goto free_buf; | |||
| 979 | } | |||
| 980 | ||||
| 981 | /* Compute the number of attributes in the list */ | |||
| 982 | for(s = buf, nattrs = 0; (s - buf) < nret; s += strlen(s) + 1) { | |||
| 983 | nattrs++; | |||
| 984 | } | |||
| 985 | ||||
| 986 | /* Create the list which will hold the result */ | |||
| 987 | mylist = PyList_New(nattrs); | |||
| 988 | if(mylist == NULL((void*)0)) { | |||
| 989 | goto free_buf; | |||
| 990 | } | |||
| 991 | ||||
| 992 | /* Create and insert the attributes as strings in the list */ | |||
| 993 | for(s = buf, nattrs = 0; s - buf < nret; s += strlen(s) + 1) { | |||
| 994 | PyObject *item = PyBytes_FromString(s); | |||
| 995 | if(item == NULL((void*)0)) { | |||
| 996 | Py_DECREF(mylist)_Py_DECREF(((PyObject*)(mylist))); | |||
| 997 | mylist = NULL((void*)0); | |||
| 998 | goto free_buf; | |||
| 999 | } | |||
| 1000 | PyList_SET_ITEM(mylist, nattrs, item)PyList_SetItem(mylist, nattrs, item); | |||
| 1001 | nattrs++; | |||
| 1002 | } | |||
| 1003 | ||||
| 1004 | free_buf: | |||
| 1005 | /* Free the buffer, now it is no longer needed */ | |||
| 1006 | PyMem_Free(buf); | |||
| 1007 | free_tgt(&tgt); | |||
| 1008 | ||||
| 1009 | /* Return the result */ | |||
| 1010 | return mylist; | |||
| 1011 | } | |||
| 1012 | ||||
| 1013 | static char __list_doc__[] = | |||
| 1014 | "list(item[, nofollow=False, namespace=None])\n" | |||
| 1015 | "Return the list of attribute names for a file.\n" | |||
| 1016 | "\n" | |||
| 1017 | "Example:\n" | |||
| 1018 | "\n" | |||
| 1019 | " >>> xattr.list('/path/to/file')\n" | |||
| 1020 | " ['user.test', 'user.comment', 'system.posix_acl_access']\n" | |||
| 1021 | " >>> xattr.list('/path/to/file', namespace=xattr.NS_USER)\n" | |||
| 1022 | " ['test', 'comment']\n" | |||
| 1023 | "\n" | |||
| 1024 | ITEM_DOC":param item: a string representing a file-name, a file-like\n" " object, a file descriptor, or (in Python 3.6+) a path-like\n" " object; this represents the file on which to act\n" | |||
| 1025 | NOFOLLOW_DOC":param nofollow: if true and if\n" " the file name given is a symbolic link, the\n" " function will operate on the symbolic link itself instead\n" " of its target; defaults to false\n" ":type nofollow: boolean, optional\n" | |||
| 1026 | NS_DOC":param namespace: if given, the attribute must not contain the\n" " namespace, but instead it will be taken from this parameter\n" ":type namespace: bytes\n" | |||
| 1027 | ":returns: the list of attributes; note that if a namespace \n" | |||
| 1028 | " argument was passed, it (and the separator) will be stripped\n" | |||
| 1029 | " from the names\n" | |||
| 1030 | " returned\n" | |||
| 1031 | ":rtype: list\n" | |||
| 1032 | ":raises EnvironmentError: caused by any system errors\n" | |||
| 1033 | "\n" | |||
| 1034 | ".. versionadded:: 0.4\n" | |||
| 1035 | NS_CHANGED_DOC".. versionchanged:: 0.5.1\n" " The namespace argument, if passed, cannot be None anymore; to\n" " explicitly specify an empty namespace, pass an empty\n" " string (byte string under Python 3)." | |||
| 1036 | ; | |||
| 1037 | ||||
| 1038 | /* Wrapper for listxattr */ | |||
| 1039 | static PyObject * | |||
| 1040 | xattr_list(PyObject *self, PyObject *args, PyObject *keywds) | |||
| 1041 | { | |||
| 1042 | char *buf = NULL((void*)0); | |||
| 1043 | int nofollow = 0; | |||
| 1044 | ssize_t nret; | |||
| 1045 | size_t nalloc = 0; | |||
| 1046 | PyObject *myarg; | |||
| 1047 | PyObject *res; | |||
| 1048 | const char *ns = NULL((void*)0); | |||
| 1049 | Py_ssize_t nattrs; | |||
| 1050 | char *s; | |||
| 1051 | target_t tgt; | |||
| 1052 | static char *kwlist[] = {"item", "nofollow", "namespace", NULL((void*)0)}; | |||
| 1053 | ||||
| 1054 | /* Parse the arguments */ | |||
| 1055 | if (!PyArg_ParseTupleAndKeywords_PyArg_ParseTupleAndKeywords_SizeT(args, keywds, "O|iy", kwlist, | |||
| 1056 | &myarg, &nofollow, &ns)) | |||
| 1057 | return NULL((void*)0); | |||
| 1058 | res = NULL((void*)0); | |||
| 1059 | if(convert_obj(myarg, &tgt, nofollow) < 0) { | |||
| 1060 | goto free_arg; | |||
| 1061 | } | |||
| 1062 | nret = _generic_get(_list_obj, &tgt, NULL((void*)0), &buf, &nalloc, NULL((void*)0)); | |||
| 1063 | if (nret == -1) { | |||
| 1064 | goto free_tgt; | |||
| 1065 | } | |||
| 1066 | ||||
| 1067 | /* Compute the number of attributes in the list */ | |||
| 1068 | for(s = buf, nattrs = 0; (s - buf) < nret; s += strlen(s) + 1) { | |||
| 1069 | if(matches_ns(ns, s) != NULL((void*)0)) | |||
| 1070 | nattrs++; | |||
| 1071 | } | |||
| 1072 | ||||
| 1073 | /* Create the list which will hold the result */ | |||
| 1074 | if((res = PyList_New(nattrs)) == NULL((void*)0)) { | |||
| 1075 | goto free_buf; | |||
| 1076 | } | |||
| 1077 | ||||
| 1078 | /* Create and insert the attributes as strings in the list */ | |||
| 1079 | for(s = buf, nattrs = 0; s - buf < nret; s += strlen(s) + 1) { | |||
| 1080 | const char *name = matches_ns(ns, s); | |||
| 1081 | if(name != NULL((void*)0)) { | |||
| 1082 | PyObject *item = PyBytes_FromString(name); | |||
| 1083 | if(item == NULL((void*)0)) { | |||
| 1084 | Py_DECREF(res)_Py_DECREF(((PyObject*)(res))); | |||
| 1085 | res = NULL((void*)0); | |||
| 1086 | goto free_buf; | |||
| 1087 | } | |||
| 1088 | PyList_SET_ITEM(res, nattrs, item)PyList_SetItem(res, nattrs, item); | |||
| 1089 | nattrs++; | |||
| 1090 | } | |||
| 1091 | } | |||
| 1092 | ||||
| 1093 | free_buf: | |||
| 1094 | /* Free the buffer, now it is no longer needed */ | |||
| 1095 | PyMem_Free(buf); | |||
| 1096 | ||||
| 1097 | free_tgt: | |||
| 1098 | free_tgt(&tgt); | |||
| 1099 | free_arg: | |||
| 1100 | ||||
| 1101 | /* Return the result */ | |||
| 1102 | return res; | |||
| 1103 | } | |||
| 1104 | ||||
| 1105 | static PyMethodDef xattr_methods[] = { | |||
| 1106 | {"getxattr", pygetxattr, METH_VARARGS0x0001, __pygetxattr_doc__ }, | |||
| 1107 | {"get", (PyCFunction) xattr_get, METH_VARARGS0x0001 | METH_KEYWORDS0x0002, | |||
| 1108 | __get_doc__ }, | |||
| 1109 | {"get_all", (PyCFunction) get_all, METH_VARARGS0x0001 | METH_KEYWORDS0x0002, | |||
| 1110 | __get_all_doc__ }, | |||
| 1111 | {"setxattr", pysetxattr, METH_VARARGS0x0001, __pysetxattr_doc__ }, | |||
| 1112 | {"set", (PyCFunction) xattr_set, METH_VARARGS0x0001 | METH_KEYWORDS0x0002, | |||
| 1113 | __set_doc__ }, | |||
| 1114 | {"removexattr", pyremovexattr, METH_VARARGS0x0001, __pyremovexattr_doc__ }, | |||
| 1115 | {"remove", (PyCFunction) xattr_remove, METH_VARARGS0x0001 | METH_KEYWORDS0x0002, | |||
| 1116 | __remove_doc__ }, | |||
| 1117 | {"listxattr", pylistxattr, METH_VARARGS0x0001, __pylistxattr_doc__ }, | |||
| 1118 | {"list", (PyCFunction) xattr_list, METH_VARARGS0x0001 | METH_KEYWORDS0x0002, | |||
| 1119 | __list_doc__ }, | |||
| 1120 | {NULL((void*)0), NULL((void*)0), 0, NULL((void*)0)} /* Sentinel */ | |||
| 1121 | }; | |||
| 1122 | ||||
| 1123 | static char __xattr_doc__[] = \ | |||
| 1124 | "This module gives access to the extended attributes present\n" | |||
| 1125 | "in some operating systems/filesystems. You can list attributes,\n" | |||
| 1126 | "get, set and remove them.\n" | |||
| 1127 | "\n" | |||
| 1128 | "The module exposes two sets of functions:\n" | |||
| 1129 | " - the 'old' :func:`listxattr`, :func:`getxattr`, :func:`setxattr`,\n" | |||
| 1130 | " :func:`removexattr`\n" | |||
| 1131 | " functions which are deprecated since version 0.4\n" | |||
| 1132 | " - the new :func:`list`, :func:`get`, :func:`get_all`, :func:`set`,\n" | |||
| 1133 | " :func:`remove` functions\n" | |||
| 1134 | " which expose a namespace-aware API and simplify a bit the calling\n" | |||
| 1135 | " model by using keyword arguments\n" | |||
| 1136 | "\n" | |||
| 1137 | "Example: \n\n" | |||
| 1138 | " >>> import xattr\n" | |||
| 1139 | " >>> xattr.listxattr(\"file.txt\")\n" | |||
| 1140 | " ['user.mime_type']\n" | |||
| 1141 | " >>> xattr.getxattr(\"file.txt\", \"user.mime_type\")\n" | |||
| 1142 | " 'text/plain'\n" | |||
| 1143 | " >>> xattr.setxattr(\"file.txt\", \"user.comment\", " | |||
| 1144 | "\"Simple text file\")\n" | |||
| 1145 | " >>> xattr.listxattr(\"file.txt\")\n" | |||
| 1146 | " ['user.mime_type', 'user.comment']\n" | |||
| 1147 | " >>> xattr.removexattr (\"file.txt\", \"user.comment\")\n" | |||
| 1148 | "\n" | |||
| 1149 | ".. note:: Most or all errors reported by the system while using\n" | |||
| 1150 | " the ``xattr`` library will be reported by raising\n" | |||
| 1151 | " a :exc:`EnvironmentError`; under\n" | |||
| 1152 | " Linux, the following ``errno`` values are used:\n" | |||
| 1153 | "\n" | |||
| 1154 | " - ``ENODATA`` means that the attribute name is invalid\n" | |||
| 1155 | " - ``ENOTSUP`` and ``EOPNOTSUPP`` mean that the filesystem does not\n" | |||
| 1156 | " support extended attributes, or that the namespace is invalid\n" | |||
| 1157 | " - ``E2BIG`` mean that the attribute value is too big\n" | |||
| 1158 | " - ``ERANGE`` mean that the attribute name is too big (it might also\n" | |||
| 1159 | " mean an error in the xattr module itself)\n" | |||
| 1160 | " - ``ENOSPC`` and ``EDQUOT`` are documented as meaning out of disk\n" | |||
| 1161 | " space or out of disk space because of quota limits\n" | |||
| 1162 | ".. note:: Under Python 3, the namespace argument is a byte string,\n" | |||
| 1163 | " not a unicode string.\n" | |||
| 1164 | "\n" | |||
| 1165 | ; | |||
| 1166 | ||||
| 1167 | static struct PyModuleDef xattrmodule = { | |||
| 1168 | PyModuleDef_HEAD_INIT{ { 1, ((void*)0) }, ((void*)0), 0, ((void*)0), }, | |||
| 1169 | "xattr", | |||
| 1170 | __xattr_doc__, | |||
| 1171 | 0, | |||
| 1172 | xattr_methods, | |||
| 1173 | }; | |||
| 1174 | ||||
| 1175 | #define INITERRORreturn ((void*)0) return NULL((void*)0) | |||
| 1176 | ||||
| 1177 | PyMODINIT_FUNCPyObject* | |||
| 1178 | PyInit_xattr(void) | |||
| 1179 | ||||
| 1180 | { | |||
| 1181 | PyObject *ns_security = NULL((void*)0); | |||
| 1182 | PyObject *ns_system = NULL((void*)0); | |||
| 1183 | PyObject *ns_trusted = NULL((void*)0); | |||
| 1184 | PyObject *ns_user = NULL((void*)0); | |||
| 1185 | PyObject *m = PyModule_Create(&xattrmodule)PyModule_Create2(&xattrmodule, 1013); | |||
| 1186 | if (m==NULL((void*)0)) | |||
| 1187 | return NULL((void*)0); | |||
| 1188 | ||||
| 1189 | PyModule_AddStringConstant(m, "__author__", _XATTR_AUTHOR"Iustin Pop"); | |||
| 1190 | PyModule_AddStringConstant(m, "__contact__", _XATTR_EMAIL"iustin@k1024.org"); | |||
| 1191 | PyModule_AddStringConstant(m, "__version__", _XATTR_VERSION"0.7.2"); | |||
| 1192 | PyModule_AddStringConstant(m, "__license__", | |||
| 1193 | "GNU Lesser General Public License (LGPL)"); | |||
| 1194 | PyModule_AddStringConstant(m, "__docformat__", "restructuredtext en"); | |||
| 1195 | ||||
| 1196 | PyModule_AddIntConstant(m, "XATTR_CREATE", XATTR_CREATEXATTR_CREATE); | |||
| 1197 | PyModule_AddIntConstant(m, "XATTR_REPLACE", XATTR_REPLACEXATTR_REPLACE); | |||
| 1198 | ||||
| 1199 | /* namespace constants */ | |||
| 1200 | if((ns_security = PyBytes_FromString("security")) == NULL((void*)0)) | |||
| 1201 | goto err_out; | |||
| 1202 | if((ns_system = PyBytes_FromString("system")) == NULL((void*)0)) | |||
| 1203 | goto err_out; | |||
| 1204 | if((ns_trusted = PyBytes_FromString("trusted")) == NULL((void*)0)) | |||
| 1205 | goto err_out; | |||
| 1206 | if((ns_user = PyBytes_FromString("user")) == NULL((void*)0)) | |||
| 1207 | goto err_out; | |||
| 1208 | if(PyModule_AddObject(m, "NS_SECURITY", ns_security) < 0) | |||
| 1209 | goto err_out; | |||
| 1210 | ns_security = NULL((void*)0); | |||
| 1211 | if(PyModule_AddObject(m, "NS_SYSTEM", ns_system) < 0) | |||
| 1212 | goto err_out; | |||
| 1213 | ns_system = NULL((void*)0); | |||
| 1214 | if(PyModule_AddObject(m, "NS_TRUSTED", ns_trusted) < 0) | |||
| 1215 | goto err_out; | |||
| 1216 | ns_trusted = NULL((void*)0); | |||
| 1217 | if(PyModule_AddObject(m, "NS_USER", ns_user) < 0) | |||
| 1218 | goto err_out; | |||
| 1219 | ns_user = NULL((void*)0); | |||
| 1220 | ||||
| 1221 | return m; | |||
| 1222 | ||||
| 1223 | err_out: | |||
| 1224 | Py_XDECREF(ns_user)_Py_XDECREF(((PyObject*)(ns_user))); | |||
| 1225 | Py_XDECREF(ns_trusted)_Py_XDECREF(((PyObject*)(ns_trusted))); | |||
| 1226 | Py_XDECREF(ns_system)_Py_XDECREF(((PyObject*)(ns_system))); | |||
| 1227 | Py_XDECREF(ns_security)_Py_XDECREF(((PyObject*)(ns_security))); | |||
| 1228 | INITERRORreturn ((void*)0); | |||
| 1229 | } |
| 1 | #ifndef _Py_BuildValue_SizeT |
| 2 | struct _object; |
| 3 | typedef struct _object PyObject; |
| 4 | PyObject* clang_analyzer_PyObject_New_Reference(); |
| 5 | PyObject* _Py_BuildValue_SizeT(const char *format, ...) { |
| 6 | return clang_analyzer_PyObject_New_Reference(); |
| 7 | } |
| 8 | #else |
| 9 | #warning "API _Py_BuildValue_SizeT is defined as a macro." |
| 10 | #endif |