예제 #1
0
파일: afp.c 프로젝트: 007/afpfs-ng
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;

}
예제 #2
0
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;
}
예제 #3
0
파일: server.c 프로젝트: Boxee/afpfs-ng
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;

}
예제 #4
0
파일: daemon_fuse.c 프로젝트: 007/afpfs-ng
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;
}