static int do_write(struct asfd *asfd, BFILE *bfd, uint8_t *out, size_t outlen, char **metadata, uint64_t *sent) { int ret=0; if(metadata) { // Append it to our metadata. out[outlen]='\0'; //printf("\nadd outlen: %lu\n", outlen); if(!(*metadata=prepend_len(*metadata, *sent, (const char *)out, outlen, "", 0, (size_t *)sent))) { logp("error when appending metadata\n"); asfd->write_str(asfd, CMD_ERROR, "error when appending metadata"); return -1; } } else { if((ret=bfd->write(bfd, out, outlen))<=0) { logp("error when appending %d: %d\n", outlen, ret); asfd->write_str(asfd, CMD_ERROR, "write failed"); return -1; } *sent+=outlen; } return 0; }
static int get_acl_string(struct asfd *asfd, acl_t acl, char **acltext, size_t *alen, const char *path, char type, struct cntr *cntr) { int ret=0; char pre[10]=""; char *tmp=NULL; ssize_t tlen=0; char *ourtext=NULL; ssize_t maxlen=0xFFFFFFFF/2; if(!(tmp=acl_to_text(acl, NULL))) { logw(asfd, cntr, "could not get ACL text of '%s'\n", path); goto end; // carry on } tlen=strlen(tmp); if(tlen>maxlen) { logw(asfd, cntr, "ACL of '%s' too long: %d\n", path, tlen); goto end; // carry on } snprintf(pre, sizeof(pre), "%c%08X", type, (unsigned int)tlen); if(!(ourtext=prepend(pre, tmp)) || !(*acltext=prepend_len(*acltext, *alen, ourtext, tlen+9, "", 0, alen))) ret=-1; end: free_w(&tmp); free_w(&ourtext); return ret; }
static int do_write(BFILE *bfd, FILE *fp, unsigned char *out, size_t outlen, char **metadata, unsigned long long *sent) { int ret=0; if(metadata) { // Append it to our metadata. out[outlen]='\0'; //printf("\nadd outlen: %lu\n", outlen); if(!(*metadata=prepend_len(*metadata, *sent, (const char *)out, outlen, "", 0, (size_t *)sent))) { logp("error when appending metadata\n"); async_write_str(CMD_ERROR, "error when appending metadata"); return -1; } } else { #ifdef HAVE_WIN32 if((ret=bwrite(bfd, out, outlen))<=0) { logp("error when appending: %d\n", ret); async_write_str(CMD_ERROR, "write failed"); return -1; } #else if((fp && (ret=fwrite(out, 1, outlen, fp))<=0)) { logp("error when appending: %d\n", ret); async_write_str(CMD_ERROR, "write failed"); return -1; } #endif *sent+=outlen; } return 0; }
char *prepend(const char *prep, const char *fname, size_t len, const char *sep) { return prepend_len(prep, prep?strlen(prep):0, fname, len, sep, (sep && *fname)?strlen(sep):0, NULL); }
int get_xattr(struct asfd *asfd, const char *path, struct stat *statp, char **xattrtext, size_t *xlen, struct conf *conf) { char *z=NULL; size_t len=0; int have_acl=0; char *toappend=NULL; char *xattrlist=NULL; size_t totallen=0; size_t maxlen=0xFFFFFFFF/2; if((len=llistxattr(path, NULL, 0))<=0) { logw(asfd, conf, "could not llistxattr '%s': %d\n", path, len); return 0; // carry on } if(!(xattrlist=(char *)malloc(len+1))) { log_out_of_memory(__func__); return -1; } memset(xattrlist, 0, len+1); if((len=llistxattr(path, xattrlist, len))<=0) { logw(asfd, conf, "could not llistxattr '%s': %d\n", path, len); free_w(&xattrlist); return 0; // carry on } xattrlist[len]='\0'; if(xattrtext && *xattrtext) { // Already have some meta text, which means that some // ACLs were set. have_acl++; } z=xattrlist; for(z=xattrlist; len > (size_t)(z-xattrlist)+1; z=strchr(z, '\0')+1) { char tmp1[9]; char tmp2[9]; char *val=NULL; size_t vlen=0; size_t zlen=0; if((zlen=strlen(z))>maxlen) { logw(asfd, conf, "xattr element of '%s' too long: %d\n", path, zlen); free_w(&toappend); break; } if(have_acl) { int c=0; int skip=0; // skip xattr entries that were already saved as ACLs. for(c=0; xattr_acl_skiplist[c]; c++) { if(!strcmp(z, xattr_acl_skiplist[c])) { skip++; break; } } if(skip) continue; } if((vlen=lgetxattr(path, z, NULL, 0))<=0) { logw(asfd, conf, "could not lgetxattr on %s for %s: %d\n", path, z, vlen); continue; } if(!(val=(char *)malloc(vlen+1))) { log_out_of_memory(__func__); free_w(&xattrlist); free_w(&toappend); return -1; } if((vlen=lgetxattr(path, z, val, vlen))<=0) { logw(asfd, conf, "could not lgetxattr %s for %s: %d\n", path, z, vlen); free_w(&val); continue; } val[vlen]='\0'; if(vlen>maxlen) { logw(asfd, conf, "xattr value of '%s' too long: %d\n", path, vlen); free_w(&toappend); free_w(&val); break; } snprintf(tmp1, sizeof(tmp1), "%08X", (unsigned int)zlen); snprintf(tmp2, sizeof(tmp2), "%08X", (unsigned int)vlen); if(!(toappend=prepend_len(toappend, totallen, tmp1, 8, "", 0, &totallen)) || !(toappend=prepend_len(toappend, totallen, z, zlen, "", 0, &totallen)) || !(toappend=prepend_len(toappend, totallen, tmp2, 8, "", 0, &totallen)) || !(toappend=prepend_len(toappend, totallen, val, vlen, "", 0, &totallen))) { log_out_of_memory(__func__); free_w(&val); free_w(&xattrlist); return -1; } free_w(&val); if(totallen>maxlen) { logw(asfd, conf, "xattr length of '%s' grew too long: %d\n", path, totallen); free_w(&val); free_w(&toappend); free_w(&xattrlist); return 0; // carry on } } if(toappend) { char tmp3[10]; snprintf(tmp3, sizeof(tmp3), "%c%08X", META_XATTR, (unsigned int)totallen); if(!(*xattrtext=prepend_len(*xattrtext, *xlen, tmp3, 9, "", 0, xlen)) || !(*xattrtext=prepend_len(*xattrtext, *xlen, toappend, totallen, "", 0, xlen))) { log_out_of_memory(__func__); free_w(&toappend); free_w(&xattrlist); return -1; } free_w(&toappend); } free_w(&xattrlist); return 0; }
int get_xattr(const char *path, struct stat *statp, char **xattrtext, size_t *xlen, struct conf *conf) { int i=0; size_t maxlen=0xFFFFFFFF/2; for(i=0; i<(int)(sizeof(namespaces)/sizeof(int)); i++) { int j=0; size_t len=0; int have_acl=0; char *xattrlist=NULL; char *cnamespace=NULL; size_t totallen=0; char *toappend=NULL; char ctuple[BSD_BUF_SIZE]=""; char cattrname[BSD_BUF_SIZE]=""; if((len=extattr_list_link(path, namespaces[i], NULL, 0))<0) { logw(conf, "could not extattr_list_link of '%s': %d\n", path, len); return 0; // carry on } if(!len) continue; if(xattrtext && *xattrtext) { // Already have some meta text, which means that some // ACLs were set. have_acl++; } if(!(xattrlist=(char *)malloc(len+1))) { log_out_of_memory(__func__); return -1; } memset(xattrlist, 0, len+1); if((len=extattr_list_link(path, namespaces[i], xattrlist, len))<=0) { logw(conf, "could not extattr_list_link '%s': %d\n", path, len); free(xattrlist); return 0; // carry on } xattrlist[len]='\0'; // Convert namespace number to string. It has to be freed // later on. if(extattr_namespace_to_string(namespaces[i], &cnamespace)) { logp("Failed to convert %d into namespace on '%s'\n", namespaces[i], path); free(xattrlist); return 0; // carry on } for(j=0; j<(int)len; j+=xattrlist[j]+1) { int cnt=0; char tmp1[9]; char tmp2[9]; size_t zlen=0; size_t vlen=0; char *val=NULL; cnt=xattrlist[j]; if(cnt>((int)sizeof(cattrname)-1)) cnt=((int)sizeof(cattrname)-1); strncpy(cattrname, xattrlist+(j+1), cnt); cattrname[cnt]='\0'; snprintf(ctuple, sizeof(ctuple), "%s.%s", cnamespace, cattrname); if(have_acl) { int c=0; int skip=0; // skip xattr entries that were already saved // as ACLs. for(c=0; acl_skiplist[c]; c++) { if(!strcmp(ctuple, acl_skiplist[c])) { skip++; break; } } if(skip) continue; } zlen=strlen(ctuple); //printf("\ngot: %s (%s)\n", ctuple, path); if((vlen=extattr_list_link(path, namespaces[i], xattrlist, len))<0) { logw(conf, "could not extattr_list_link on %s for %s: %d\n", path, namespaces[i], vlen); continue; } if(!(val=(char *)malloc(vlen+1))) { log_out_of_memory(__func__); free(xattrlist); if(toappend) free(toappend); return -1; } if((vlen=extattr_get_link(path, namespaces[i], cattrname, val, vlen))<0) { logw(conf, "could not extattr_list_link %s for %s: %d\n", path, namespaces[i], vlen); free(val); continue; } val[vlen]='\0'; if(vlen>maxlen) { logw(conf, "xattr value of '%s' too long: %d\n", path, vlen); if(toappend) { free(toappend); toappend=NULL; } free(val); break; } snprintf(tmp1, sizeof(tmp1), "%08X", (unsigned)zlen); snprintf(tmp2, sizeof(tmp2), "%08X", (unsigned)vlen); if(!(toappend=prepend_len(toappend, totallen, tmp1, 8, "", 0, &totallen)) || !(toappend=prepend_len(toappend, totallen, ctuple, zlen, "", 0, &totallen)) || !(toappend=prepend_len(toappend, totallen, tmp2, 8, "", 0, &totallen)) || !(toappend=prepend_len(toappend, totallen, val, vlen, "", 0, &totallen))) { log_out_of_memory(__func__); free(val); free(xattrlist); return -1; } free(val); if(totallen>maxlen) { logw(conf, "xattr length of '%s' grew too long: %d\n", path, totallen); free(val); free(toappend); free(xattrlist); return 0; // carry on } //printf("now: %s\n", toappend); } free(cnamespace); if(toappend) { char tmp3[10]; snprintf(tmp3, sizeof(tmp3), "%c%08X", META_XATTR_BSD, (unsigned)totallen); if(!(*xattrtext=prepend_len(*xattrtext, *xlen, tmp3, 9, "", 0, xlen)) || !(*xattrtext=prepend_len(*xattrtext, *xlen, toappend, totallen, "", 0, xlen))) { log_out_of_memory(__func__); free(toappend); free(xattrlist); return -1; } free(toappend); //printf("and: %s %li\n", *xattrtext, *xlen); } free(xattrlist); } return 0; }