1#include "EXTERN.h" 2#include "perl.h" 3#include "XSUB.h" 4 5#include "ppport.h" 6#include "portable.h" 7 8 9#define MAX_INITIAL_VALUELEN_VARNAME "File::ExtAttr::MAX_INITIAL_VALUELEN" 10 /* Richard, fixme! */ 11 12 13MODULE = File::ExtAttr PACKAGE = File::ExtAttr 14 15PROTOTYPES: ENABLE 16 17 18int 19_setfattr (path, attrname, attrvalueSV, flags = 0) 20 const char *path 21 const char *attrname 22 SV * attrvalueSV 23 HV * flags 24 PREINIT: 25 STRLEN slen; 26 char * attrvalue; 27 int rc; 28 29 CODE: 30 attrvalue = SvPV(attrvalueSV, slen); 31 rc = portable_setxattr(path, attrname, attrvalue, slen, flags); 32 if (rc < 0) 33 errno = -rc; 34 RETVAL = (rc == 0); 35 36 OUTPUT: 37 RETVAL 38 39 40int 41_fsetfattr (fd, attrname, attrvalueSV, flags = 0) 42 int fd 43 const char *attrname 44 SV * attrvalueSV 45 HV * flags 46 PREINIT: 47 STRLEN slen; 48 char * attrvalue; 49 int rc; 50 51 CODE: 52 attrvalue = SvPV(attrvalueSV, slen); 53 rc = portable_fsetxattr(fd, attrname, attrvalue, slen, flags); 54 if (rc < 0) 55 errno = -rc; 56 RETVAL = (rc == 0); 57 58 OUTPUT: 59 RETVAL 60 61 62SV * 63_getfattr(path, attrname, flags = 0) 64 const char *path 65 const char *attrname 66 HV * flags 67 PREINIT: 68 char * attrvalue; 69 int attrlen; 70 ssize_t buflen; 71 72 CODE: 73 buflen = portable_lenxattr(path, attrname, flags); 74 if (buflen <= 0) 75 buflen = SvIV(get_sv(MAX_INITIAL_VALUELEN_VARNAME, FALSE)); 76 77 attrvalue = NULL; 78 Newz(1, attrvalue, buflen, char); 79 80 attrlen = portable_getxattr(path, attrname, attrvalue, buflen, flags); 81 if (attrlen < 0){ 82 83 //key not found, just return undef 84 if(errno == ENOATTR){ 85 Safefree(attrvalue); 86 errno = -attrlen; 87 XSRETURN_UNDEF; 88 89 //return undef 90 }else{ 91 Safefree(attrvalue); 92 errno = -attrlen; 93 XSRETURN_UNDEF; 94 } 95 } 96 97 RETVAL = newSVpv(attrvalue, attrlen); 98 Safefree(attrvalue); 99 100 OUTPUT: 101 RETVAL 102 103 104SV * 105_fgetfattr(fd, attrname, flags = 0) 106 int fd 107 const char *attrname 108 HV * flags 109 PREINIT: 110 char * attrvalue; 111 int attrlen; 112 ssize_t buflen; 113 114 CODE: 115 buflen = portable_flenxattr(fd, attrname, flags); 116 if (buflen <= 0) 117 buflen = SvIV(get_sv(MAX_INITIAL_VALUELEN_VARNAME, FALSE)); 118 119 attrvalue = NULL; 120 Newz(1, attrvalue, buflen, char); 121 122 attrlen = portable_fgetxattr(fd, attrname, attrvalue, buflen, flags); 123 if (attrlen < 0){ 124 125 //key not found, just return undef 126 if(errno == ENOATTR){ 127 Safefree(attrvalue); 128 errno = -attrlen; 129 XSRETURN_UNDEF; 130 131 //return undef 132 }else{ 133 Safefree(attrvalue); 134 errno = -attrlen; 135 XSRETURN_UNDEF; 136 } 137 } 138 139 RETVAL = newSVpv(attrvalue, attrlen); 140 Safefree(attrvalue); 141 142 OUTPUT: 143 RETVAL 144 145 146int 147_delfattr (path, attrname, flags = 0) 148 const char *path 149 const char *attrname 150 HV * flags 151 PREINIT: 152 int rc; 153 154 CODE: 155 rc = portable_removexattr(path, attrname, flags); 156 if (rc < 0) 157 errno = -rc; 158 RETVAL = (rc == 0); 159 160 OUTPUT: 161 RETVAL 162 163 164int 165_fdelfattr (fd, attrname, flags = 0) 166 int fd 167 const char *attrname 168 HV * flags 169 PREINIT: 170 int rc; 171 172 CODE: 173 rc = portable_fremovexattr(fd, attrname, flags); 174 if (rc < 0) 175 errno = -rc; 176 RETVAL = (rc == 0); 177 178 OUTPUT: 179 RETVAL 180 181void 182_listfattr (path, fd, flags = 0) 183 const char *path 184 int fd 185 HV * flags 186 PREINIT: 187 ssize_t size, ret; 188 char *namebuf = NULL; 189 char *nameptr; 190 191 PPCODE: 192 if(fd == -1) 193 size = portable_listxattr(path, NULL, 0, flags); 194 else 195 size = portable_flistxattr(fd, NULL, 0, flags); 196 197 if (size < 0) 198 { 199 errno = -(int) size; 200 XSRETURN_UNDEF; 201 } else if (size == 0) 202 { 203 XSRETURN_EMPTY; 204 } 205 206 namebuf = malloc(size); 207 208 if (fd == -1) 209 ret = portable_listxattr(path, namebuf, size, flags); 210 else 211 ret = portable_flistxattr(fd, namebuf, size, flags); 212 213 // There could be a race condition here, if someone adds a new 214 // attribute between the two listxattr calls. However it just means we 215 // might return ERANGE. 216 217 if (ret < 0) 218 { 219 free(namebuf); 220 errno = -ret; 221 XSRETURN_UNDEF; 222 } else if (ret == 0) 223 { 224 free(namebuf); 225 XSRETURN_EMPTY; 226 } 227 228 nameptr = namebuf; 229 230 while(nameptr < namebuf + ret) 231 { 232 char *endptr = nameptr; 233 while(*endptr++ != '\0'); 234 235 // endptr will now point one past the end.. 236 237 XPUSHs(sv_2mortal(newSVpvn(nameptr, endptr - nameptr - 1))); 238 239 // nameptr could now point past the end of namebuf 240 nameptr = endptr; 241 } 242 243 free(namebuf); 244 245void 246_listfattrns (path, fd, flags = 0) 247 const char *path 248 int fd 249 HV * flags 250 PREINIT: 251 ssize_t size, ret; 252 char *namebuf = NULL; 253 char *nameptr; 254 255 PPCODE: 256 if(fd == -1) 257 size = portable_listxattrns(path, NULL, 0, flags); 258 else 259 size = portable_flistxattrns(fd, NULL, 0, flags); 260 261 if (size < 0) 262 { 263 errno = -(int) size; 264 XSRETURN_UNDEF; 265 } else if (size == 0) 266 { 267 XSRETURN_EMPTY; 268 } 269 270 namebuf = malloc(size); 271 272 if (fd == -1) 273 ret = portable_listxattrns(path, namebuf, size, flags); 274 else 275 ret = portable_flistxattrns(fd, namebuf, size, flags); 276 277 // There could be a race condition here, if someone adds a new 278 // attribute between the two listxattr calls. However it just means we 279 // might return ERANGE. 280 281 if (ret < 0) 282 { 283 free(namebuf); 284 errno = -ret; 285 XSRETURN_UNDEF; 286 } else if (ret == 0) 287 { 288 free(namebuf); 289 XSRETURN_EMPTY; 290 } 291 292 nameptr = namebuf; 293 294 while(nameptr < namebuf + ret) 295 { 296 char *endptr = nameptr; 297 while(*endptr++ != '\0'); 298 299 // endptr will now point one past the end.. 300 301 XPUSHs(sv_2mortal(newSVpvn(nameptr, endptr - nameptr - 1))); 302 303 // nameptr could now point past the end of namebuf 304 nameptr = endptr; 305 } 306 307 free(namebuf); 308