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.
		
		
		
		
		
			
		
			
				
					
					
						
							46 lines
						
					
					
						
							1.7 KiB
						
					
					
				
			
		
		
	
	
							46 lines
						
					
					
						
							1.7 KiB
						
					
					
				| import os
 | |
| from cffi import FFI
 | |
| from typing import Any, List
 | |
| 
 | |
| # Workaround for the EON/termux build of Python having os.*xattr removed.
 | |
| ffi = FFI()
 | |
| ffi.cdef("""
 | |
| int setxattr(const char *path, const char *name, const void *value, size_t size, int flags);
 | |
| ssize_t getxattr(const char *path, const char *name, void *value, size_t size);
 | |
| ssize_t listxattr(const char *path, char *list, size_t size);
 | |
| int removexattr(const char *path, const char *name);
 | |
| """)
 | |
| libc = ffi.dlopen(None)
 | |
| 
 | |
| def setxattr(path, name, value, flags=0) -> None:
 | |
|   path = path.encode()
 | |
|   name = name.encode()
 | |
|   if libc.setxattr(path, name, value, len(value), flags) == -1:
 | |
|     raise OSError(ffi.errno, f"{os.strerror(ffi.errno)}: setxattr({path}, {name}, {value}, {flags})")
 | |
| 
 | |
| def getxattr(path, name, size=128):
 | |
|   path = path.encode()
 | |
|   name = name.encode()
 | |
|   value = ffi.new(f"char[{size}]")
 | |
|   l = libc.getxattr(path, name, value, size)
 | |
|   if l == -1:
 | |
|     # errno 61 means attribute hasn't been set
 | |
|     if ffi.errno == 61:
 | |
|       return None
 | |
|     raise OSError(ffi.errno, f"{os.strerror(ffi.errno)}: getxattr({path}, {name}, {size})")
 | |
|   return ffi.buffer(value)[:l]
 | |
| 
 | |
| def listxattr(path, size=128) -> List[Any]:
 | |
|   path = path.encode()
 | |
|   attrs = ffi.new(f"char[{size}]")
 | |
|   l = libc.listxattr(path, attrs, size)
 | |
|   if l == -1:
 | |
|     raise OSError(ffi.errno, f"{os.strerror(ffi.errno)}: listxattr({path}, {size})")
 | |
|   # attrs is b'\0' delimited values (so chop off trailing empty item)
 | |
|   return [a.decode() for a in ffi.buffer(attrs)[:l].split(b"\0")[0:-1]]
 | |
| 
 | |
| def removexattr(path, name) -> None:
 | |
|   path = path.encode()
 | |
|   name = name.encode()
 | |
|   if libc.removexattr(path, name) == -1:
 | |
|     raise OSError(ffi.errno, f"{os.strerror(ffi.errno)}: removexattr({path}, {name})")
 | |
| 
 |