int afp_unmount_volume(struct afp_volume * volume) { struct afp_server * server; if (volume==NULL) return -1; server=volume->server; if (volume->mounted != AFP_VOLUME_MOUNTED) { return -1; } volume->mounted=AFP_VOLUME_UNMOUNTING; /* close the volume */ afp_flush(volume); free_entire_did_cache(volume); remove_fork_list(volume); if (volume->dtrefnum) afp_closedt(server,volume->dtrefnum); volume->dtrefnum=0; if (libafpclient->unmount_volume) libafpclient->unmount_volume(volume); volume->mounted=AFP_VOLUME_UNMOUNTED; /* Figure out if this is the last volume of the server */ if (something_is_mounted(server)) return 0; /* Logout */ afp_logout(server,DSI_DONT_WAIT /* don't wait */); afp_server_remove(server); return -1; }
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); if ((afp_default_connection_request(&conn_req,&req->url))==-1) { log_for_client((void *)c,AFPFSD,LOG_ERR, "Unknown UAM"); return -1; } 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; }
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) { char loginmsg[AFP_LOGINMESG_LEN]; int using_uam; #define LOGIN_ERROR_MESG_LEN 1024 char mesg[LOGIN_ERROR_MESG_LEN]; unsigned int len=0; memset(loginmsg,0,AFP_LOGINMESG_LEN); server->requested_version=requested_version; memcpy(server->username,username,sizeof(server->username)); memcpy(server->password,password,sizeof(server->password)); add_fd_and_signal(server->fd); dsi_opensession(server); /* Figure out what version we're using */ if (((server->using_version= pick_version(versions,requested_version))==NULL)) { log_for_client(priv,AFPFSD,LOG_ERR, "Server cannot handle AFP version %d\n", requested_version); goto error; } using_uam=pick_uam(uams,uam_mask); if (using_uam==-1) { log_for_client(priv,AFPFSD,LOG_ERR, "Could not pick a matching UAM.\n"); goto error; } server->using_uam=using_uam; if (afp_server_login(server,mesg,&len,LOGIN_ERROR_MESG_LEN)) { log_for_client(priv,AFPFSD,LOG_ERR, "Login error: %s\n", mesg); goto error; } if (afp_getsrvrparms(server)) { log_for_client(priv,AFPFSD,LOG_ERR, "Could not get server parameters\n"); goto error; } /* If we haven't gotten a proper date back, so set it to the connect time. */ if (server->connect_time==3094168448) { struct timeval tv; gettimeofday(&tv,NULL); server->connect_time = tv.tv_sec; } afp_getsrvrmsg(server,AFPMESG_LOGIN, ((server->using_version->av_number>=30)?1:0), DSI_DEFAULT_TIMEOUT,loginmsg); /* block */ if (strlen(loginmsg)>0) log_for_client(priv,AFPFSD,LOG_NOTICE, "Login message: %s\n", loginmsg); memcpy(server->loginmesg,loginmsg, AFP_LOGINMESG_LEN); return server; error: afp_server_remove(server); return NULL; }
int fuse_mount(struct daemon_client * c, volumeid_t * volumeid) { 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; char * r; int response_result = AFP_SERVER_RESULT_OKAY; memset(&volumeid,0,sizeof(volumeid_t)); req=(void *) c->complete_packet; 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)); response_result=AFP_SERVER_RESULT_MOUNTPOINT_PERM; goto error; } if (stat(FUSE_DEVICE,&lstat)) { printf("Could not find %s\n",FUSE_DEVICE); response_result=AFP_SERVER_RESULT_MOUNTPOINT_NOEXIST; 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()); response_result=AFP_SERVER_RESULT_MOUNTPOINT_PERM; 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); if ((s=find_server_by_url(&req->url))==NULL) { log_for_client((void *) c,AFPFSD,LOG_ERR, "%s is an unknown server\n",req->url.servername); response_result=AFP_SERVER_RESULT_NOSERVER; goto error; } /* response_result could be set in command_sub_attach_volume as: * AFP_SERVER_RESULT_OKAY: * AFP_SERVER_RESULT_NOVOLUME: * AFP_SERVER_RESULT_ALREADY_MOUNTED: * AFP_SERVER_RESULT_VOLPASS_NEEDED: * AFP_SERVER_RESULT_ERROR_UNKNOWN: */ if ((volume=command_sub_attach_volume(c,s,req->url.volumename, req->url.volpassword,&response_result))==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 */ if (fuse_mount_thread(c,volume,req->changeuid)<0) goto error; response_result=AFP_SERVER_RESULT_OKAY; goto done; error: #if 0 if ((s) && (!something_is_mounted(s))) { afp_server_remove(s); } #endif done: signal_main_thread(); return response_result; }