afpfs-ng-mac/lib/proto_attr.c

227 lines
6.0 KiB
C

/*
* attr.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"
/* 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;
}