afpfs-ng-mac/lib/proto_fork.c

263 lines
6.7 KiB
C

/*
* fork.c
*
* Copyright (C) 2006 Alex deVries
*
*/
#include <stdlib.h>
#include <string.h>
#include "afpfs-ng/dsi.h"
#include "afpfs-ng/afp.h"
#include "afpfs-ng/utils.h"
#include "dsi_protocol.h"
#include "afpfs-ng/afp_protocol.h"
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_flushfork(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=afpFlushFork;
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_openfork_reply(struct afp_server *server, char * buf, unsigned int size, void * x)
{
struct {
struct dsi_header header __attribute__((__packed__));
uint16_t bitmap;
uint16_t forkid;
} __attribute__((__packed__)) * afp_openfork_reply_packet = (void *) buf;
struct afp_file_info * fp=x;
/* For convenience... */
struct dsi_header * header = &afp_openfork_reply_packet->header;
if ((header->return_code.error_code==kFPNoErr) ||
(header->return_code.error_code==kFPDenyConflict)) {
if (size < sizeof (*afp_openfork_reply_packet)) {
log_for_client(NULL,AFPFSD,LOG_ERR,
"openfork response is too short\n");
return -1;
}
fp->forkid=ntohs(afp_openfork_reply_packet->forkid);
}
/* We end up ignoring the reply bitmap */
return 0;
}
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_byterangelock(struct afp_volume * volume,
unsigned char flag,
unsigned short forkid,
uint32_t offset,
uint32_t len, uint32_t *generated_offset)
{
struct {
struct dsi_header dsi_header __attribute__((__packed__));
uint8_t command;
uint8_t flag;
uint16_t forkid;
uint32_t offset;
uint32_t len;
} __attribute__((__packed__)) request;
int rc;
dsi_setup_header(volume->server,&request.dsi_header,DSI_DSICommand);
request.command=afpByteRangeLock;
request.flag=flag;
request.forkid=htons(forkid);
request.offset=htonl(offset);
request.len=htonl(len);
rc=dsi_send(volume->server, (char *) &request,
sizeof(request),DSI_DEFAULT_TIMEOUT,
afpByteRangeLock,(void *) generated_offset);
return rc;
}
int afp_byterangelock_reply(struct afp_server *server, char * buf, unsigned int size, void * x)
{
struct {
struct dsi_header header __attribute__((__packed__));
uint64_t offset;
} __attribute__((__packed__)) * reply = (void *) buf;
uint32_t *offset=x;
*offset=0;
if (size>=sizeof(*reply))
*offset=ntohl(reply->offset);
return reply->header.return_code.error_code;
}
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_byterangelockext_reply(struct afp_server *server, char * buf, unsigned int size, void * x)
{
struct {
struct dsi_header header __attribute__((__packed__));
uint64_t offset;
} __attribute__((__packed__)) * reply = (void *) buf;
uint64_t *offset=x;
*offset=0;
if (size>=sizeof(*reply))
*offset=ntoh64(reply->offset);
return reply->header.return_code.error_code;
}