mirror of
https://github.com/mabam/afpfs-ng-mac.git
synced 2024-12-28 06:30:24 +00:00
433 lines
11 KiB
C
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;
|
||
|
|
||
|
}
|