/* * attr.c * * Copyright (C) 2006 Alex deVries * */ #include #include #include "afpfs-ng/dsi.h" #include "afpfs-ng/afp.h" #include "afpfs-ng/utils.h" #include "afpfs-ng/afp_protocol.h" #include "dsi_protocol.h" /* This is a new command, function 76. There are currently no docs, so this * can be nothing but a rough implementation. It is possible to create * some sort of reverse-engineered parser for the return. */ int afp_newcommand76(struct afp_volume * volume, unsigned int dlen, char * data) { struct { struct dsi_header dsi_header __attribute__((__packed__)); uint8_t command; uint8_t pad; uint16_t volid ; } __attribute__((__packed__)) *request_packet; struct afp_server * server=volume->server; unsigned int len = sizeof(*request_packet)+dlen; int ret; char * msg = malloc(len); if (!msg) { log_for_client(NULL,AFPFSD,LOG_WARNING,"Out of memory\n"); return -1; }; request_packet=(void *) msg; dsi_setup_header(server,&request_packet->dsi_header,DSI_DSICommand); request_packet->command=76; request_packet->pad=0; request_packet->volid=htons(volume->volid); char * p=msg+sizeof(*request_packet); memcpy(p, data,dlen); ret=dsi_send(server, msg, len,DSI_DEFAULT_TIMEOUT, 76 , NULL); free(msg); return ret; } int afp_listextattr(struct afp_volume * volume, unsigned int dirid, unsigned short bitmap, char * pathname, struct afp_extattr_info * info) { struct { struct dsi_header dsi_header __attribute__((__packed__)); uint8_t command; uint8_t pad; uint16_t volid ; uint32_t dirid ; uint16_t bitmap; uint16_t reqcount; uint32_t startindex; uint32_t maxreplysize; } __attribute__((__packed__)) *request_packet; struct afp_server * server=volume->server; unsigned int len = sizeof(*request_packet)+sizeof_path_header(server)+strlen(pathname); char * pathptr; int ret; char * msg = malloc(len); if (!msg) { log_for_client(NULL,AFPFSD,LOG_WARNING,"Out of memory\n"); return -1; }; pathptr = msg + (sizeof(*request_packet)); request_packet=(void *) msg; dsi_setup_header(server,&request_packet->dsi_header,DSI_DSICommand); request_packet->command=afpListExtAttrs; request_packet->pad=0; request_packet->volid=htons(volume->volid); request_packet->dirid=htonl(dirid); request_packet->reqcount=0; request_packet->startindex=0; request_packet->bitmap=htons(bitmap); request_packet->maxreplysize=hton64(info->maxsize); copy_path(server,pathptr,pathname,strlen(pathname)); unixpath_to_afppath(server,pathptr); ret=dsi_send(server, (char *) request_packet,len,DSI_DEFAULT_TIMEOUT, afpListExtAttrs , (void *) info); free(msg); return ret; } int afp_listextattrs_reply(struct afp_server * server, char * buf, unsigned int size, void * x) { struct { struct dsi_header header __attribute__((__packed__)); uint16_t reserved ; uint32_t datalength ; char * data ; } __attribute__((__packed__)) * reply = (void *) buf; struct afp_extattr_info * i = x; unsigned int len = min(i->maxsize,ntohl(reply->datalength)); i->size=len; /* Todo: make sure we don't go past the end of the buffer */ memcpy(&i->data,&reply->data,len) ; return 0; } int afp_getextattr(struct afp_volume * volume, unsigned int dirid, unsigned short bitmap, unsigned int replysize , char * pathname, unsigned short namelen, char * name, struct afp_extattr_info * i) { struct { struct dsi_header dsi_header __attribute__((__packed__)); uint8_t command; char pad; uint16_t volid ; uint32_t dirid ; uint16_t bitmap ; uint64_t offset ; uint64_t reqcount; uint32_t replysize; } __attribute__((__packed__)) *request_packet; struct { uint16_t len; char * name ; } __attribute__((__packed__)) * req2; struct afp_server * server = volume->server; unsigned int len = sizeof(*request_packet)+ sizeof_path_header(server)+strlen(pathname) +1+sizeof(unsigned int) + strlen(name); char * p,*p2; int ret; char * msg = malloc(len); if (!msg) { log_for_client(NULL,AFPFSD,LOG_WARNING,"Out of memory\n"); return -1; }; p= msg + (sizeof(*request_packet)); request_packet=(void *) msg; dsi_setup_header(server,&request_packet->dsi_header,DSI_DSICommand); request_packet->command=afpGetExtAttr; request_packet->pad=0; request_packet->volid=htons(volume->volid); request_packet->dirid=htonl(dirid); request_packet->offset=hton64(0); request_packet->reqcount=hton64(0); request_packet->replysize=htonl(replysize); copy_path(server,p,pathname,strlen(pathname)); unixpath_to_afppath(server,p); p2=p+sizeof_path_header(server)+strlen(pathname); if (((unsigned long) p2) & 0x1) p2++; req2=(void *) p2; req2->len=htons(namelen); memcpy(&req2->name,name,namelen); len=(p2+namelen)-msg; ret=dsi_send(server, (char *) request_packet,len,DSI_DEFAULT_TIMEOUT, afpDelete ,(void *) i); free(msg); return ret; } int afp_setextattr(struct afp_volume * volume, unsigned int dirid, unsigned short bitmap, uint64_t offset, char * pathname, unsigned short namelen, char * name, unsigned int attribdatalen, char * attribdata) { struct { struct dsi_header dsi_header __attribute__((__packed__)); uint8_t command; uint8_t pad; uint16_t volid ; uint32_t dirid ; uint16_t bitmap ; uint64_t offset ; } __attribute__((__packed__)) *request_packet; struct afp_server * server = volume->server; unsigned int len = sizeof(*request_packet)+sizeof_path_header(server)+strlen(pathname); char * pathptr; int ret; char * msg = malloc(len); if (!msg) { log_for_client(NULL,AFPFSD,LOG_WARNING,"Out of memory\n"); return -1; }; pathptr = msg + (sizeof(*request_packet)); request_packet=(void *) msg; dsi_setup_header(server,&request_packet->dsi_header,DSI_DSICommand); request_packet->command=afpSetExtAttr; request_packet->pad=0; request_packet->volid=htons(volume->volid); request_packet->dirid=htonl(dirid); copy_path(server,pathptr,pathname,strlen(pathname)); unixpath_to_afppath(server,pathptr); ret=dsi_send(server, (char *) request_packet,len,DSI_DEFAULT_TIMEOUT, afpDelete ,NULL); free(msg); return ret; }