afpfs-ng-mac/lib/proto_directory.c
2013-03-12 00:08:07 -07:00

433 lines
11 KiB
C

/*
* directory.c
*
* Copyright (C) 2006 Alex deVries
*
*/
#include <string.h>
#include <stdlib.h>
#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"
#include "afp_replies.h"
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;
}
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_createdir(struct afp_volume * volume, unsigned int dirid, const char * pathname, unsigned int *did_p)
{
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 * pathptr;
char * msg;
struct afp_server * server = volume->server;
unsigned int len = sizeof(*request_packet) +
sizeof_path_header(server) + strlen(pathname);
int ret;
if ((msg=malloc(len)) == NULL)
return -1;
pathptr=msg+sizeof(*request_packet);
request_packet = (void *) msg;
dsi_setup_header(server,&request_packet->dsi_header,DSI_DSICommand);
request_packet->command=afpCreateDir;
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 *) msg,len,DSI_DEFAULT_TIMEOUT,
afpCreateDir,(void *)did_p);
free(msg);
return ret;
}
int afp_createdir_reply(struct afp_server * server, char * buf, unsigned int size, void * other)
{
/* We're actually just going to ignore the return bitmap and forkid. */
struct {
struct dsi_header header __attribute__((__packed__));
uint16_t bitmap;
uint16_t forkid;
} __attribute__((__packed__)) * reply_packet = (void *) buf;
unsigned short * dir_p = (void *) other;
*dir_p = 0;
if (reply_packet->header.return_code.error_code)
return (reply_packet->header.return_code.error_code);
if (size<sizeof(*reply_packet))
return -1;
return 0;
}
int afp_enumerate_reply(struct afp_server *server, char * buf, unsigned int size, void * other)
{
struct {
struct dsi_header dsi_header __attribute__((__packed__));
uint16_t filebitmap;
uint16_t dirbitmap;
uint16_t reqcount;
} __attribute__((__packed__)) * reply = (void *) buf;
struct {
uint8_t size;
uint8_t isdir;
} __attribute__((__packed__)) * entry;
char * p = buf + sizeof(*reply);
int i;
char *max=buf+size;
struct afp_file_info * filebase = NULL, *filecur=NULL, *prev=NULL;
void **x = other;
if (reply->dsi_header.return_code.error_code) {
return reply->dsi_header.return_code.error_code;
}
if (size<sizeof(*reply)) {
return -1;
}
for (i=0;i<ntohs(reply->reqcount);i++) {
entry = (void *) p;
if (p>max) {
return -1;
}
prev=filecur;
if ((filecur=malloc(sizeof(struct afp_file_info)))==NULL) {
return -1;
}
if (filebase==NULL) {
filebase=filecur;
prev=filecur;
} else {
prev->next=filecur;
}
parse_reply_block(server,p+sizeof(*entry),
ntohs(entry->size),entry->isdir,
ntohs(reply->filebitmap),
ntohs(reply->dirbitmap),
filecur);
p+=entry->size;
}
*x=filebase;
return 0;
}
int afp_enumerateext2_reply(struct afp_server *server, char * buf, unsigned int size, void * other)
{
struct {
struct dsi_header dsi_header __attribute__((__packed__));
uint16_t filebitmap;
uint16_t dirbitmap;
uint16_t reqcount;
} __attribute__((__packed__)) * reply = (void *) buf;
struct sEntry{
uint16_t size;
uint8_t isdir;
uint8_t pad;
} __attribute__((__packed__)) * entry;
char * p = buf + sizeof(*reply);
int i;
//char *max=buf+size;
struct afp_file_info * filebase = NULL, *filecur = NULL, *new_file = NULL, **x = (struct afp_file_info **) other;
if (reply->dsi_header.return_code.error_code) {
return reply->dsi_header.return_code.error_code;
}
if (size<sizeof(*reply)) {
return -1;
}
for (i=0;i<ntohs(reply->reqcount);i++) {
if ((new_file=malloc(sizeof(struct afp_file_info)))==NULL) {
return -1;
}
new_file->next=NULL;
if (filecur) {
filecur->next=new_file;
filecur=new_file;
} else {
filebase=new_file;
filecur=new_file;
}
entry = (struct sEntry *)p;
parse_reply_block(server,p+sizeof(*entry),
ntohs(entry->size),entry->isdir,
ntohs(reply->filebitmap),
ntohs(reply->dirbitmap),
filecur);
p+=ntohs(entry->size);
}
*x=filebase;
return 0;
}
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 afp_enumerateext2(
struct afp_volume * volume,
unsigned int dirid,
unsigned int filebitmap, unsigned int dirbitmap,
unsigned short reqcount,
unsigned long 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;
uint32_t startindex;
uint32_t maxreplysize;
} __attribute__((__packed__)) * afp_enumerateext2_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_enumerateext2_request_packet);
if ((data=malloc(len))==NULL)
return -1;
path = data+sizeof(*afp_enumerateext2_request_packet);
afp_enumerateext2_request_packet = (void *) data;
dsi_setup_header(server,&afp_enumerateext2_request_packet->dsi_header,DSI_DSICommand);
afp_enumerateext2_request_packet->command=afpEnumerateExt2;
afp_enumerateext2_request_packet->pad=0;
afp_enumerateext2_request_packet->volid=htons(volume->volid);
afp_enumerateext2_request_packet->dirid=htonl(dirid);
afp_enumerateext2_request_packet->filebitmap=htons(filebitmap);
afp_enumerateext2_request_packet->dirbitmap=htons(dirbitmap);
afp_enumerateext2_request_packet->reqcount=htons(reqcount);
afp_enumerateext2_request_packet->startindex=htonl(startindex);
afp_enumerateext2_request_packet->maxreplysize=htonl(5280);
copy_path(server,path,pathname,strlen(pathname));
unixpath_to_afppath(server,path);
rc=dsi_send(server, (char *) data,len,DSI_DEFAULT_TIMEOUT,
afpEnumerateExt2,(void **) &files);
*file_p = files;
free(data);
return rc;
}