afpfs-ng-mac/lib/utils.c

215 lines
4.2 KiB
C

/*
* utils.c
*
* Copyright (C) 2006 Alex deVries
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "afpfs-ng/afp.h"
#include "afpfs-ng/utils.h"
#include "afp_internal.h"
#include "afpfs-ng/afp_protocol.h"
struct afp_path_header_long {
unsigned char type;
unsigned char len;
} __attribute__((__packed__)) ;
struct afp_path_header_unicode {
uint8_t type;
uint32_t hint;
uint16_t unicode;
} __attribute__((__packed__)) ;
int translate_path(struct afp_volume * volume,
char *incoming, char * outgoing)
{
return 0;
}
unsigned short utf8_to_string(char * dest, char * buf, unsigned short maxlen)
{
return copy_from_pascal_two(dest,buf+4,maxlen);
}
unsigned char unixpath_to_afppath(
struct afp_server * server,
char * buf)
{
unsigned char encoding = server->path_encoding;
char *p =NULL, *end;
unsigned short len=0;
switch (encoding) {
case kFPUTF8Name: {
unsigned short *len_p = NULL;
len_p = (void *) buf + 5;
p=buf+7;
len=ntohs(*len_p);
}
break;
case kFPLongName: {
unsigned char *len_p = NULL;
len_p = (void *) buf + 1;
p=buf+2;
len=(*len_p);
}
}
end=p+len;
while (p<end) {
if (*p=='/') *p='\0';
p++;
}
return 0;
}
void afp_unixpriv_to_stat(struct afp_file_info *fp,
struct stat *stat)
{
memset(stat,0,sizeof(*stat));
if (fp->unixprivs.permissions)
stat->st_mode=fp->unixprivs.permissions;
else
stat->st_mode=fp->unixprivs.ua_permissions;
stat->st_uid=fp->unixprivs.uid;
stat->st_gid=fp->unixprivs.gid;
}
unsigned char copy_from_pascal(char *dest, char *pascal,unsigned int max_len)
{
unsigned char len;
if (!pascal) return 0;
len=*pascal;
if (max_len<len) len=max_len;
memset(dest,0,max_len);
memcpy(dest,pascal+1,len);
return len;
}
unsigned short copy_from_pascal_two(char *dest, char *pascal,unsigned int max_len)
{
unsigned short * len_p = (unsigned short *) pascal;
unsigned short len = ntohs(*len_p);
if (max_len<len) len=max_len;
if (len==0) return 0;
memset(dest,0,max_len);
memcpy(dest,pascal+2,len);
return len;
}
unsigned char copy_to_pascal(char *dest, const char *src)
{
unsigned char len = (unsigned char) strlen(src);
dest[0]=len;
memcpy(dest+1,src,len);
return len;
}
unsigned short copy_to_pascal_two(char *dest, const char *src)
{
unsigned short * sendlen = (void *) dest;
char * data = dest + 2;
unsigned short len ;
if (!src) {
dest[0]=0;
dest[1]=0;
return 2;
}
len = (unsigned short) strlen(src);
*sendlen=htons(len);
memcpy(data,src,len);
return len;
}
unsigned char sizeof_path_header(struct afp_server * server)
{
switch (server->path_encoding) {
case kFPUTF8Name:
return(sizeof(struct afp_path_header_unicode));
case kFPLongName:
return(sizeof(struct afp_path_header_long));
}
return 0;
}
void copy_path(struct afp_server * server, char * dest, const char * pathname, unsigned char len)
{
char tmppathname[255];
unsigned char encoding = server->path_encoding;
struct afp_path_header_unicode * header_unicode = (void *) dest;
struct afp_path_header_long * header_long = (void *) dest;
unsigned char offset, header_len, namelen;
switch (encoding) {
case kFPUTF8Name:
header_unicode->type=encoding;
header_unicode->hint=htonl(0x08000103);
offset = 5;
header_len = sizeof(struct afp_path_header_unicode);
namelen=copy_to_pascal_two(tmppathname,pathname);
memcpy(dest+offset,tmppathname,namelen+2);
break;
case kFPLongName:
header_long->type=encoding;
offset = 1;
header_len = sizeof(struct afp_path_header_long);
namelen=copy_to_pascal(tmppathname,pathname) ;
memcpy(dest+offset,tmppathname,namelen+1);
}
}
int invalid_filename(struct afp_server * server, const char * filename)
{
unsigned int maxlen=0;
int len;
char * p, *q;
len = strlen(filename);
if ((len==1) && (*filename=='/')) return 0;
/* From p.34, each individual file can be 255 chars for > 30
for Long or short names. UTF8 is "virtually unlimited" */
if (server->using_version->av_number < 30)
maxlen=31;
else
if (server->path_encoding==kFPUTF8Name)
maxlen=1024;
else
maxlen=255;
p=(char *)filename+1;
while ((q=strchr(p,'/'))) {
if (q>p+maxlen)
return 1;
p=q+1;
if (p>filename+len)
return 0;
}
if (strlen(filename)-(p-filename)>maxlen)
return 1;
return 0;
}