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 int ) 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_byterangelockext(struct afp_volume * volume, unsigned char flag, unsigned short forkid, uint64_t offset, uint64_t len, uint64_t *generated_offset) { struct { struct dsi_header dsi_header __attribute__((__packed__)); uint8_t command; uint8_t flag; uint16_t forkid; uint64_t offset; uint64_t len; } __attribute__((__packed__)) request; int rc; dsi_setup_header(volume->server,&request.dsi_header,DSI_DSICommand); request.command=afpByteRangeLockExt; request.flag=flag; request.forkid=htons(forkid); request.offset=hton64(offset); request.len=hton64(len); rc=dsi_send(volume->server, (char *) &request, sizeof(request),DSI_DEFAULT_TIMEOUT, afpByteRangeLockExt,(void *) generated_offset); return rc; }
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_enumerate( struct afp_volume * volume, unsigned int dirid, unsigned int filebitmap, unsigned int dirbitmap, unsigned short reqcount, unsigned short startindex, char * pathname, struct afp_file_info ** file_p) { struct { struct dsi_header dsi_header __attribute__((__packed__)); uint8_t command; uint8_t pad; uint16_t volid; uint32_t dirid; uint16_t filebitmap; uint16_t dirbitmap; uint16_t reqcount; uint16_t startindex; uint16_t maxreplysize; } __attribute__((__packed__)) * afp_enumerate_request_packet; unsigned short len; char * data; int rc; struct afp_file_info * files = NULL; struct afp_server * server = volume->server; char * path; len = sizeof_path_header(server) + strlen(pathname) + sizeof(*afp_enumerate_request_packet); if ((data=malloc(len))==NULL) return -1; path = data+sizeof(*afp_enumerate_request_packet); afp_enumerate_request_packet = (void *) data; dsi_setup_header(server,&afp_enumerate_request_packet->dsi_header,DSI_DSICommand); afp_enumerate_request_packet->command=afpEnumerate; afp_enumerate_request_packet->pad=0; afp_enumerate_request_packet->volid=htons(volume->volid); afp_enumerate_request_packet->dirid=htonl(dirid); afp_enumerate_request_packet->filebitmap=htons(filebitmap); afp_enumerate_request_packet->dirbitmap=htons(dirbitmap); afp_enumerate_request_packet->reqcount=htons(reqcount); afp_enumerate_request_packet->startindex=htons(startindex); afp_enumerate_request_packet->maxreplysize=htons(5280); copy_path(server,path,pathname,strlen(pathname)); unixpath_to_afppath(server,path); rc=dsi_send(server, (char *) data,len,DSI_DEFAULT_TIMEOUT, afpEnumerate,(void **) &files); *file_p = files; free(data); return rc; }
int dsi_sendtickle(struct afp_server *server) { struct dsi_header header; dsi_setup_header(server,&header,DSI_DSITickle); dsi_send(server,(char *) &header,sizeof(struct dsi_header),1, DSI_DONT_WAIT,NULL); return 0; }
void dsi_incoming_tickle(struct afp_server * server) { struct dsi_header header; dsi_setup_header(server,&header,DSI_DSITickle); dsi_send(server,(char *) &header,sizeof(struct dsi_header),0, DSI_DONT_WAIT,NULL); }
int afp_volclose(struct afp_volume * volume) { struct { struct dsi_header dsi_header __attribute__((__packed__)); uint8_t command; uint8_t pad; uint16_t volid; } __attribute__((__packed__)) request; dsi_setup_header(volume->server,&request.dsi_header,DSI_DSICommand); request.command=afpCloseVol; request.pad=0; request.volid=htons(volume->volid); return dsi_send(volume->server, (char *) &request,sizeof(request), DSI_DEFAULT_TIMEOUT,afpCloseVol,NULL); }
int afp_volopen(struct afp_volume * volume, unsigned short bitmap, char * password) { struct { struct dsi_header dsi_header __attribute__((__packed__)); uint8_t command; uint8_t pad; uint16_t bitmap; } __attribute__((__packed__)) * afp_volopen_request; char * msg, *volname, * password_ptr; unsigned int len = sizeof(*afp_volopen_request) + strlen(volume->volume_name)+1; unsigned char len2; int ret; if (password) { len+=AFP_VOLPASS_LEN; /* This is undocumented, but put it on an even boundary. This is how netatalk works. */ if (len & 0x1) len++; } if ((msg=malloc(len))==NULL) return -1; afp_volopen_request = (void *) msg; dsi_setup_header(volume->server,&afp_volopen_request->dsi_header,DSI_DSICommand); afp_volopen_request->command=afpOpenVol; afp_volopen_request->pad=0; afp_volopen_request->bitmap=htons(bitmap); volname = msg + sizeof(*afp_volopen_request); copy_to_pascal(volname,volume->volume_name); if (password) { password_ptr=msg+len-AFP_VOLPASS_LEN; len2=strlen(password); if (len2>AFP_VOLPASS_LEN) len2=AFP_VOLPASS_LEN; memset(password_ptr,0,AFP_VOLPASS_LEN); memcpy(password_ptr,password,len2); } ret=dsi_send_sys(volume->server, (char *) msg,len, DSI_DEFAULT_TIMEOUT,afpOpenVol,(void *) &volume); free(msg); return ret; }
int dsi_getstatus(struct afp_server * server) { #define GETSTATUS_BUF_SIZE 1024 struct dsi_header header; struct afp_rx_buffer rx; int ret; rx.data=malloc(GETSTATUS_BUF_SIZE); rx.maxsize=GETSTATUS_BUF_SIZE; rx.size=0; dsi_setup_header(server,&header,DSI_DSIGetStatus); /* We're intentionally ignoring the results */ ret=dsi_send(server,(char *) &header,sizeof(struct dsi_header),20, 0,(void *) &rx); free(rx.data); return ret; }
int afp_rename(struct afp_volume *volume, unsigned int dirid, char * path_from, char * path_to) { struct { struct dsi_header dsi_header __attribute__((__packed__)); uint8_t command; uint8_t pad; uint16_t volid; uint32_t dirid; } __attribute__((__packed__)) * request_packet; char * pathfromptr, *pathtoptr; char * msg; struct afp_server * server = volume->server; unsigned int len = sizeof(*request_packet) + sizeof_path_header(server) + strlen(path_from) + sizeof_path_header(server) + strlen(path_to); int ret; if ((msg=malloc(len)) == NULL) return -1; request_packet=(void *) msg; dsi_setup_header(server,&request_packet->dsi_header,DSI_DSICommand); request_packet->command=afpRename; request_packet->pad=0; request_packet->volid=htons(volume->volid); request_packet->dirid=htonl(dirid); pathfromptr=msg+sizeof(*request_packet); copy_path(server,pathfromptr,path_from,strlen(path_from)); unixpath_to_afppath(server,pathfromptr); pathtoptr=pathfromptr+sizeof_path_header(server) + strlen(path_from); copy_path(server,pathtoptr,path_to,strlen(path_to)); unixpath_to_afppath(server,pathtoptr); ret=dsi_send(server, (char *) msg,len,DSI_DEFAULT_TIMEOUT, afpRename,NULL); free(msg); return ret; }
int afp_openfork(struct afp_volume * volume, unsigned char forktype, unsigned int dirid, unsigned short accessmode, char * filename, struct afp_file_info * fp) { struct { struct dsi_header dsi_header __attribute__((__packed__)); uint8_t command; uint8_t forktype; uint16_t volid; uint32_t dirid ; uint16_t bitmap ; uint16_t accessmode; } __attribute__((__packed__)) * afp_openfork_request; char * msg; char *pathptr; struct afp_server * server = volume->server; unsigned int len = sizeof(*afp_openfork_request) + sizeof_path_header(server) + strlen(filename); int ret; if ((msg=malloc(len)) == NULL) return -1; pathptr=msg+sizeof(*afp_openfork_request); afp_openfork_request = (void *) msg; dsi_setup_header(server,&afp_openfork_request->dsi_header,DSI_DSICommand); afp_openfork_request->command=afpOpenFork; afp_openfork_request->forktype=forktype ? AFP_FORKTYPE_RESOURCE : AFP_FORKTYPE_DATA; afp_openfork_request->bitmap=0; afp_openfork_request->volid=htons(volume->volid); afp_openfork_request->dirid=htonl(dirid); afp_openfork_request->accessmode=htons(accessmode); copy_path(server,pathptr,filename,strlen(filename)); unixpath_to_afppath(server,pathptr); ret=dsi_send(server, (char *) msg,len,DSI_DEFAULT_TIMEOUT, afpOpenFork,(void *) fp); 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_setforkparms(struct afp_volume * volume, unsigned short forkid, unsigned short bitmap, unsigned long len) { /* The implementation here deserves some explanation. * If the functin is called with an extended size, use 64 bits. * otherwise, 32. */ struct { struct dsi_header dsi_header __attribute__((__packed__)); uint8_t command; uint8_t pad; uint16_t forkid; uint16_t bitmap; union { uint64_t newlen64; struct { uint32_t newlen; uint32_t pad; } __attribute__((__packed__)) newlen32; } newlen; } __attribute__((__packed__)) request_packet; unsigned int actual_len = sizeof(request_packet); dsi_setup_header(volume->server,&request_packet.dsi_header,DSI_DSICommand); request_packet.command=afpSetForkParms; request_packet.pad=0; request_packet.forkid=htons(forkid); request_packet.bitmap=htons(bitmap); if (bitmap & ( kFPExtDataForkLenBit | kFPExtRsrcForkLenBit )) { /* Ah, so this is a long */ request_packet.newlen.newlen64=htonl(len); } else { request_packet.newlen.newlen32.newlen=htonl(len); actual_len-=4; } return dsi_send(volume->server, (char *) &request_packet, actual_len,DSI_DEFAULT_TIMEOUT,afpSetForkParms,NULL); }
int afp_closefork(struct afp_volume * volume, unsigned short forkid) { struct { struct dsi_header dsi_header __attribute__((__packed__)); uint8_t command; uint8_t pad; uint16_t forkid; } __attribute__((__packed__)) request_packet; dsi_setup_header(volume->server,&request_packet.dsi_header,DSI_DSICommand); request_packet.command=afpCloseFork; request_packet.pad=0; request_packet.forkid=htons(forkid); return dsi_send(volume->server, (char *) &request_packet, sizeof(request_packet),DSI_DEFAULT_TIMEOUT,afpFlushFork,NULL); }
int afp_syncdir(struct afp_volume * volume, unsigned int did) { struct { struct dsi_header dsi_header __attribute__((__packed__)); uint8_t command; uint8_t pad; uint16_t volid; uint32_t dirid; } __attribute__((__packed__)) request_packet; dsi_setup_header(volume->server,&request_packet.dsi_header,DSI_DSICommand); request_packet.command=afpSyncDir; request_packet.pad=0; request_packet.volid=htons(volume->volid); request_packet.dirid=htonl(did); return dsi_send(volume->server, (char *) &request_packet, sizeof(request_packet),DSI_DEFAULT_TIMEOUT,afpSyncDir,NULL); }
int dsi_opensession(struct afp_server *server) { struct { struct dsi_header dsi_header __attribute__((__packed__)); uint8_t flags; uint8_t length; uint32_t rx_quantum ; } __attribute__((__packed__)) dsi_opensession_header; dsi_setup_header(server,&dsi_opensession_header.dsi_header,DSI_DSIOpenSession); /* Advertize our rx quantum */ dsi_opensession_header.flags=1; dsi_opensession_header.length=sizeof(unsigned int); dsi_opensession_header.rx_quantum=htonl(server->attention_quantum); dsi_send(server,(char *) &dsi_opensession_header, sizeof(dsi_opensession_header),1,DSI_BLOCK_TIMEOUT,NULL); return 0; }
int afp_flush(struct afp_volume * volume) { struct { struct dsi_header dsi_header __attribute__((__packed__)); uint8_t command; uint8_t pad; uint16_t volid __attribute__((__packed__)); } __attribute__((__packed__)) afp_flush_request; int ret; dsi_setup_header(volume->server,&afp_flush_request.dsi_header,DSI_DSICommand); afp_flush_request.command=afpFlush; afp_flush_request.pad=0; afp_flush_request.volid=htons(volume->volid); ret=dsi_send(volume->server, (char *) &afp_flush_request, sizeof(afp_flush_request), DSI_DEFAULT_TIMEOUT, afpFlush,(void *) volume); 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; }
int afp_getvolparms(struct afp_volume * volume,unsigned short bitmap) { struct { struct dsi_header dsi_header __attribute__((__packed__)); uint8_t command; uint8_t pad; uint16_t volid __attribute__((__packed__)); uint16_t bitmap __attribute__((__packed__)); } __attribute__((__packed__)) afp_getvolparms_request; int ret; dsi_setup_header(volume->server,&afp_getvolparms_request.dsi_header,DSI_DSICommand); afp_getvolparms_request.command=afpGetVolParms; afp_getvolparms_request.pad=0; afp_getvolparms_request.volid=htons(volume->volid); afp_getvolparms_request.bitmap=htons(bitmap); ret=dsi_send(volume->server, (char *) &afp_getvolparms_request, sizeof(afp_getvolparms_request), DSI_DEFAULT_TIMEOUT, afpGetVolParms,(void *) volume); return ret; }
int afp_moveandrename(struct afp_volume *volume, unsigned int src_did, unsigned int dst_did, char * src_path, char * dst_path, char *new_name) { struct { struct dsi_header dsi_header __attribute__((__packed__)); uint8_t command; uint8_t pad; uint16_t volid ; uint32_t src_did; uint32_t dst_did ; } __attribute__((__packed__)) * request_packet; char * p; char * msg; struct afp_server * server = volume->server; unsigned int len; unsigned int dlen=0,slen=0,nlen=0; int ret; unsigned short header_len=sizeof_path_header(server); char null_path[255]; if (dst_path==NULL) { null_path[0]='\0'; dlen=0; dst_path=null_path; } else { dlen=strlen(dst_path); } if (src_path) slen=strlen(src_path); if (new_name) nlen=strlen(new_name); len = sizeof(*request_packet) + (3* header_len) + dlen + slen + nlen; if ((msg=malloc(len)) == NULL) return -1; request_packet=(void *) msg; dsi_setup_header(server,&request_packet->dsi_header,DSI_DSICommand); request_packet->command=afpMoveAndRename; request_packet->pad=0; request_packet->volid=htons(volume->volid); request_packet->src_did=htonl(src_did); request_packet->dst_did=htonl(dst_did); p=msg+sizeof(*request_packet); copy_path(server,p,src_path,slen); unixpath_to_afppath(server,p); p+=sizeof_path_header(server)+slen; copy_path(server,p,dst_path,dlen); unixpath_to_afppath(server,p); p+=sizeof_path_header(server)+dlen; copy_path(server,p,new_name,nlen); unixpath_to_afppath(server,p); ret=dsi_send(server, (char *) msg,len,DSI_DEFAULT_TIMEOUT,afpMoveAndRename,NULL); free(msg); return ret; }