diff -Nru afpfs-ng-0.8.1/cmdline/cmdline_afp.c afpfs-ng-0.8.1/cmdline/cmdline_afp.c --- afpfs-ng-0.8.1/cmdline/cmdline_afp.c 2008-02-19 01:54:19.000000000 +0000 +++ afpfs-ng-0.8.1/cmdline/cmdline_afp.c 2015-03-27 07:22:33.000000000 +0000 @@ -828,11 +828,11 @@ char text[40960]; afp_status_header(text,&len); - printf(text); + printf("%s",text); len=40960; afp_status_server(server,text,&len); - printf(text); + printf("%s",text); return 0; } diff -Nru afpfs-ng-0.8.1/cmdline/cmdline_testafp.c afpfs-ng-0.8.1/cmdline/cmdline_testafp.c --- afpfs-ng-0.8.1/cmdline/cmdline_testafp.c 2008-03-04 20:16:50.000000000 +0000 +++ afpfs-ng-0.8.1/cmdline/cmdline_testafp.c 2015-03-27 07:22:33.000000000 +0000 @@ -26,12 +26,12 @@ struct afp_url valid_url; afp_default_url(&valid_url); valid_url.protocol=protocol; - sprintf(valid_url.servername,servername); - sprintf(valid_url.volumename,volumename); - sprintf(valid_url.path,path); - sprintf(valid_url.username,username); - sprintf(valid_url.password,password); - sprintf(valid_url.uamname,uamname); + strcpy(valid_url.servername,servername); + strcpy(valid_url.volumename,volumename); + strcpy(valid_url.path,path); + strcpy(valid_url.username,username); + strcpy(valid_url.password,password); + strcpy(valid_url.uamname,uamname); valid_url.port=port; if (afp_url_validate(url_string,&valid_url)) diff -Nru afpfs-ng-0.8.1/debian/changelog afpfs-ng-0.8.1/debian/changelog --- afpfs-ng-0.8.1/debian/changelog 2013-12-24 00:58:38.000000000 +0000 +++ afpfs-ng-0.8.1/debian/changelog 2015-10-30 12:35:46.000000000 +0000 @@ -1,3 +1,15 @@ +afpfs-ng (0.8.1-5~wily) wily; urgency=medium + + * port to wily + + -- wsnipex Fri, 30 Oct 2015 13:34:42 +0100 + +afpfs-ng (0.8.1-5~vivid) vivid; urgency=medium + + * port to vivid + + -- wsnipex Fri, 27 Mar 2015 08:23:59 +0100 + afpfs-ng (0.8.1-5ubuntu1) trusty; urgency=medium * Use dh-autoreconf to get new libtool macros for ppc64el and update diff -Nru afpfs-ng-0.8.1/debian/source/format afpfs-ng-0.8.1/debian/source/format --- afpfs-ng-0.8.1/debian/source/format 2012-03-15 15:28:52.000000000 +0000 +++ afpfs-ng-0.8.1/debian/source/format 2015-03-27 10:52:47.000000000 +0000 @@ -1 +1 @@ -3.0 (quilt) +3.0 (native) diff -Nru afpfs-ng-0.8.1/fuse/client.c afpfs-ng-0.8.1/fuse/client.c --- afpfs-ng-0.8.1/fuse/client.c 2008-03-08 02:44:16.000000000 +0000 +++ afpfs-ng-0.8.1/fuse/client.c 2015-03-27 07:22:33.000000000 +0000 @@ -547,7 +547,7 @@ done: memset(toprint,0,MAX_CLIENT_RESPONSE+200); snprintf(toprint,MAX_CLIENT_RESPONSE+200,"%s",incoming_buffer+sizeof(*answer)); - printf(toprint); + printf("%s",toprint); return ((struct afp_server_response *) incoming_buffer)->result; return 0; diff -Nru afpfs-ng-0.8.1/fuse/commands.c afpfs-ng-0.8.1/fuse/commands.c --- afpfs-ng-0.8.1/fuse/commands.c 2008-03-08 16:06:25.000000000 +0000 +++ afpfs-ng-0.8.1/fuse/commands.c 2015-03-27 07:22:33.000000000 +0000 @@ -163,8 +163,7 @@ if (c) { len = strlen(c->client_string); - snprintf(c->client_string+len, - MAX_CLIENT_RESPONSE-len, + strcpy(c->client_string+len, message); } else { @@ -468,7 +467,7 @@ volume->mapping=req->map; afp_detect_mapping(volume); - snprintf(volume->mountpoint,255,req->mountpoint); + strcpy(volume->mountpoint,req->mountpoint); /* Create the new thread and block until we get an answer back */ { diff -Nru afpfs-ng-0.8.1/fuse/mount_afp.1 afpfs-ng-0.8.1/fuse/mount_afp.1 --- afpfs-ng-0.8.1/fuse/mount_afp.1 1970-01-01 00:00:00.000000000 +0000 +++ afpfs-ng-0.8.1/fuse/mount_afp.1 2015-03-27 07:22:33.000000000 +0000 @@ -0,0 +1,8 @@ +.TH MOUNT_AFP "1" "January 2012" "User Commands" +.SH NAME +mount_afp \- mount an AFP (AppleShare) filesystem using FUSE +.SH DESCRIPTION +This is the program which is symlinked by afp_client. See the documentation +for afp_client for information how to use this program. +.SH SEE ALSO +afp_client(1), afpfsd(1) diff -Nru afpfs-ng-0.8.1/include/afp.h afpfs-ng-0.8.1/include/afp.h --- afpfs-ng-0.8.1/include/afp.h 2008-03-08 16:08:18.000000000 +0000 +++ afpfs-ng-0.8.1/include/afp.h 2015-03-27 07:22:33.000000000 +0000 @@ -7,8 +7,8 @@ #include #include #include -#include -#include +#include "afp_protocol.h" +#include "libafpclient.h" #include #include #include diff -Nru afpfs-ng-0.8.1/lib/afp_url.c afpfs-ng-0.8.1/lib/afp_url.c --- afpfs-ng-0.8.1/lib/afp_url.c 2008-03-04 20:16:49.000000000 +0000 +++ afpfs-ng-0.8.1/lib/afp_url.c 2015-03-27 07:22:33.000000000 +0000 @@ -233,7 +233,7 @@ } } - snprintf(url->servername,strlen(p)+1,p); + strcpy(url->servername,p); if (check_servername(url->servername)) { if (verbose) printf("This isn't a valid servername\n"); return -1; @@ -263,7 +263,7 @@ if ((q=escape_strrchr(p,':',":"))) { *q='\0'; q++; - snprintf(url->password,strlen(q)+1,q); + strcpy(url->password,q); if (check_password(url->password)) { if (verbose) printf("This isn't a valid passwd\n"); return -1; @@ -276,7 +276,7 @@ if ((q=strstr(p,";AUTH="))) { *q='\0'; q+=6; - snprintf(url->uamname,strlen(q)+1,q); + strcpy(url->uamname,q); if (check_uamname(url->uamname)) { if (verbose) printf("This isn't a valid uamname\n"); return -1; @@ -284,7 +284,7 @@ } if (strlen(p)>0) { - snprintf(url->username,strlen(p)+1,p); + strcpy(url->username,p); if (check_username(url->username)) { if (verbose) printf("This isn't a valid username\n"); return -1;; @@ -304,12 +304,12 @@ *q='\0'; q++; } - snprintf(url->volumename,strlen(p)+1,p); + strcpy(url->volumename,p); if (q) { url->path[0]='/'; - snprintf(url->path+1,strlen(q)+1,q); + strcpy(url->path+1,q); } done: diff -Nru afpfs-ng-0.8.1/.pc/applied-patches afpfs-ng-0.8.1/.pc/applied-patches --- afpfs-ng-0.8.1/.pc/applied-patches 1970-01-01 00:00:00.000000000 +0000 +++ afpfs-ng-0.8.1/.pc/applied-patches 2015-03-27 07:22:33.000000000 +0000 @@ -0,0 +1,3 @@ +build-error-fixes.patch +mount_afp.1.patch +header-path-fix.patch diff -Nru afpfs-ng-0.8.1/.pc/build-error-fixes.patch/cmdline/cmdline_afp.c afpfs-ng-0.8.1/.pc/build-error-fixes.patch/cmdline/cmdline_afp.c --- afpfs-ng-0.8.1/.pc/build-error-fixes.patch/cmdline/cmdline_afp.c 1970-01-01 00:00:00.000000000 +0000 +++ afpfs-ng-0.8.1/.pc/build-error-fixes.patch/cmdline/cmdline_afp.c 2008-02-19 01:54:19.000000000 +0000 @@ -0,0 +1,1240 @@ +/* + portions Copyright (C) 2007 Alex deVries + +*/ + +#include "afp.h" +#include "midlevel.h" +#include "map_def.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cmdline_main.h" + +static char curdir[AFP_MAX_PATH]; +static struct afp_url url; + +int full_url=0; + +#define DEFAULT_DIRECTORY "/" + +static struct afp_server * server = NULL; +struct afp_volume * vol= NULL; + +static int recursive_get(char * path); + +static int escape_paths(char * outgoing1, char * outgoing2, char * incoming) +{ + char * writeto=outgoing1; + int inquote=0, inescape=0, donewith1=0; + char *p = incoming; + + if ((outgoing1==NULL) || (strlen(incoming)==0)) { + goto error; + } + + memset(outgoing1,0,AFP_MAX_PATH); + if (outgoing2) memset(outgoing2,0,AFP_MAX_PATH); + + for (p=incoming;ptv_sec - starttv->tv_sec) * 1000; + d+= (endtv->tv_usec - starttv->tv_usec) / 1000; + return d; + +} + +static void printdiff(struct timeval * starttv, struct timeval *endtv, + unsigned long long * amount_written) +{ + unsigned int diff; + unsigned long long kb_written; + + diff=tvdiff(starttv,endtv); + float frac = ((float) diff) / 1000.0; /* Now in seconds */ + printf("Transferred %lld bytes in ",*amount_written); + printf("%.3f seconds. ",frac); + + /* Now calculate the transfer rate */ + kb_written = (*amount_written/1000); + float rate = (kb_written)/frac; + printf("(%.0f kB/s)\n", rate); +} + +static int cmdline_getpass(void) +{ + char * passwd; + if (strcmp(url.password,"-")==0) { + passwd=getpass("Password:"); + strncpy(url.password,passwd,AFP_MAX_PASSWORD_LEN); + } + return 0; +} + + +static int get_server_path(char * filename,char * server_fullname) +{ + if (filename[0]!='/') { + if (strlen(curdir)==1) + snprintf(server_fullname,PATH_MAX,"/%s",filename); + else + snprintf(server_fullname,PATH_MAX,"%s/%s",curdir,filename); + } else { + snprintf(server_fullname,PATH_MAX,"%s",filename); + } + return 0; +} + +static void print_file_details(struct afp_file_info * p) +{ + struct tm * mtime; + time_t t,t2; +#define DATE_LEN 32 + char datestr[DATE_LEN]; + char mode_str[11]; + uint32_t mode; + struct stat stat; + + afp_unixpriv_to_stat(p,&stat); + mode=stat.st_mode; + + sprintf(mode_str,"----------"); + + t2=time(NULL); + t=p->modification_date; + mtime=localtime(&t); + + if (p->isdir) mode_str[0]='d'; + + if (mode & S_IRUSR) mode_str[1]='r'; + if (mode & S_IWUSR) mode_str[2]='w'; + if (mode & S_IXUSR) mode_str[3]='x'; + + if (mode & S_IRGRP) mode_str[4]='r'; + if (mode & S_IWGRP) mode_str[5]='w'; + if (mode & S_IXGRP) mode_str[6]='x'; + + if (mode & S_IROTH) mode_str[7]='r'; + if (mode & S_IWOTH) mode_str[8]='w'; + if (mode & S_IXOTH) mode_str[9]='x'; + + + strftime(datestr,DATE_LEN,"%F %H:%M", mtime); + + printf("%s %6lld %s %s\n",mode_str,p->size,datestr,p->name); + +} + +static int connect_volume(const char * volumename) +{ + + if (strlen(volumename)==0) goto error; + + /* Ah, we're not connected to a volume*/ + unsigned int len=0; + char mesg[1024]; + + if ((vol = find_volume_by_name(server,volumename))==NULL) + { + printf("Could not find a volume called %s\n",volumename); + goto error; + } + vol->mapping= AFP_MAPPING_LOGINIDS; + vol->extra_flags |= VOLUME_EXTRA_FLAGS_NO_LOCKING; + + if (afp_connect_volume(vol,server,mesg,&len,1024 )) + { + printf("Could not access volume %s\n", + vol->volume_name); + goto error; + } + + printf("Connected to volume %s\n",vol->volume_name_printable); + + return 0; +error: + return -1; +} + +static int server_subconnect(void) +{ + struct afp_connection_request * conn_req; + +#define BUFFER_SIZE 2048 + conn_req = malloc(sizeof(struct afp_connection_request)); + + memset(conn_req, 0,sizeof(struct afp_connection_request)); + + conn_req->url=url; + conn_req->url.requested_version=31; + if (strlen(url.uamname)>0) { + if ((conn_req->uam_mask = find_uam_by_name(url.uamname))==0) { + printf("I don't know about UAM %s\n",url.uamname); + return -1; + } + + } else { + conn_req->uam_mask=default_uams_mask(); + } + if ((server=afp_server_full_connect(NULL, conn_req))==NULL) { + goto error; + } + + printf("Connected to server %s using UAM \"%s\"\n", + server->server_name_printable, uam_bitmap_to_string(server->using_uam)); + + free(conn_req); + + return 0; +error: + free(conn_req); + printf("Could not connect\n"); + return -1; +} + +int com_pass(char * arg) +{ + if ((strlen(arg)==0) || (strcmp(arg,"-"))) { + getpass("Password: "); + return -1; + } + printf("Password set.\n"); + + strncpy(url.password,arg,AFP_MAX_PASSWORD_LEN); + return 0; + +} + + +int com_user(char * arg) +{ + if (strlen(arg)==0) { + printf("You must specify a user\n"); + return -1; + } + + strncpy(url.username,arg,AFP_MAX_PASSWORD_LEN); + printf("username is now %s\n",url.username); + return 0; +} + +int com_disconnect(char * arg) +{ + if (server==NULL) { + printf("You're not connected yet to a server\n"); + goto error; + } + afp_unmount_volume(vol); + + vol=NULL; + + server=NULL; + snprintf(curdir,AFP_MAX_PATH,"/"); + + return 0; +error: + return -1; +} + + +int com_connect(char * arg) +{ + struct afp_url tmpurl; + if (!arg) + arg = ""; + + if (server) { + printf("You're already connected to a server\n"); + goto error; + } + + afp_default_url(&tmpurl); + + /* First, try to parse the URL */ + + if (afp_parse_url(&tmpurl,arg,0)!=0) { + /* Okay, this isn't a real URL */ + printf("Could not parse url, let me see if this is a server name...\n"); + if (gethostbyname(arg)) + memcpy(&url.servername,arg,AFP_SERVER_NAME_LEN); + else { + printf("Cannot understand server name or url %s\n",arg); + return -1; + } + } else { + url=tmpurl; + + } + cmdline_getpass(); + + + if (server_subconnect()) { + printf("Could not connect\n"); + goto error; + }; + + connect_volume(url.volumename); + + return 0; +error: + return -1; + +} + + +int com_dir(char * arg) +{ + if (!arg) + arg = ""; + + struct afp_file_info *filebase = NULL, *p; + + if (server==NULL) { + printf("You're not connected yet to a volume\n"); + goto error; + } + + if (strlen(url.volumename)==0) { + char names[1024]; + afp_list_volnames(server,names,1024); + printf("You're not connected to a volume, choose from %s\n", + names); + goto out; + } + + if (ml_readdir(vol,curdir,&filebase)) goto error; + + if (filebase==NULL) goto out; + for (p=filebase;p;p=p->next) { + print_file_details(p); + } + afp_ml_filebase_free(&filebase); + +out: + + return 0; +error: + return -1; +} + + +int com_touch(char * arg) +{ + char server_fullname[AFP_MAX_PATH]; + int ret; + char filename[AFP_MAX_PATH]; + char * basename = filename; + + if (escape_paths(filename,NULL,arg)) { + printf("Syntax: touch \n"); + goto error; + } + + if ((server==NULL) || (vol==NULL)) { + printf("You're not connected yet to a volume\n"); + goto error; + } + + get_server_path(basename,server_fullname); + + ret=ml_creat(vol,server_fullname,0600); + return 0; +error: + return -1; + + return 0; +} + +int com_chmod(char * arg) +{ + unsigned int mode; + char basename[PATH_MAX]; + char server_fullname[AFP_MAX_PATH]; + char modestring[100]; + int ret; + + if ((server==NULL) || (vol==NULL)) { + printf("You're not connected yet to a volume\n"); + goto error; + } + + if (escape_paths(modestring,basename,arg)) { + printf("expecting format: chmod \n"); + goto error; + } + + if (sscanf(modestring,"%o",&mode)!=1) { + printf("Mode of %s isn't octal\n"); + goto error; + } + + get_server_path(basename,server_fullname); + + printf("Changing mode of %s to %o\n",server_fullname,mode); + ret=ml_chmod(vol,server_fullname,mode); + return 0; +error: + return -1; +} + + +int com_put(char *arg) +{ + int ret, amount_read; + struct afp_file_info *fp; + int offset=0; +#define PUT_BUFSIZE 102400 + char buf[PUT_BUFSIZE]; + int fd; + char server_fullname[AFP_MAX_PATH]; + char * basename; + uid_t uid; + gid_t gid; + struct stat localstat; + unsigned long long amount_written=0; + struct timeval starttv,endtv; + char filename[AFP_MAX_PATH]; + + if ((server==NULL) || (vol==NULL)) { + printf("You're not connected yet to a volume\n"); + goto error; + } + + if ((escape_paths(filename,NULL,arg))) { + printf("expecting format: put \n"); + goto error; + } + + /* FIXME find basename */ + basename=filename; + + get_server_path(basename,server_fullname); + + /* FIXME need a better way to get server's uid/gid */ + + uid=getuid(); + gid=getgid(); + + if (stat(filename, &localstat)!=0) { + perror("Opening local file"); + } + + fd = open(filename,O_RDONLY); + + if (fd<0) { + perror("Opening local file"); + goto error; + } + + gettimeofday(&starttv,NULL); + + ret = ml_open(vol,server_fullname,O_CREAT | O_RDWR,&fp); + + if (ret<0) { + printf("Problem opening file %s on server\n",basename); + goto out; + } + + /* Now set various permissions */ + + ret=ml_chmod(vol,server_fullname,localstat.st_mode); + if (ret==-ENOSYS) printf("cannot change permissions\n"); + if (ret) { + printf("Could not change permissions to 0%o\n", + localstat.st_mode); + } + + while (1) { + amount_read=read(fd,buf,PUT_BUFSIZE); + if (amount_read<0) { + perror("Reading"); + goto out; + } + if (amount_read==0) goto out; + ret=ml_write(vol,server_fullname,buf,amount_read, + offset,fp,uid,gid); + offset+=amount_read; + amount_written+=amount_read; + if (ret<0) { + printf("IO error when writing to server, error %d\n", + ret); + goto out; + } + } + +/* FIXME time */ + +out: + gettimeofday(&endtv,NULL); + printdiff(&starttv, &endtv,&amount_written); + + close(fd); + ml_close(vol,server_fullname,fp); + return 0; + +error: + return -1; + +} + +static int retrieve_file(char * arg,int fd, int silent, + struct stat *stat, unsigned long long * amount_written) +{ + int flags=O_RDONLY; + int ret=0; + struct afp_file_info * fp; + char path[PATH_MAX]; + off_t offset = 0; +#define BUF_SIZE 102400 + size_t size = BUF_SIZE; + char buf[BUF_SIZE]; + int eof; + unsigned long long total=0; + struct timeval starttv,endtv; + + *amount_written=0; + + if (server==NULL) { + printf("You're not connected yet to a volume\n"); + goto error; + } + + get_server_path(arg,path); + + gettimeofday(&starttv,NULL); + + if ((ret=ml_getattr(vol,path,stat))!=0) { + printf("Could not get file attributes for file %s, return code %d\n",path,ret); + goto error; + } + + ret = ml_open(vol,path,flags,&fp); + + if (ret) { + printf("Could not open %s on server, AFP error %d\n",arg,ret); + goto error; + } + + ret =1; /* to get the loop going */ + while (ret) + { + memset(buf,0,BUF_SIZE); + ret = ml_read(vol,path,buf,size,offset,fp,&eof); + if (ret<=0) goto out; + total+=write(fd,buf,ret); + offset+=ret; + if ((eof==1) || (ret==0)) goto out; + } +out: + + if (fd>1) close(fd); + ml_close(vol,path,fp); + + free(fp); + + if (silent==0) { + gettimeofday(&endtv,NULL); + printdiff(&starttv, &endtv,&total); + } + + *amount_written=total; + return 0; +error: + return -1; +} + +static int com_get_file(char * arg, int silent, + unsigned long long * total) +{ + int fd; + struct stat stat; + char * localfilename; + char filename[AFP_MAX_PATH]; + char getattr_path[AFP_MAX_PATH]; + int ret; + + if ((server==NULL) || (vol==NULL)) { + printf("You're not connected yet to a volume\n"); + goto error; + } + if ((escape_paths(filename,NULL,arg))) { + printf("expecting format: get \n"); + goto error; + } + localfilename=basename(filename); + + printf(" Getting file %s\n",filename); + + if ((access(localfilename,W_OK)) && (errno!=ENOENT)) { + printf("Trying to access %s\n",localfilename); + perror("Access local file for write"); + goto error; + } + + get_server_path(filename,getattr_path); + + if ((ret=ml_getattr(vol,getattr_path,&stat))!=0) { + printf("Could not get file attributes for file %s, return code %d\n",filename,ret); + goto error; + } + + fd=open(localfilename,O_CREAT | O_TRUNC| O_RDWR, stat.st_mode); + if (fd<0) { + perror("Opening local file"); + goto error; + } + chmod(localfilename,stat.st_mode); + chown(localfilename,stat.st_uid,stat.st_gid); + retrieve_file(filename,fd,silent,&stat, total); + + close(fd); + return 0; +error: + return -1; +} + +int com_get (char *arg) +{ + unsigned long long amount_written; + char newpath[255]; + + if ((server==NULL) || (vol==NULL)) { + printf("You're not connected yet to a volume\n"); + goto error; + } + if ((arg[0]=='-') && (arg[1]=='r') && (arg[2]==' ')) { + arg+=3; + while ((arg) && (isspace(arg[0]))) arg++; + snprintf(newpath,255,"%s/%s",curdir,arg); + return recursive_get(newpath); + } else + return com_get_file(arg,0, &amount_written); +error: + return -1; +} + + +int com_view (char * arg) +{ + unsigned long long amount_written; + char filename[AFP_MAX_PATH]; + + if ((server==NULL) || (vol==NULL)) { + printf("You're not connected yet to a volume\n"); + goto error; + } + + if ((escape_paths(filename,NULL,arg))) { + printf("expecting format: view \n"); + goto error; + } + printf("Viewing: %s\n",filename); + retrieve_file(filename,fileno(stdout),1,NULL, &amount_written); + return 0; +error: + return -1; +} + +int com_rename (char * arg) +{ + + char from_path[AFP_MAX_PATH], to_path[AFP_MAX_PATH]; + char full_from_path[AFP_MAX_PATH], full_to_path[AFP_MAX_PATH]; + struct stat stbuf; + int ret; + + if ((server==NULL) || (vol==NULL)) { + printf("You're not connected yet to a volume\n"); + goto error; + } + + if (escape_paths(from_path,to_path,arg)) { + printf("Syntax: mv \n"); + goto error; + } + + get_server_path(from_path,full_from_path); + get_server_path(to_path,full_to_path); + printf("Moving from %s to %s\n",full_from_path,full_to_path); + + /* Make sure from_file exists */ + if ((ret=ml_getattr(vol,full_from_path,&stbuf))) { + printf("Could not find file %s, error was %d\n", + full_from_path,ret); + goto error; + } + + /* Make sure to_file doesn't exist */ + ret=ml_getattr(vol,full_to_path,&stbuf); + if ((ret==0) && ((stbuf.st_mode & S_IFDIR)==0)) { + printf("File %s already exists, error: %d\n", + full_to_path,ret); + goto error; + } + + if ((ret=ml_rename(vol,full_from_path, full_to_path))) goto error; + + return 0; +error: + return -1; +} + +int com_delete (char *arg) +{ + + int ret; + char server_fullname[AFP_MAX_PATH]; + char filename[AFP_MAX_PATH]; + + if ((server==NULL) || (vol==NULL)) { + printf("You're not connected yet to a volume\n"); + goto error; + } + + if (escape_paths(filename,NULL,arg)) { + printf("Syntax: del \n"); + goto error; + } + + get_server_path(filename,server_fullname); + + if ((ret=ml_unlink(vol,server_fullname))) { + printf("Could not remove %s, error code is %d\n", + filename,ret); + goto error; + } + printf("Removed file %s\n",filename); + return (1); +error: + return -1; +} + +int com_mkdir(char *arg) +{ + + int ret; + char server_fullname[AFP_MAX_PATH]; + char filename[AFP_MAX_PATH]; + + if ((server==NULL) || (vol==NULL)) { + printf("You're not connected yet to a volume\n"); + goto error; + } + + if (escape_paths(filename,NULL,arg)) { + printf("Syntax: mkdir \n"); + goto error; + } + + get_server_path(filename,server_fullname); + + if ((ret=ml_mkdir(vol,server_fullname,0755))) { + printf("Could not create directory %s, error code is %d\n", + filename,ret); + goto error; + } + printf("Created directory %s\n",filename); + return 0; +error: + return -1; +} + +int com_rmdir(char *arg) +{ + + int ret; + char server_fullname[AFP_MAX_PATH]; + char filename[AFP_MAX_PATH]; + + if ((server==NULL) || (vol==NULL)) { + printf("You're not connected yet to a volume\n"); + goto error; + } + + if (escape_paths(filename,NULL,arg)) { + printf("Syntax: rmdir \n"); + goto error; + } + + get_server_path(filename,server_fullname); + + if ((ret=ml_rmdir(vol,server_fullname))) { + printf("Could not remove directory %s, error code is %d\n", + filename,ret); + goto error; + } + printf("Removed directory %s\n",filename); + return 0; +error: + return -1; +} + +int com_status(char * arg) +{ + int len=40960; + char text[40960]; + + afp_status_header(text,&len); + printf(text); + + len=40960; + afp_status_server(server,text,&len); + printf(text); + return 0; +} + +int com_passwd(char * arg) +{ + char * p; + int ret; + char newpass[AFP_MAX_PASSWORD_LEN]; + + if (!server) { + printf("Not connected to a server\n"); + goto error; + } + p = getpass("New password: "); + strncpy(newpass,p,AFP_MAX_PASSWORD_LEN); + ret=ml_passwd(server,url.username,url.password,newpass); + if (ret) { + printf("Could not change password\n"); + goto error; + } + + return 0; +error: + return -1; +} + +static void print_size(unsigned long l) +{ + + if (l>(1073741824)) { + printf("%4ldTb",l/1073741824); + return; + } + if (l>(1048576)) { + printf("%4ldGb",l/1048576); + return; + } + if (l>(1024)) { + printf("%4ldMb",l>>10); + return; + } + printf("%4ldKb\n",l); + +} + +int com_statvfs(char * arg) +{ + struct statvfs stat; + unsigned long avail, used,total; + unsigned int portion; + int i; + + if ((server==NULL) || (vol==NULL)) { + printf("Not connected to a volume\n"); + goto error; + } + ml_statfs(vol,"/",&stat); + + avail=stat.f_bavail*4; + used=(stat.f_blocks-stat.f_bavail)*4; + total=avail+used; + + portion = (unsigned int) (((float) used*100)/((float) avail+(float) used)); + + printf("Volume "); + for (i=strlen(vol->volume_name_printable)-6;i>0;i--) printf(" "); + + if (strstr(arg,"-h")) { + printf(" Size Used Avail Capacity\n"); + printf("%s ", vol->volume_name_printable); + print_size(total); printf(" "); + print_size(used); printf(" "); + print_size(avail); printf(" "); + printf(" %d%%\n",portion); + } else { + avail*=2; + used*=2; + total*=2; + printf(" 512-blocks Used Available Use%%\n"); + printf("%s %10ld %10ld %10ld %d%%\n", vol->volume_name_printable, + total, used, avail,portion); + } + return 0; +error: + return -1; +} + + +int com_lcd(char * path) +{ + + int ret; + char curpath[PATH_MAX]; + + ret=chdir(path); + if (ret!=0) + perror("Changing directories"); + else { + getcwd(curpath,PATH_MAX); + printf("Now in local directory %s\n",curpath); + } + return ret; + +} + +/* Change to the directory ARG. */ +int com_cd (char *arg) +{ + + int ret; + char newdir[AFP_MAX_PATH]; + char * p; + struct stat stbuf; + char tmppath[AFP_MAX_PATH]; + char * path = tmppath; + + memset(newdir,'\0',AFP_MAX_PATH); + memset(path,'\0',AFP_MAX_PATH); + + if (server==NULL) { + printf("You're not connected to a server yet\n"); + goto error; + } + + if (strlen(url.volumename)==0) { + char * volumename, *t; + + if (escape_paths(path,NULL,arg)) { + printf("Syntax: cd \n"); + goto error; + } + volumename=path; + if ((t=strchr(path,'/'))) { + path=t+1; + *t='\0'; + } else + path=NULL; + + if (connect_volume(volumename)==0) { + memcpy(url.volumename,vol->volume_name, + AFP_VOLUME_NAME_UTF8_LEN); + if (path==NULL) { + return 0; + } + } + else return -1; + } else { + if (escape_paths(path,NULL,arg)) + memset(path,'\0',AFP_MAX_PATH); + } + + /* Chop off the last / */ + if (((strlen(path)>1) && (path[strlen(path)-1]=='/'))) + path[strlen(path)-1]='\0'; + if (((strlen(curdir)>1) && (curdir[strlen(curdir)-1]=='/'))) + curdir[strlen(curdir)-1]='\0'; + + if (strncmp(path,"..", AFP_MAX_PATH)==0) { + /* go back one */ + + if (strlen(curdir)==1) { + printf("Already at top level\n"); + return 0; + } + if ((p=strrchr(curdir,'/'))) { + if (p==curdir) snprintf(curdir,AFP_MAX_PATH,"/"); + else *p='\0'; + } else { + printf("Internal error\n"); + goto error; + } + } else { + if (path[0]=='/') { + memcpy(newdir,path, AFP_MAX_PATH); + } else { + if (((strlen(path)==1) && (path[0]=='/')) || + (((strlen(curdir)==1) && (curdir[0]=='/')))) { + + snprintf(newdir,AFP_MAX_PATH,"/%s",path); + } else { + snprintf(newdir,AFP_MAX_PATH, + "%s/%s",curdir,path); + } + } + + ret=ml_getattr(vol,newdir,&stbuf); + + if ((ret==0) && (stbuf.st_mode & S_IFDIR)) { + memcpy(curdir,newdir,AFP_MAX_PATH); + printf("Now in directory %s\n",curdir); + } else { + if ((stbuf.st_mode & S_IFDIR)==0) { + printf("%s is not a directory, mode is 0%o\n",newdir, + stbuf.st_mode); + } else { + printf("Error %d\n",ret); + goto error; + } + } + + + } + + /* To change directory, get a file list and grab the did. */ + return 0; +error: + return -1; +} + +/* Print out the current working directory locally. */ +int com_lpwd (char * ignore) +{ + char dir[255]; + getcwd(dir,255); + printf("Now in local directory %s\n",dir); + return 0; +} + +/* Print out the current working directory. */ +int com_pwd (char * ignore) +{ + if ((server==NULL) || (vol==NULL)) { + printf("You're not connected to a volume yet\n"); + goto error; + } + + printf("Now in directory %s on volume %s.\n",curdir, vol->volume_name_printable); + return 0; +error: + return -1; +} + +static int get_dir(char * server_base, char * path, + unsigned long long * total) +{ + struct afp_file_info * p, *filebase; + char total_path[AFP_MAX_PATH]; + unsigned long long amount_written, local_total=0; + + if (strcmp(server_base,"/")==0) + snprintf(total_path,AFP_MAX_PATH,"/%s",path); + else + snprintf(total_path,AFP_MAX_PATH,"%s/%s",server_base,path); + + printf("Getting directory %s\n",total_path); + + mkdir(path,0755); + chdir(path); + + if (ml_readdir(vol,total_path,&filebase)) goto error; + if (filebase==NULL) goto out; + for (p=filebase;p;p=p->next) { + if (p->isdir) { + get_dir(total_path,p->name, &amount_written); + } else { + snprintf(curdir,AFP_MAX_PATH,"%s",total_path); + com_get_file(p->name,1, &amount_written); + } + local_total+=amount_written; + } + + afp_ml_filebase_free(&filebase); + +out: + + *total=local_total; + chdir(".."); + + return 0; +error: + chdir(".."); + return -1; + +} + + +static int recursive_get(char * path) +{ + char * dirc = strdup(path); + char * base = basename(path); + char * dir = dirname(dirc); + + struct timeval starttv, endtv; + unsigned long long amount_written; + + gettimeofday(&starttv,NULL); + get_dir(dir,base, &amount_written); + gettimeofday(&endtv,NULL); + + printdiff(&starttv,&endtv, &amount_written); + + return 0; + +} + +static struct libafpclient afpclient = { + .unmount_volume = NULL, + .log_for_client = stdout_log_for_client, + .forced_ending_hook = cmdline_forced_ending_hook, + .scan_extra_fds = NULL, + .loop_started = cmdline_loop_started, +}; + +static void * cmdline_server_startup(int recursive) +{ + + struct stat stbuf; + int ret; + + full_url=1; + + if (server_subconnect()) goto error; + + if (strlen(url.volumename)==0) { + int i; + char names[1024]; + afp_list_volnames(server,names,1024); + printf("Specify a volume with 'cd volume'. Choose one of: %s\n", + names); + trigger_connected(); + return NULL; + } + + ret=connect_volume(url.volumename); + + if (ret) { + printf("Could not connect to volume %s on server\n",url.volumename); + just_end_it_now(NULL); + goto error; + } + + + trigger_connected(); + + if (strlen(url.path)==0) + return NULL; + + ret=ml_getattr(vol,url.path,&stbuf); + + if (ret) { + printf("Could not open %s on server\n",url.path); + just_end_it_now(NULL); + goto error; + } + + if (stbuf.st_mode & S_IFDIR) { + snprintf(curdir,AFP_MAX_PATH,"%s",url.path); + printf("In directory %s\n",url.path); + if (recursive) { + recursive_get(url.path); + } + + } else { + com_get(url.path); + just_end_it_now(NULL); + } + + return NULL; + +error: + printf("Error\n"); + return (void *) -1; + + +} + +void cmdline_afp_exit(void) +{ + + afp_unmount_volume(vol); + +} + +void cmdline_afp_setup_client(void) +{ + libafpclient_register(&afpclient); + +} + + +int cmdline_afp_setup(int recursive, char * url_string) +{ + struct passwd * passwd; + + snprintf(curdir,PATH_MAX,"%s",DEFAULT_DIRECTORY); + if (init_uams()<0) return -1; + + afp_default_url(&url); + + passwd = getpwuid(getuid()); + strncpy(url.username, passwd->pw_name,AFP_MAX_USERNAME_LEN); + if ((url_string) && (strlen(url_string)>1)) { + + + if (afp_parse_url(&url,url_string,1)) { + printf("Could not parse url.\n"); + } + cmdline_getpass(); + trigger_connected(); + cmdline_server_startup(recursive); + } + + return 0; +} + diff -Nru afpfs-ng-0.8.1/.pc/build-error-fixes.patch/cmdline/cmdline_testafp.c afpfs-ng-0.8.1/.pc/build-error-fixes.patch/cmdline/cmdline_testafp.c --- afpfs-ng-0.8.1/.pc/build-error-fixes.patch/cmdline/cmdline_testafp.c 1970-01-01 00:00:00.000000000 +0000 +++ afpfs-ng-0.8.1/.pc/build-error-fixes.patch/cmdline/cmdline_testafp.c 2008-03-04 20:16:50.000000000 +0000 @@ -0,0 +1,120 @@ +/* + Copyright (C) 2008 Alex deVries + +*/ + +#include "afp.h" +#include "midlevel.h" + +#include "cmdline_main.h" + +#include +#include + +extern struct afp_volume * vol; + +static int test_one_url(char * url_string, + enum {TCPIP,AT} protocol, + char * username, + char * uamname, + char * password, + char * servername, + int port, + char * volumename, + char * path) +{ + struct afp_url valid_url; + afp_default_url(&valid_url); + valid_url.protocol=protocol; + sprintf(valid_url.servername,servername); + sprintf(valid_url.volumename,volumename); + sprintf(valid_url.path,path); + sprintf(valid_url.username,username); + sprintf(valid_url.password,password); + sprintf(valid_url.uamname,uamname); + valid_url.port=port; + + if (afp_url_validate(url_string,&valid_url)) + printf("* Could not parse %s\n",url_string); + else + printf("* Parsed %s correctly\n",url_string); + + return 0; +} + +int test_urls(void) +{ + + printf("Testing URL parsing\n"); + + test_one_url("afp://user::name;AUTH=authtype:pa@@sword@server/volume/path", + TCPIP,"user:name","authtype","pa@sword","server",548,"volume","path"); + + test_one_url("afp://username;AUTH=authtype:password@server/volume/path", + TCPIP,"username","authtype","password","server",548,"volume","path"); + test_one_url("afp://username;AUTH=authtype:password@server:548/volume/path", + TCPIP,"username","authtype","password","server",548,"volume","path"); + test_one_url("afp://username:password@server/volume/path", + TCPIP,"username","","password","server",548,"volume","path"); + test_one_url("afp://username@server/volume/path", + TCPIP,"username","","","server",548,"volume","path"); + test_one_url("afp://server/volume/path", + TCPIP,"","","","server",548,"volume","path"); + test_one_url("afp://server/", + TCPIP,"","","","server",548,"",""); + test_one_url("afp://server:22/", + TCPIP,"","","","server",22,"",""); + test_one_url("afp://server:22", + TCPIP,"","","","server",22,"",""); + test_one_url("afp://server:22/volume/", + TCPIP,"","","","server",22,"volume",""); + return 0; +} + +int com_testafp(char * arg) +{ + char * data = malloc(200); + int i; + + if (!arg) + arg = ""; + +for (i=0;i<6;i++) { + data[0]=0x00; + data[1]=0x00; + data[2]=i; + data[3]=4; + data[4]=0x00; + data[5]=0x00; + data[6]=0x00; + data[7]=0x01; + data[8]=0x00; + data[9]=0x00; + data[10]=0x00; + data[11]=0x00; + + sprintf(data+12,"%s","mymountpoint"); + afp_newcommand76(vol,31,data); +} + return 0; + + + data[0]=0x00; + data[1]=0x00; + data[2]=0x00; + data[3]=0x04; + data[4]=0x00; + data[5]=0x00; + data[6]=0x00; + data[7]=0x02; + data[8]=0x00; + data[9]=0x00; + data[10]=0x00; + data[11]=0x00; + +afp_newcommand76(vol,12,data); + + + return 0; +} + diff -Nru afpfs-ng-0.8.1/.pc/build-error-fixes.patch/fuse/client.c afpfs-ng-0.8.1/.pc/build-error-fixes.patch/fuse/client.c --- afpfs-ng-0.8.1/.pc/build-error-fixes.patch/fuse/client.c 1970-01-01 00:00:00.000000000 +0000 +++ afpfs-ng-0.8.1/.pc/build-error-fixes.patch/fuse/client.c 2008-03-08 02:44:16.000000000 +0000 @@ -0,0 +1,585 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include +#include "afp_server.h" +#include "uams_def.h" +#include "map_def.h" +#include "libafpclient.h" + +#define default_uam "Cleartxt Passwrd" + +#define MAX_OUTGOING_LENGTH 8192 + +#define AFPFSD_FILENAME "afpfsd" +#define DEFAULT_MOUNT_FLAGS (VOLUME_EXTRA_FLAGS_SHOW_APPLEDOUBLE|\ + VOLUME_EXTRA_FLAGS_NO_LOCKING | VOLUME_EXTRA_FLAGS_IGNORE_UNIXPRIVS) + +static char outgoing_buffer[MAX_OUTGOING_LENGTH]; +static int outgoing_len=0; +static unsigned int uid, gid=0; +static int changeuid=0; +static int changegid=0; +static char * thisbin; + + +static int start_afpfsd(void) +{ + char *argv[1]; + + argv[0]=0; + if (fork()==0) { + char filename[PATH_MAX]; + if (changegid) { + if (setegid(gid)) { + perror("Changing gid"); + return -1; + } + } + if (changeuid) { + if (seteuid(uid)) { + perror("Changing uid"); + return -1; + } + } + snprintf(filename,PATH_MAX,AFPFSD_FILENAME); + if (getenv("PATH")==NULL) { + /* If we don't have an PATH set, it is probably + becaue we are being called from mount, + so go search for it */ + snprintf(filename, PATH_MAX, + "/usr/local/bin/%s",AFPFSD_FILENAME); + if (access(filename,X_OK)) { + snprintf(filename, "/usr/bin/%s", + AFPFSD_FILENAME); + if (access(filename,X_OK)) { + printf("Could not find server (%s)\n", + filename); + return -1; + } + } + } + + if (execvp(filename,argv)) { + if (errno==ENOENT) { + /* Try the path of afp_client */ + char newpath[PATH_MAX]; + snprintf(newpath,PATH_MAX,"%s/%s", + basename(thisbin),AFPFSD_FILENAME); + if (execvp(newpath,argv)) { + perror("Starting up afpfsd\n"); + return -1; + } + } else { + perror("Starting up afpfsd"); + return -1; + } + } + printf("done threading\n"); + } + return 0; +} + + +static int daemon_connect(void) +{ + int sock; + struct sockaddr_un servaddr; + char filename[PATH_MAX]; + unsigned char trying=2; + + if ((sock=socket(AF_UNIX,SOCK_STREAM,0)) < 0) { + perror("Could not create socket\n"); + return -1; + } + memset(&servaddr,0,sizeof(servaddr)); + servaddr.sun_family = AF_UNIX; + sprintf(filename,"%s-%d",SERVER_FILENAME,uid); + + strcpy(servaddr.sun_path,filename); + + while(trying) { + if ((connect(sock,(struct sockaddr*) &servaddr, + sizeof(servaddr.sun_family) + + sizeof(servaddr.sun_path))) >=0) + goto done; + printf("The afpfs daemon does not appear to be running for uid %d, let me start it for you\n", uid); + + if (start_afpfsd()!=0) { + printf("Error in starting up afpfsd\n"); + goto error; + } + if ((connect(sock,(struct sockaddr*) &servaddr, + sizeof(servaddr.sun_family) + + sizeof(servaddr.sun_path))) >=0) + goto done; + sleep(1); + trying--; + } +error: + perror("Trying to startup afpfsd"); + return -1; + +done: + return sock; +} + + +static void usage(void) +{ + printf( +"afp_client [command] [options]\n" +" mount [mountopts] : \n" +" mount options:\n" +" -u, --user : log in as user \n" +" -p, --pass : use \n" +" If password is '-', password will be hidden\n" +" -o, --port : connect using instead of 548\n" +" -V, --volumepassword : use this volume password\n" +" -v, --afpversion set the AFP version, eg. 3.1\n" +" -a, --uam : use this authentication method, one of:\n" +" \"No User Authent\", \"Cleartxt Passwrd\", \n" +" \"Randnum Exchange\", \"2-Way Randnum Exchange\", \n" +" \"DHCAST128\", \"Client Krb v2\", \"DHX2\" \n\n" +" -m, --map : use this uid/gid mapping method, one of:\n" +" \"Common user directory\", \"Login ids\"\n" +" status: get status of the AFP daemon\n\n" +" unmount : unmount\n\n" +" suspend : terminates the connection to the server, but\n" +" maintains the mount. For laptop suspend/resume\n" +" resume : resumes the server connection \n\n" +" exit : unmounts all volumes and exits afpfsd\n" +); + } + + +static int send_command(int sock, char * msg,int len) +{ + + return write(sock,msg,len); +} + +static int do_exit(int argc,char **argv) +{ + outgoing_len=1; + outgoing_buffer[0]=AFP_SERVER_COMMAND_EXIT; + + return 0; + +} + +static int do_status(int argc, char ** argv) +{ + int c; + int option_index=0; + struct afp_server_status_request * req; + int optnum; + struct option long_options[] = { + {"volume",1,0,'v'}, + {"server",1,0,'s'}, + {0,0,0,0}, + }; + + outgoing_len=sizeof(struct afp_server_status_request)+1; + req = (void *) outgoing_buffer+1; + memset(outgoing_buffer,0,outgoing_len); + outgoing_buffer[0]=AFP_SERVER_COMMAND_STATUS; + + while(1) { + optnum++; + c = getopt_long(argc,argv,"v:s:", + long_options,&option_index); + if (c==-1) break; + switch(c) { + case 'v': + snprintf(req->volumename,AFP_VOLUME_NAME_LEN, + "%s",optarg); + break; + } + } + + return 0; +} + +static int do_resume(int argc, char ** argv) +{ + struct afp_server_resume_request * req; + outgoing_len=sizeof(struct afp_server_resume_request)+1; + req = (void *) outgoing_buffer+1; + if (argc<3) { + usage(); + return -1; + } + + memset(req,0,sizeof(*req)); + snprintf(req->server_name,AFP_SERVER_NAME_LEN,"%s",argv[2]); + outgoing_buffer[0]=AFP_SERVER_COMMAND_RESUME; + + return 0; +} + +static int do_suspend(int argc, char ** argv) +{ + struct afp_server_suspend_request * req; + outgoing_len=sizeof(struct afp_server_suspend_request)+1; + req = (void *) outgoing_buffer+1; + if (argc<3) { + usage(); + return -1; + } + + memset(req,0,sizeof(*req)); + snprintf(req->server_name,AFP_SERVER_NAME_LEN,"%s",argv[2]); + outgoing_buffer[0]=AFP_SERVER_COMMAND_SUSPEND; + + return 0; +} + +static int do_unmount(int argc, char ** argv) +{ + struct afp_server_unmount_request * req; + outgoing_len=sizeof(struct afp_server_unmount_request)+1; + req = (void *) outgoing_buffer+1; + if (argc<2) { + usage(); + return -1; + } + + memset(req,0,sizeof(*req)); + snprintf(req->mountpoint,255,"%s",argv[2]); + outgoing_buffer[0]=AFP_SERVER_COMMAND_UNMOUNT; + + return 0; +} + +static int do_mount(int argc, char ** argv) +{ + int c; + int option_index=0; + struct afp_server_mount_request * req; + int optnum; + unsigned int uam_mask=default_uams_mask(); + + struct option long_options[] = { + {"afpversion",1,0,'v'}, + {"volumepassword",1,0,'V'}, + {"user",1,0,'u'}, + {"pass",1,0,'p'}, + {"port",1,0,'o'}, + {"uam",1,0,'a'}, + {"map",1,0,'m'}, + {0,0,0,0}, + }; + + if (argc<4) { + usage(); + return -1; + } + + outgoing_len=sizeof(struct afp_server_mount_request)+1; + req = (void *) outgoing_buffer+1; + memset(outgoing_buffer,0,outgoing_len); + outgoing_buffer[0]=AFP_SERVER_COMMAND_MOUNT; + req->url.port=548; + req->map=AFP_MAPPING_UNKNOWN; + + while(1) { + optnum++; + c = getopt_long(argc,argv,"a:u:m:o:p:v:V:", + long_options,&option_index); + if (c==-1) break; + switch(c) { + case 'a': + if (strcmp(optarg,"guest")==0) + uam_mask=UAM_NOUSERAUTHENT; + else + uam_mask=uam_string_to_bitmap(optarg); + break; + case 'm': + req->map=map_string_to_num(optarg); + break; + case 'u': + snprintf(req->url.username,AFP_MAX_USERNAME_LEN,"%s",optarg); + break; + case 'o': + req->url.port=strtol(optarg,NULL,10); + break; + case 'p': + snprintf(req->url.password,AFP_MAX_PASSWORD_LEN,"%s",optarg); + break; + case 'V': + snprintf(req->url.volpassword,9,"%s",optarg); + break; + case 'v': + req->url.requested_version=strtol(optarg,NULL,10); + break; + } + } + + if (strcmp(req->url.password, "-") == 0) { + char *p = getpass("AFP Password: "); + if (p) + snprintf(req->url.password,AFP_MAX_PASSWORD_LEN,"%s",p); + } + if (strcmp(req->url.volpassword, "-") == 0) { + char *p = getpass("Password for volume: "); + if (p) + snprintf(req->url.volpassword,9,"%s",p); + } + + optnum=optind+1; + if (optnum>=argc) { + printf("No volume or mount point specified\n"); + return -1; + } + if (sscanf(argv[optnum++],"%[^':']:%[^':']", + req->url.servername,req->url.volumename)!=2) { + printf("Incorrect server:volume specification\n"); + return -1; + } + if (uam_mask==0) { + printf("Unknown UAM\n"); + return -1; + } + + req->uam_mask=uam_mask; + req->volume_options=DEFAULT_MOUNT_FLAGS; + + if (optnum>=argc) { + printf("No mount point specified\n"); + return -1; + } + + snprintf(req->mountpoint,255,"%s",argv[optnum++]); + + + return 0; +} + +static void mount_afp_usage(void) +{ + printf("Usage:\n mount_afp [-o volpass=password] \n"); +} + +static int handle_mount_afp(int argc, char * argv[]) +{ + struct afp_server_mount_request * req = (void *) outgoing_buffer+1; + unsigned int uam_mask=default_uams_mask(); + char * urlstring, * mountpoint; + char * volpass = NULL; + int readonly=0; + + if (argc<2) { + mount_afp_usage(); + return -1; + } + if (strncmp(argv[1],"-o",2)==0) { + char * p = argv[2], *q; + char command[256]; + struct passwd * passwd; + struct group * group; + + do { + memset(command,0,256); + + if ((q=strchr(p,','))) + strncpy(command,p,(q-p)); + else + strcpy(command,p); + + if (strncmp(command,"volpass=",8)==0) { + p+=8; + volpass=p; + } else if (strncmp(command,"user=",5)==0) { + p=command+5; + if ((passwd=getpwnam(p))==NULL) { + printf("Unknown user %s\n",p); + return -1; + } + uid=passwd->pw_uid; + if (geteuid()!=uid) + changeuid=1; + } else if (strncmp(command,"group=",6)==0) { + p=command+6; + if ((group=getgrnam(p))==NULL) { + printf("Unknown group %s\n",p); + return -1; + } + gid=group->gr_gid; + changegid=1; + } else if (strcmp(command,"rw")==0) { + /* Don't do anything */ + } else if (strcmp(command,"ro")==0) { + readonly=1; + } else { + printf("Unknown option %s, skipping\n",command); + } + + + if (q) p=q+1; + else p=NULL; + + } while (p); + + urlstring=argv[3]; + mountpoint=argv[4]; + } else { + urlstring=argv[1]; + mountpoint=argv[2]; + } + + + outgoing_len=sizeof(struct afp_server_mount_request)+1; + memset(outgoing_buffer,0,outgoing_len); + + afp_default_url(&req->url); + + req->changeuid=changeuid; + + req->volume_options|=DEFAULT_MOUNT_FLAGS; + if (readonly) req->volume_options |= VOLUME_EXTRA_FLAGS_READONLY; + req->uam_mask=uam_mask; + + outgoing_buffer[0]=AFP_SERVER_COMMAND_MOUNT; + req->map=AFP_MAPPING_UNKNOWN; + snprintf(req->mountpoint,255,"%s",mountpoint); + if (afp_parse_url(&req->url,urlstring,0) !=0) + { + printf("Could not parse URL\n"); + return -1; + } + if (strcmp(req->url.password,"-")==0) { + char *p = getpass("AFP Password: "); + if (p) + snprintf(req->url.password,AFP_MAX_PASSWORD_LEN,"%s",p); + } + + if (volpass && (strcmp(volpass,"-")==0)) { + volpass = getpass("Password for volume: "); + } + if (volpass) + snprintf(req->url.volpassword,9,"%s",volpass); + + return 0; +} + +static int prepare_buffer(int argc, char * argv[]) +{ + + if (argc<2) { + usage(); + return -1; + } + if (strncmp(argv[1],"mount",5)==0) { + return do_mount(argc,argv); + } else if (strncmp(argv[1],"resume",6)==0) { + return do_resume(argc,argv); + } else if (strncmp(argv[1],"suspend",7)==0) { + return do_suspend(argc,argv); + + } else if (strncmp(argv[1],"status",6)==0) { + return do_status(argc,argv); + + } else if (strncmp(argv[1],"unmount",7)==0) { + return do_unmount(argc,argv); + } else if (strncmp(argv[1],"exit",4)==0) { + return do_exit(argc,argv); + + } else { + usage(); + return -1; + } + + return 0; +} + + +int read_answer(int sock) { + int len=0, expected_len=0, packetlen; + char incoming_buffer[MAX_CLIENT_RESPONSE]; + char toprint[MAX_CLIENT_RESPONSE+200]; + struct timeval tv; + fd_set rds,ords; + int ret; + struct afp_server_response * answer = (void *) incoming_buffer; + + memset(incoming_buffer,0,MAX_CLIENT_RESPONSE); + + FD_ZERO(&rds); + FD_SET(sock,&rds); + while (1) { + tv.tv_sec=30; tv.tv_usec=0; + ords=rds; + ret=select(sock+1,&ords,NULL,NULL,&tv); + if (ret==0) { + printf("No response from server\n"); + return -1; + } + if (FD_ISSET(sock,&ords)) { + packetlen=read(sock,incoming_buffer+len,MAX_CLIENT_RESPONSE-len); + if (packetlen==0) { + printf("Dropped connection\n"); + goto done; + } + if (len==0) { + expected_len=((struct afp_server_response *) incoming_buffer)->len; + } + len+=packetlen; + if (len==expected_len+sizeof(struct afp_server_response)) + + goto done; + if (ret<0) goto error; + + } + } + +done: + memset(toprint,0,MAX_CLIENT_RESPONSE+200); + snprintf(toprint,MAX_CLIENT_RESPONSE+200,"%s",incoming_buffer+sizeof(*answer)); + printf(toprint); + return ((struct afp_server_response *) incoming_buffer)->result; + + return 0; +error: + return -1; +} + +int main(int argc, char *argv[]) +{ + int sock; + int ret; + struct afp_volume volume; + thisbin=argv[0]; + + uid=((unsigned int) geteuid()); + + volume.server=NULL; + + if (strstr(argv[0],"mount_afp")) { + if (handle_mount_afp(argc,argv)<0) + return -1; + } + else if (prepare_buffer(argc,argv)<0) + return -1; + + if ((sock=daemon_connect()) < 0) + return -1; + + send_command(sock,outgoing_buffer,outgoing_len); + + + ret=read_answer(sock); + return ret; +} + diff -Nru afpfs-ng-0.8.1/.pc/build-error-fixes.patch/fuse/commands.c afpfs-ng-0.8.1/.pc/build-error-fixes.patch/fuse/commands.c --- afpfs-ng-0.8.1/.pc/build-error-fixes.patch/fuse/commands.c 1970-01-01 00:00:00.000000000 +0000 +++ afpfs-ng-0.8.1/.pc/build-error-fixes.patch/fuse/commands.c 2008-03-08 16:06:25.000000000 +0000 @@ -0,0 +1,691 @@ +/* + * commands.c + * + * Copyright (C) 2006 Alex deVries + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "afp.h" +#include "dsi.h" +#include "afp_server.h" +#include "utils.h" +#include "daemon.h" +#include "uams_def.h" +#include "codepage.h" +#include "libafpclient.h" +#include "map_def.h" +#include "fuse_int.h" +#include "fuse_error.h" +#include "fuse_internal.h" + +#ifdef __linux +#define FUSE_DEVICE "/dev/fuse" +#else +#define FUSE_DEVICE "/dev/fuse0" +#endif + + +static int fuse_log_method=LOG_METHOD_SYSLOG; + +void trigger_exit(void); + +static struct fuse_client * client_base = NULL; + +struct afp_volume * global_volume; + +static int volopen(struct fuse_client * c, struct afp_volume * volume); +static int process_command(struct fuse_client * c); +static struct afp_volume * mount_volume(struct fuse_client * c, + struct afp_server * server, char * volname, char * volpassword) ; + +void fuse_set_log_method(int new_method) +{ + fuse_log_method=new_method; +} + + +static int remove_client(struct fuse_client * toremove) +{ + struct fuse_client * c, * prev=NULL; + + for (c=client_base;c;c=c->next) { + if (c==toremove) { + if (!prev) client_base=NULL; + else prev->next=toremove->next; + free(toremove); + toremove=NULL; + return 0; + } + prev=c; + } + return -1; +} + +static int fuse_add_client(int fd) +{ + struct fuse_client * c, *newc; + + if ((newc=malloc(sizeof(*newc)))==NULL) goto error; + + + memset(newc,0,sizeof(*newc)); + newc->fd=fd; + newc->next=NULL; + if (client_base==NULL) client_base=newc; + else { + for (c=client_base;c->next;c=c->next); + c->next=newc; + + } + return 0; +error: + return -1; +} + +static int fuse_process_client_fds(fd_set * set, int max_fd) +{ + + struct fuse_client * c; + + for (c=client_base;c;c=c->next) { + if (FD_ISSET(c->fd,set)) { + if (process_command(c)<0) return -1; + return 1; + } + } + return 0; + +} + +static int fuse_scan_extra_fds(int command_fd, fd_set *set, int * max_fd) +{ + + struct sockaddr_un new_addr; + socklen_t new_len = sizeof(struct sockaddr_un); + int new_fd; + + + + if (FD_ISSET(command_fd,set)) { + new_fd=accept(command_fd,(struct sockaddr *) &new_addr,&new_len); + if (new_fd>=0) { + fuse_add_client(new_fd); + FD_SET(new_fd,set); + if ((new_fd+1) > *max_fd) *max_fd=new_fd+1; + } + } + + switch (fuse_process_client_fds(set,*max_fd)) { + case -1: + { + int i; + FD_CLR(new_fd,set); + for (i=*max_fd;i>=0;i--) + if (FD_ISSET(i,set)) { + *max_fd=i; + break; + } + } + + (*max_fd)++; + close(new_fd); + goto out; + case 1: + goto out; + } + /* unknown fd */ + sleep(10); + + return 0; + +out: + return 1; +} + +static void fuse_log_for_client(void * priv, + enum loglevels loglevel, int logtype, const char *message) { + int len = 0; + struct fuse_client * c = priv; + + if (c) { + len = strlen(c->client_string); + snprintf(c->client_string+len, + MAX_CLIENT_RESPONSE-len, + message); + } else { + + if (fuse_log_method & LOG_METHOD_SYSLOG) + syslog(LOG_INFO, "%s", message); + if (fuse_log_method & LOG_METHOD_STDOUT) + printf("%s",message); + } + +} + +struct start_fuse_thread_arg { + struct afp_volume * volume; + struct fuse_client * client; + int wait; + int fuse_result; + int fuse_errno; + int changeuid; +}; + +static void * start_fuse_thread(void * other) +{ + int fuseargc=0; + const char *fuseargv[200]; +#define mountstring_len (AFP_SERVER_NAME_LEN+1+AFP_VOLUME_NAME_LEN+1) + char mountstring[mountstring_len]; + struct start_fuse_thread_arg * arg = other; + struct afp_volume * volume = arg->volume; + struct fuse_client * c = arg->client; + struct afp_server * server = volume->server; + + /* Check to see if we have permissions to access the mountpoint */ + + snprintf(mountstring,mountstring_len,"%s:%s", + server->server_name_printable, + volume->volume_name_printable); + fuseargc=0; + fuseargv[0]=mountstring; + fuseargc++; + fuseargv[1]=volume->mountpoint; + fuseargc++; + if (get_debug_mode()) { + fuseargv[fuseargc]="-d"; + fuseargc++; + } else { + fuseargv[fuseargc]="-f"; + fuseargc++; + } + + if (arg->changeuid) { + fuseargv[fuseargc]="-o"; + fuseargc++; + fuseargv[fuseargc]="allow_other"; + fuseargc++; + } + + +/* #ifdef USE_SINGLE_THREAD */ + fuseargv[fuseargc]="-s"; + fuseargc++; +/* +#endif +*/ + global_volume=volume; + + arg->fuse_result= + afp_register_fuse(fuseargc, (char **) fuseargv,volume); + + arg->fuse_errno=errno; + + arg->wait=0; + pthread_cond_signal(&volume->startup_condition_cond); + + log_for_client((void *) c,AFPFSD,LOG_WARNING, + "Unmounting volume %s from %s\n", + volume->volume_name_printable, + volume->mountpoint); + + return NULL; +} + +static int volopen(struct fuse_client * c, struct afp_volume * volume) +{ + char mesg[1024]; + unsigned int l = 0; + memset(mesg,0,1024); + int rc=afp_connect_volume(volume,volume->server,mesg,&l,1024); + + log_for_client((void *) c,AFPFSD,LOG_ERR,mesg); + + return rc; + +} + + +static unsigned char process_suspend(struct fuse_client * c) +{ + struct afp_server_suspend_request * req =(void *)c->incoming_string+1; + struct afp_server * s; + + /* Find the server */ + if ((s=find_server_by_name(req->server_name))==NULL) { + log_for_client((void *) c,AFPFSD,LOG_ERR, + "%s is an unknown server\n",req->server_name); + return AFP_SERVER_RESULT_ERROR; + } + + if (afp_zzzzz(s)) + return AFP_SERVER_RESULT_ERROR; + + loop_disconnect(s); + + s->connect_state=SERVER_STATE_DISCONNECTED; + log_for_client((void *) c,AFPFSD,LOG_NOTICE, + "Disconnected from %s\n",req->server_name); + return AFP_SERVER_RESULT_OKAY; +} + + +static int afp_server_reconnect_loud(struct fuse_client * c, struct afp_server * s) +{ + char mesg[1024]; + unsigned int l = 2040; + int rc; + + rc=afp_server_reconnect(s,mesg,&l,l); + + if (rc) + log_for_client((void *) c,AFPFSD,LOG_ERR, + "%s",mesg); + return rc; + + +} + + +static unsigned char process_resume(struct fuse_client * c) +{ + struct afp_server_resume_request * req =(void *) c->incoming_string+1; + struct afp_server * s; + + /* Find the server */ + if ((s=find_server_by_name(req->server_name))==NULL) { + log_for_client((void *) c,AFPFSD,LOG_ERR, + "%s is an unknown server\n",req->server_name); + return AFP_SERVER_RESULT_ERROR; + } + + if (afp_server_reconnect_loud(c,s)) + { + log_for_client((void *) c,AFPFSD,LOG_ERR, + "Unable to reconnect to %s\n",req->server_name); + return AFP_SERVER_RESULT_ERROR; + } + log_for_client((void *) c,AFPFSD,LOG_NOTICE, + "Resumed connection to %s\n",req->server_name); + + return AFP_SERVER_RESULT_OKAY; + +} + +static unsigned char process_unmount(struct fuse_client * c) +{ + struct afp_server_unmount_request * req; + struct afp_server * s; + struct afp_volume * v; + int j=0; + + req=(void *) c->incoming_string+1; + + for (s=get_server_base();s;s=s->next) { + for (j=0;jnum_volumes;j++) { + v=&s->volumes[j]; + if (strcmp(v->mountpoint,req->mountpoint)==0) { + goto found; + } + + } + } + goto notfound; +found: + if (v->mounted != AFP_VOLUME_MOUNTED ) { + log_for_client((void *) c,AFPFSD,LOG_NOTICE, + "%s was not mounted\n",v->mountpoint); + return AFP_SERVER_RESULT_ERROR; + } + + afp_unmount_volume(v); + + return AFP_SERVER_RESULT_OKAY; +notfound: + log_for_client((void *)c,AFPFSD,LOG_WARNING, + "afpfs-ng doesn't have anything mounted on %s.\n",req->mountpoint); + return AFP_SERVER_RESULT_ERROR; + + +} + +static unsigned char process_ping(struct fuse_client * c) +{ + log_for_client((void *)c,AFPFSD,LOG_INFO, + "Ping!\n"); + return AFP_SERVER_RESULT_OKAY; +} + +static unsigned char process_exit(struct fuse_client * c) +{ + log_for_client((void *)c,AFPFSD,LOG_INFO, + "Exiting\n"); + trigger_exit(); + return AFP_SERVER_RESULT_OKAY; +} + +static unsigned char process_status(struct fuse_client * c) +{ + struct afp_server * s; + + char text[40960]; + int len=40960; + + if ((c->incoming_size + 1)< sizeof(struct afp_server_status_request)) + return AFP_SERVER_RESULT_ERROR; + + afp_status_header(text,&len); + + log_for_client((void *)c,AFPFSD,LOG_INFO,text); + + s=get_server_base(); + + for (s=get_server_base();s;s=s->next) { + afp_status_server(s,text,&len); + log_for_client((void *)c,AFPFSD,LOG_DEBUG,text); + } + + return AFP_SERVER_RESULT_OKAY; + +} + +static int process_mount(struct fuse_client * c) +{ + struct afp_server_mount_request * req; + struct afp_server * s=NULL; + struct afp_volume * volume; + struct afp_connection_request conn_req; + int ret; + struct stat lstat; + + if ((c->incoming_size-1) < sizeof(struct afp_server_mount_request)) + goto error; + + req=(void *) c->incoming_string+1; + + /* Todo should check the existance and perms of the mount point */ + + if ((ret=access(req->mountpoint,X_OK))!=0) { + log_for_client((void *)c,AFPFSD,LOG_DEBUG, + "Incorrect permissions on mountpoint %s: %s\n", + req->mountpoint, strerror(errno)); + + goto error; + } + + if (stat(FUSE_DEVICE,&lstat)) { + printf("Could not find %s\n",FUSE_DEVICE); + goto error; + } + + if (access(FUSE_DEVICE,R_OK | W_OK )!=0) { + log_for_client((void *)c, AFPFSD,LOG_NOTICE, + "Incorrect permissions on %s, mode of device" + " is %o, uid/gid is %d/%d. But your effective " + "uid/gid is %d/%d\n", + FUSE_DEVICE,lstat.st_mode, lstat.st_uid, + lstat.st_gid, + geteuid(),getegid()); + goto error; + } + + log_for_client((void *)c,AFPFSD,LOG_NOTICE, + "Mounting %s from %s on %s\n", + (char *) req->url.servername, + (char *) req->url.volumename,req->mountpoint); + + memset(&conn_req,0,sizeof(conn_req)); + + conn_req.url=req->url; + conn_req.uam_mask=req->uam_mask; + + if ((s=afp_server_full_connect(c,&conn_req))==NULL) { + signal_main_thread(); + goto error; + } + + if ((volume=mount_volume(c,s,req->url.volumename, + req->url.volpassword))==NULL) { + goto error; + } + + volume->extra_flags|=req->volume_options; + + volume->mapping=req->map; + afp_detect_mapping(volume); + + snprintf(volume->mountpoint,255,req->mountpoint); + + /* Create the new thread and block until we get an answer back */ + { + pthread_mutex_t mutex; + struct timespec ts; + struct timeval tv; + int ret; + struct start_fuse_thread_arg arg; + memset(&arg,0,sizeof(arg)); + arg.client = c; + arg.volume = volume; + arg.wait = 1; + arg.changeuid=req->changeuid; + + gettimeofday(&tv,NULL); + ts.tv_sec=tv.tv_sec; + ts.tv_sec+=5; + ts.tv_nsec=tv.tv_usec*1000; + pthread_mutex_init(&mutex,NULL); + pthread_cond_init(&volume->startup_condition_cond,NULL); + + /* Kickoff a thread to see how quickly it exits. If + * it exits quickly, we have an error and it failed. */ + + pthread_create(&volume->thread,NULL,start_fuse_thread,&arg); + + if (arg.wait) ret = pthread_cond_timedwait( + &volume->startup_condition_cond,&mutex,&ts); + + report_fuse_errors(c); + + switch (arg.fuse_result) { + case 0: + if (volume->mounted==AFP_VOLUME_UNMOUNTED) { + /* Try and discover why */ + switch(arg.fuse_errno) { + case ENOENT: + log_for_client((void *)c,AFPFSD,LOG_ERR, + "Permission denied, maybe a problem with the fuse device or mountpoint?\n"); + break; + default: + log_for_client((void *)c,AFPFSD,LOG_ERR, + "Mounting of volume %s of server %s failed.\n", + volume->volume_name_printable, + volume->server->server_name_printable); + } + goto error; + } else { + log_for_client((void *)c,AFPFSD,LOG_NOTICE, + "Mounting of volume %s of server %s succeeded.\n", + volume->volume_name_printable, + volume->server->server_name_printable); + return 0; + } + break; + case ETIMEDOUT: + log_for_client((void *)c,AFPFSD,LOG_NOTICE, + "Still trying.\n"); + return 0; + break; + default: + volume->mounted=AFP_VOLUME_UNMOUNTED; + log_for_client((void *)c,AFPFSD,LOG_NOTICE, + "Unknown error %d, %d.\n", + arg.fuse_result,arg.fuse_errno); + goto error; + } + + } + return AFP_SERVER_RESULT_OKAY; +error: + if ((s) && (!something_is_mounted(s))) { + afp_server_remove(s); + } + signal_main_thread(); + return AFP_SERVER_RESULT_ERROR; +} + + +static void * process_command_thread(void * other) +{ + + struct fuse_client * c = other; + int ret=0; + char tosend[sizeof(struct afp_server_response) + MAX_CLIENT_RESPONSE]; + struct afp_server_response response; + + + switch(c->incoming_string[0]) { + case AFP_SERVER_COMMAND_MOUNT: + ret=process_mount(c); + break; + case AFP_SERVER_COMMAND_STATUS: + ret=process_status(c); + break; + case AFP_SERVER_COMMAND_UNMOUNT: + ret=process_unmount(c); + break; + case AFP_SERVER_COMMAND_SUSPEND: + ret=process_suspend(c); + break; + case AFP_SERVER_COMMAND_RESUME: + ret=process_resume(c); + break; + case AFP_SERVER_COMMAND_PING: + ret=process_ping(c); + break; + case AFP_SERVER_COMMAND_EXIT: + ret=process_exit(c); + break; + default: + log_for_client((void *)c,AFPFSD,LOG_ERR,"Unknown command\n"); + } + /* Send response */ + response.result=ret; + response.len=strlen(c->client_string); + + bcopy(&response,tosend,sizeof(response)); + bcopy(c->client_string,tosend+sizeof(response),response.len); + ret=write(c->fd,tosend,sizeof(response)+response.len); + if (ret<0) { + perror("Writing"); + } + + if ((!c) || (c->fd==0)) return NULL; + rm_fd_and_signal(c->fd); + close(c->fd); + remove_client(c); + + return NULL; + +} +static int process_command(struct fuse_client * c) +{ + int ret; + int fd; + + ret=read(c->fd,&c->incoming_string,AFP_CLIENT_INCOMING_BUF); + + if (ret<=0) { + perror("reading"); + goto out; + } + c->incoming_size=ret; + + pthread_t thread; + pthread_create(&thread,NULL,process_command_thread,c); + return 0; +out: + fd=c->fd; + c->fd=0; + remove_client(c); + close(fd); + rm_fd_and_signal(fd); + return 0; +} + + +static struct afp_volume * mount_volume(struct fuse_client * c, + struct afp_server * server, char * volname, char * volpassword) +{ + struct afp_volume * using_volume; + + using_volume = find_volume_by_name(server,volname); + + if (!using_volume) { + log_for_client((void *) c,AFPFSD,LOG_ERR, + "Volume %s does not exist on server %s.\n",volname, + server->server_name_printable); + if (server->num_volumes) { + char names[1024]; + afp_list_volnames(server,names,1024); + log_for_client((void *)c,AFPFSD,LOG_ERR, + "Choose from: %s\n",names); + } + goto error; + } + + if (using_volume->mounted==AFP_VOLUME_MOUNTED) { + log_for_client((void *)c,AFPFSD,LOG_ERR, + "Volume %s is already mounted on %s\n",volname, + using_volume->mountpoint); + goto error; + } + + if (using_volume->flags & HasPassword) { + bcopy(volpassword,using_volume->volpassword,AFP_VOLPASS_LEN); + if (strlen(volpassword)<1) { + log_for_client((void *) c,AFPFSD,LOG_ERR,"Volume password needed\n"); + goto error; + } + } else memset(using_volume->volpassword,0,AFP_VOLPASS_LEN); + + if (volopen(c,using_volume)) { + log_for_client((void *) c,AFPFSD,LOG_ERR,"Could not mount volume %s\n",volname); + goto error; + } + + using_volume->server=server; + + return using_volume; +error: + return NULL; +} + + +static struct libafpclient client = { + .unmount_volume = fuse_unmount_volume, + .log_for_client = fuse_log_for_client, + .forced_ending_hook =fuse_forced_ending_hook, + .scan_extra_fds = fuse_scan_extra_fds}; + +int fuse_register_afpclient(void) +{ + libafpclient_register(&client); + return 0; +} + + + diff -Nru afpfs-ng-0.8.1/.pc/build-error-fixes.patch/lib/afp_url.c afpfs-ng-0.8.1/.pc/build-error-fixes.patch/lib/afp_url.c --- afpfs-ng-0.8.1/.pc/build-error-fixes.patch/lib/afp_url.c 1970-01-01 00:00:00.000000000 +0000 +++ afpfs-ng-0.8.1/.pc/build-error-fixes.patch/lib/afp_url.c 2008-03-04 20:16:49.000000000 +0000 @@ -0,0 +1,368 @@ + +#include +#include +#include +#include +#include "afp.h" + +void afp_default_url(struct afp_url *url) +{ + memset(url,0,sizeof(*url)); + url->protocol=TCPIP; + url->port=548; +} + +static int check_servername (char * servername) +{ + if (strchr(servername,':')) return -1; + if (strchr(servername,'/')) return -1; + return 0; +} + +static int check_port(char * port) +{ + long long ret = strtol(port,NULL,10); + if ((ret<0) || (ret>32767)) return -1; + if (errno) { + printf("port error\n"); + return -1; + } + return 0; +} + +static int check_uamname(const char * uam) +{ + char * p; + for (p=uam;*p;p++) { + if (*p==' ') continue; + if ((*p<'A') || (*p>'z')) return -1; + } + return 0; +} + +static int check_username(const char * user) +{ + return 0; +} + +static int check_password(const char * pass) +{ + return 0; +} + +static void escape_string(char * string, char c) +{ + int i; char d; + int inescape=0; + char tmpstring[1024]; + char * p = tmpstring; + memset(tmpstring,0,1024); + + for (i=0;ipassword,'@'); + escape_string(url->username,':'); +} + + +void afp_print_url(struct afp_url * url) +{ + + printf("servername: %s\n" + "volumename: %s\n" + "path: %s\n" + "username: %s\n" + "password: %s\n" + "port: %d\n" + "uam name: %s\n", + url->servername, + url->volumename, + url->path, + url->username, + url->password, + url->port,url->uamname); + +} + +static char * escape_strrchr(const char * haystack, int c, const char *toescape) +{ + char * p; + if (strchr(toescape,c)==NULL) + return strrchr(haystack,c); + + if ((p=strrchr(haystack,c))==NULL) + return NULL; + + if (p==haystack) + return p; + + if (*(p-1)!=c) + return p; + + p-=2; + + return escape_strrchr(p,c,toescape); +} + +static char * escape_strchr(const char * haystack, int c, const char * toescape) +{ + char * p; + if (strchr(toescape,c)==NULL) + return strchr(haystack,c); + + if ((p=strchr(haystack,c))==NULL) + return NULL; + + if (p-haystack==strlen(haystack)) + return p; + + if (*(p+1)!=c) + return p; + + p+=2; + + return escape_strchr(p,c,toescape); +} + +int afp_parse_url(struct afp_url * url, const char * toparse, int verbose) +{ + char firstpart[255],secondpart[2048]; + char *p, *q; + int firstpartlen; + int skip_earliestpart=0; + int skip_secondpart=0; + char * lastchar; + + if (verbose) printf("Parsing %s\n",toparse); + + url->username[0]='\0'; + url->servername[0]='\0'; + url->uamname[0]='\0'; + url->password[0]='\0'; + url->volumename[0]='\0'; + url->path[0]='\0'; + + /* The most complex URL is: + + afp://user;AUTH=authType:password@server-name:port/volume-name/path + + where the optional parms are user, password, AUTH and port, so the + simplest is: + + afp://server-name/volume-name/path + + */ + + /* if there is a ://, make sure it is preceeded by afp */ + + if ((p=strstr(toparse,"://"))!=NULL) { + q=p-3; + if (pport=atoi(q))==0) { + if (verbose) printf("Port appears to be zero\n"); + return -1; + } + } + + snprintf(url->servername,strlen(p)+1,p); + if (check_servername(url->servername)) { + if (verbose) printf("This isn't a valid servername\n"); + return -1; + } + + if ((p==NULL) || ((strlen(p)+p-1)==lastchar)) { + /* afp://server */ + } + + if ((q) && ((strlen(q)+q-1)==lastchar)) { + /* afp://server:port */ + } + + + /* Earliest part */ + + if (skip_earliestpart) { + p+=strlen(p); + goto parse_secondpart; + } + p=firstpart; + + /* Now we're left with something like user[;AUTH=uamname][:password] */ + + /* Look for :password */ + + if ((q=escape_strrchr(p,':',":"))) { + *q='\0'; + q++; + snprintf(url->password,strlen(q)+1,q); + if (check_password(url->password)) { + if (verbose) printf("This isn't a valid passwd\n"); + return -1; + } + } + + /* Now we're down to user[;AUTH=uamname] */ + p=firstpart; + + if ((q=strstr(p,";AUTH="))) { + *q='\0'; + q+=6; + snprintf(url->uamname,strlen(q)+1,q); + if (check_uamname(url->uamname)) { + if (verbose) printf("This isn't a valid uamname\n"); + return -1; + } + } + + if (strlen(p)>0) { + snprintf(url->username,strlen(p)+1,p); + if (check_username(url->username)) { + if (verbose) printf("This isn't a valid username\n"); + return -1;; + } + } + + +parse_secondpart: + if (skip_secondpart) goto done; + if (strlen(secondpart)==0) goto done; + + if (secondpart[strlen(secondpart)]=='/') + secondpart[strlen(secondpart)]='\0'; + + p=secondpart; + if ((q=strchr(p,'/'))) { + *q='\0'; + q++; + } + snprintf(url->volumename,strlen(p)+1,p); + + + if (q) { + url->path[0]='/'; + snprintf(url->path+1,strlen(q)+1,q); + } + +done: + escape_url(url); + if (verbose) printf("Successful parsing of URL\n"); + return 0; +} + + +int afp_url_validate(char * url_string, struct afp_url * valid_url) +{ + struct afp_url new_url; + + if (afp_parse_url(&new_url, url_string,0)) { + printf("url doesn't parse\n"); + goto error; + } + +#if BROKEN + + if (new_url.protocol!=valid_url->protocol) { + printf("protocol doesn't match, I got %d when I expected %d\n", + new_url.protocol,valid_url->protocol); + goto error; + } +#endif + + if (strcmp(new_url.username, valid_url->username)!=0) { + printf("username doesn't match, I got %s when I should have received %s\n",new_url.username, valid_url->username); + goto error; + } + if (strcmp(new_url.uamname, valid_url->uamname)!=0) { + printf("uamname doesn't match, I got %s when I should have received %s\n",new_url.uamname, valid_url->uamname); + goto error; + } + + if (strcmp(new_url.password, valid_url->password)!=0) { + printf("password doesn't match, I got %s when I should have received %s\n",new_url.password, valid_url->password); + goto error; + } + + if (strcmp(new_url.servername, valid_url->servername)!=0) { + printf("servername doesn't match, I got %s when I should have received %s\n",new_url.servername, valid_url->servername); + goto error; + } + + if (strcmp(new_url.volumename, valid_url->volumename)!=0) { + printf("volumename doesn't match, I got %s when I should have received %s\n",new_url.volumename, valid_url->volumename); + goto error; + } + return 0; +error: + return -1; +} + + diff -Nru afpfs-ng-0.8.1/.pc/header-path-fix.patch/include/afp.h afpfs-ng-0.8.1/.pc/header-path-fix.patch/include/afp.h --- afpfs-ng-0.8.1/.pc/header-path-fix.patch/include/afp.h 1970-01-01 00:00:00.000000000 +0000 +++ afpfs-ng-0.8.1/.pc/header-path-fix.patch/include/afp.h 2008-03-08 16:08:18.000000000 +0000 @@ -0,0 +1,533 @@ + +#ifndef _AFP_H_ +#define _AFP_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define AFPFS_VERSION "0.8.1" + +/* This is the maximum AFP version this library supports */ +#define AFP_MAX_SUPPORTED_VERSION 32 + +/* afp_url is used to pass locations around */ +struct afp_url { + enum {TCPIP,AT} protocol; + char username[AFP_MAX_USERNAME_LEN]; + char uamname[50]; + char password[AFP_MAX_PASSWORD_LEN]; + char servername[AFP_SERVER_NAME_UTF8_LEN]; + int port; + char volumename[AFP_VOLUME_NAME_UTF8_LEN]; + char path[AFP_MAX_PATH]; + + int requested_version; + char zone[AFP_ZONE_LEN]; /* Only used for Appletalk */ + char volpassword[9];; +}; + +struct afp_token { + unsigned int length; + char data[AFP_TOKEN_MAX_LEN]; +}; + +#define SERVER_MAX_VERSIONS 10 +#define SERVER_MAX_UAMS 10 + +struct afp_rx_buffer { + unsigned int size; + unsigned int maxsize; + char * data; + int errorcode; +}; + + +struct afp_file_info { + unsigned short attributes; + unsigned int did; + unsigned int creation_date; + unsigned int modification_date; + unsigned int backup_date; + unsigned int fileid; + unsigned short offspring; + char sync; + char finderinfo[32]; + char name[AFP_MAX_PATH]; + char basename[AFP_MAX_PATH]; + char translated_name[AFP_MAX_PATH]; + struct afp_unixprivs unixprivs; + unsigned int accessrights; + struct afp_file_info * next; + struct afp_file_info * largelist_next; + unsigned char isdir; + unsigned long long size; + unsigned short resourcesize; + unsigned int resource; + unsigned short forkid; + struct afp_icon * icon; + int eof; +}; + + +#define VOLUME_EXTRA_FLAGS_VOL_CHMOD_KNOWN 0x1 +#define VOLUME_EXTRA_FLAGS_VOL_CHMOD_BROKEN 0x2 +#define VOLUME_EXTRA_FLAGS_SHOW_APPLEDOUBLE 0x4 +#define VOLUME_EXTRA_FLAGS_VOL_SUPPORTS_UNIX 0x8 +#define VOLUME_EXTRA_FLAGS_NO_LOCKING 0x10 +#define VOLUME_EXTRA_FLAGS_IGNORE_UNIXPRIVS 0x20 +#define VOLUME_EXTRA_FLAGS_READONLY 0x40 + +#define AFP_VOLUME_UNMOUNTED 0 +#define AFP_VOLUME_MOUNTED 1 +#define AFP_VOLUME_UNMOUNTING 2 + +struct afp_volume { + unsigned short volid; + char flags; /* This is from afpGetSrvrParms */ + unsigned short attributes; /* This is from VolOpen */ + unsigned short signature; /* This is fixed or variable */ + unsigned int creation_date; + unsigned int modification_date; + unsigned int backup_date; + struct statvfs stat; + unsigned char mounted; + char mountpoint[255]; + struct afp_server * server; + char volume_name[AFP_VOLUME_NAME_LEN]; + char volume_name_printable[AFP_VOLUME_NAME_UTF8_LEN]; + unsigned short dtrefnum; + char volpassword[AFP_VOLPASS_LEN]; + unsigned int extra_flags; /* This is an afpfs-ng specific field */ + + /* Our directory ID cache */ + struct did_cache_entry * did_cache_base; + pthread_mutex_t did_cache_mutex; + + /* Our journal of open forks */ + struct afp_file_info * open_forks; + pthread_mutex_t open_forks_mutex; + + /* Used to trigger startup */ + pthread_cond_t startup_condition_cond; + + struct { + uint64_t hits; + uint64_t misses; + uint64_t expired; + uint64_t force_removed; + } did_cache_stats; + + void * priv; /* This is a private structure for fuse/cmdline, etc */ + pthread_t thread; /* This is the per-volume thread */ + + int mapping; + +}; + +#define SERVER_STATE_CONNECTED 1 +#define SERVER_STATE_DISCONNECTED 2 + +enum server_type{ + AFPFS_SERVER_TYPE_UNKNOWN, + AFPFS_SERVER_TYPE_NETATALK, + AFPFS_SERVER_TYPE_AIRPORT, + AFPFS_SERVER_TYPE_MACINTOSH, +}; + +#define is_netatalk(x) ( (x)->machine_type == AFPFS_SERVER_TYPE_NETATALK ) +#define is_airport(x) ( (x)->machine_type == AFPFS_SERVER_TYPE_AIRPORT ) +#define is_macintosh(x) ( (x)->machine_type == AFPFS_SERVER_TYPE_MACINTOSH ) + + + +struct afp_versions { + char *av_name; + int av_number; +}; +extern struct afp_versions afp_versions[]; + +struct afp_server { + + /* Our buffer sizes */ + unsigned int tx_quantum; + unsigned int rx_quantum; + + unsigned int tx_delay; + + /* Connection information */ + struct sockaddr_in address; + int fd; + + /* Some stats, for information only */ + struct { + uint64_t runt_packets; + uint64_t incoming_dsi; + uint64_t rx_bytes; + uint64_t tx_bytes; + uint64_t requests_pending; + } stats; + + /* General information */ + char server_name[AFP_SERVER_NAME_LEN]; + char server_name_utf8[AFP_SERVER_NAME_UTF8_LEN]; + char server_name_printable[AFP_SERVER_NAME_UTF8_LEN]; + + char machine_type[17]; + char icon[256]; + char signature[16]; + unsigned short flags; + int connect_state; + enum server_type server_type; + + /* This is the time we connected */ + time_t connect_time; + + /* UAMs */ + unsigned int supported_uams; + unsigned int using_uam; + + /* Authentication */ + char username[AFP_MAX_USERNAME_LEN]; + char password[AFP_MAX_PASSWORD_LEN]; + + /* Session */ + struct afp_token token; + char need_resume; + + /* Versions */ + unsigned char requested_version; + unsigned char versions[SERVER_MAX_VERSIONS]; + struct afp_versions *using_version; + + /* Volumes */ + unsigned char num_volumes; + struct afp_volume * volumes; + + void * dsi; + unsigned int exit_flag; + + /* Our DSI request queue */ + pthread_mutex_t requestid_mutex; + pthread_mutex_t request_queue_mutex; + unsigned short lastrequestid; + unsigned short expectedrequestid; + struct dsi_request * command_requests; + + + char loginmesg[200]; + char servermesg[200]; + char path_encoding; + + /* This is the data for the incoming buffer */ + char * incoming_buffer; + int data_read; + int bufsize; + + /* And this is for the outgoing queue */ + pthread_mutex_t send_mutex; + + /* This is for user mapping */ + struct passwd passwd; + unsigned int server_uid, server_gid; + int server_gid_valid; + + struct afp_server *next; + + /* These are for DSI attention packets */ + unsigned int attention_quantum; + unsigned int attention_len; + char * attention_buffer; + +}; + +struct afp_extattr_info { + unsigned int maxsize; + unsigned int size; + char data[1024]; +}; +struct afp_comment { + unsigned int maxsize; + unsigned int size; + char *data; +}; + +struct afp_icon { + unsigned int maxsize; + unsigned int size; + char *data; +}; + +#define AFP_DEFAULT_ATTENTION_QUANTUM 1024 + +void afp_unixpriv_to_stat(struct afp_file_info *fp, + struct stat *stat); + +int init_uams(void) ; + +unsigned int find_uam_by_name(const char * name); +char * uam_bitmap_to_string(unsigned int bitmap); + + +char * get_uam_names_list(void); + +unsigned int default_uams_mask(void); + +struct afp_volume * find_volume_by_name(struct afp_server * server, + const char * volname); + +struct afp_connection_request { + unsigned int uam_mask; + struct afp_url url; +}; + +void afp_default_url(struct afp_url *url); +int afp_parse_url(struct afp_url * url, const char * toparse, int verbose); +void afp_print_url(struct afp_url * url); +int afp_url_validate(char * url_string, struct afp_url * valid_url); + +int afp_list_volnames(struct afp_server * server, char * names, int max); + +/* User mapping */ +int afp_detect_mapping(struct afp_volume * volume); + +/* These are some functions that help with simple status text generation */ + +int afp_status_header(char * text, int * len); +int afp_status_server(struct afp_server * s,char * text, int * len); + + +struct afp_server * afp_server_full_connect(void * priv, struct afp_connection_request * req); + +void * just_end_it_now(void *other); +void add_fd_and_signal(int fd); +void loop_disconnect(struct afp_server *s); +void afp_wait_for_started_loop(void); + + +struct afp_versions * pick_version(unsigned char *versions, + unsigned char requested) ; +int pick_uam(unsigned int u1, unsigned int u2); + +int afp_server_login(struct afp_server *server, + char * mesg, unsigned int *l, unsigned int max); + + +int afp_dologin(struct afp_server *server, + unsigned int uam, char * username, char * passwd); + +void afp_free_server(struct afp_server **server); + +struct afp_server * afp_server_init(struct sockaddr_in * address); +int afp_get_address(void * priv, const char * hostname, unsigned int port, + struct sockaddr_in * address); + + +int afp_main_loop(int command_fd); +int afp_main_quick_startup(pthread_t * thread); + +int afp_server_destroy(struct afp_server *s) ; +int afp_server_reconnect(struct afp_server * s, char * mesg, + unsigned int *l, unsigned int max); +int afp_server_connect(struct afp_server *s, int full); + +struct afp_server * afp_server_complete_connection( + void * priv, + struct afp_server * server, + struct sockaddr_in * address, unsigned char * versions, + unsigned int uams, char * username, char * password, + unsigned int requested_version, unsigned int uam_mask); + +int afp_connect_volume(struct afp_volume * volume, struct afp_server * server, + char * mesg, unsigned int * l, unsigned int max); +int something_is_mounted(struct afp_server * server); + +int add_cache_entry(struct afp_file_info * file) ; +struct afp_file_info * get_cache_by_name(char * name); +struct afp_server * find_server_by_address(struct sockaddr_in * address); +struct afp_server * find_server_by_signature(char * signature); +struct afp_server * find_server_by_name(char * name); +int server_still_valid(struct afp_server * server); + + +struct afp_server * get_server_base(void); +int afp_server_remove(struct afp_server * server); + +int afp_unmount_volume(struct afp_volume * volume); +int afp_unmount_all_volumes(struct afp_server * server); + +#define volume_is_readonly(x) (((x)->attributes&kReadOnly) || \ + ((x)->extra_flags & VOLUME_EXTRA_FLAGS_READONLY)) + +int afp_opendt(struct afp_volume *volume, unsigned short * refnum); + +int afp_closedt(struct afp_server * server, unsigned short * refnum); + +int afp_getcomment(struct afp_volume *volume, unsigned int did, + const char * pathname, struct afp_comment * comment); + +int afp_addcomment(struct afp_volume *volume, unsigned int did, + const char * pathname, char * comment,uint64_t *size); + +int afp_geticon(struct afp_volume * volume, unsigned int filecreator, + unsigned int filetype, unsigned char icontype, + unsigned short length, struct afp_icon * icon); + +/* Things you want to do to a server */ + +int afp_getsrvrmsg(struct afp_server *server, unsigned short messagetype,unsigned char utf8, unsigned char block, char * mesg); + +int afp_login(struct afp_server *server, char * uaname, + char * userauthinfo, unsigned int userauthinfo_len, + struct afp_rx_buffer *rx); + +int afp_changepassword(struct afp_server *server, char * uaname, + char * userauthinfo, unsigned int userauthinfo_len, + struct afp_rx_buffer *rx); + +int afp_logincont(struct afp_server *server, unsigned short id, + char * userauthinfo, unsigned int userauthinfo_len, + struct afp_rx_buffer *rx); + +int afp_getsessiontoken(struct afp_server * server, int type, + unsigned int timestamp, struct afp_token *outgoing_token, + struct afp_token * incoming_token); + +int afp_getsrvrparms(struct afp_server *server); + +int afp_logout(struct afp_server *server,unsigned char wait); + +int afp_mapname(struct afp_server * server, unsigned char subfunction, + char * name, unsigned int * id); + +int afp_mapid(struct afp_server * server, unsigned char subfunction, + unsigned int id, char *name); + +int afp_getuserinfo(struct afp_server * server, int thisuser, + unsigned int userid, unsigned short bitmap, + unsigned int *newuid, unsigned int *newgid); + +int afp_zzzzz(struct afp_server *server); + +int afp_volopen(struct afp_volume * volume, + unsigned short bitmap, char * password); + +int afp_flush(struct afp_volume * volume); + +int afp_getfiledirparms(struct afp_volume *volume, unsigned int did, + unsigned int filebitmap, unsigned int dirbitmap, const char * pathname, + struct afp_file_info *fp); + +int afp_enumerate(struct afp_volume * volume, + unsigned int dirid, + unsigned int filebitmap, unsigned int dirbitmap, + unsigned short reqcount, + unsigned short startindex, + char * path, + struct afp_file_info ** file_p); + +int afp_enumerateext2(struct afp_volume * volume, + unsigned int dirid, + unsigned int filebitmap, unsigned int dirbitmap, + unsigned short reqcount, + unsigned long startindex, + char * path, + struct afp_file_info ** file_p); + +int afp_openfork(struct afp_volume * volume, + unsigned char forktype, + unsigned int dirid, + unsigned short accessmode, + char * filename, + struct afp_file_info *fp); + +int afp_read(struct afp_volume * volume, unsigned short forkid, + uint32_t offset, + uint32_t count, struct afp_rx_buffer * rx); + +int afp_readext(struct afp_volume * volume, unsigned short forkid, + uint64_t offset, + uint64_t count, struct afp_rx_buffer * rx); + +int afp_getvolparms(struct afp_volume * volume, unsigned short bitmap); + + +int afp_createdir(struct afp_volume * volume, unsigned int dirid, const char * pathname, unsigned int *did_p); + +int afp_delete(struct afp_volume * volume, + unsigned int dirid, char * pathname); + + +int afp_createfile(struct afp_volume * volume, unsigned char flag, + unsigned int did, char * pathname); + +int afp_write(struct afp_volume * volume, unsigned short forkid, + uint32_t offset, uint32_t reqcount, + char * data, uint32_t * written); + +int afp_writeext(struct afp_volume * volume, unsigned short forkid, + uint64_t offset, uint64_t reqcount, + char * data, uint64_t * written); + +int afp_flushfork(struct afp_volume * volume, unsigned short forkid); + +int afp_closefork(struct afp_volume * volume, unsigned short forkid); +int afp_setfileparms(struct afp_volume * volume, + unsigned int dirid, const char * pathname, unsigned short bitmap, + struct afp_file_info *fp); +int afp_setfiledirparms(struct afp_volume * volume, + unsigned int dirid, const char * pathname, unsigned short bitmap, + struct afp_file_info *fp); + +int afp_setdirparms(struct afp_volume * volume, + unsigned int dirid, const char * pathname, unsigned short bitmap, + struct afp_file_info *fp); + +int afp_volclose(struct afp_volume * volume); + + +int afp_setforkparms(struct afp_volume *volume, + unsigned short forkid, unsigned short bitmap, unsigned long len); + +int afp_byterangelock(struct afp_volume * volume, + unsigned char flag, + unsigned short forkid, + uint32_t offset, + uint32_t len, uint32_t *generated_offset); + +int afp_byterangelockext(struct afp_volume * volume, + unsigned char flag, + unsigned short forkid, + uint64_t offset, + uint64_t len, uint64_t *generated_offset); + +int afp_moveandrename(struct afp_volume *volume, + unsigned int src_did, + unsigned int dst_did, + char * src_path, char * dst_path, char *new_name); + +int afp_rename(struct afp_volume * volume, + unsigned int dirid, + char * path_from, char * path_to); + +int afp_listextattr(struct afp_volume * volume, + unsigned int dirid, unsigned short bitmap, + char * pathname, struct afp_extattr_info * info); + +/* This is a currently undocumented command */ +int afp_newcommand76(struct afp_volume * volume, unsigned int dlen, char * data); + +/* For debugging */ +char * afp_get_command_name(char code); + + +#endif diff -Nru afpfs-ng-0.8.1/.pc/.quilt_patches afpfs-ng-0.8.1/.pc/.quilt_patches --- afpfs-ng-0.8.1/.pc/.quilt_patches 1970-01-01 00:00:00.000000000 +0000 +++ afpfs-ng-0.8.1/.pc/.quilt_patches 2015-03-27 07:22:33.000000000 +0000 @@ -0,0 +1 @@ +debian/patches diff -Nru afpfs-ng-0.8.1/.pc/.quilt_series afpfs-ng-0.8.1/.pc/.quilt_series --- afpfs-ng-0.8.1/.pc/.quilt_series 1970-01-01 00:00:00.000000000 +0000 +++ afpfs-ng-0.8.1/.pc/.quilt_series 2015-03-27 07:22:33.000000000 +0000 @@ -0,0 +1 @@ +series diff -Nru afpfs-ng-0.8.1/.pc/.version afpfs-ng-0.8.1/.pc/.version --- afpfs-ng-0.8.1/.pc/.version 1970-01-01 00:00:00.000000000 +0000 +++ afpfs-ng-0.8.1/.pc/.version 2015-03-27 07:22:33.000000000 +0000 @@ -0,0 +1 @@ +2