int _alpm_check_downloadspace(alpm_handle_t *handle, const char *cachedir,
		size_t num_files, off_t *file_sizes)
{
	alpm_list_t *mount_points;
	alpm_mountpoint_t *cachedir_mp;
	char resolved_cachedir[PATH_MAX];
	size_t j;
	int error = 0;

	/* resolve the cachedir path to ensure we check the right mountpoint. We
	 * handle failures silently, and continue to use the possibly unresolved
	 * path. */
	if(realpath(cachedir, resolved_cachedir) != NULL) {
		cachedir = resolved_cachedir;
	}

	mount_points = mount_point_list(handle);
	if(mount_points == NULL) {
		_alpm_log(handle, ALPM_LOG_ERROR, _("could not determine filesystem mount points\n"));
		return -1;
	}

	cachedir_mp = match_mount_point(mount_points, cachedir);
	if(cachedir_mp == NULL) {
		_alpm_log(handle, ALPM_LOG_ERROR, _("could not determine cachedir mount point %s\n"),
				cachedir);
		error = 1;
		goto finish;
	}

	if(cachedir_mp->fsinfo_loaded == MOUNT_FSINFO_UNLOADED) {
		if(mount_point_load_fsinfo(handle, cachedir_mp)) {
			error = 1;
			goto finish;
		}
	}

	/* there's no need to check for a R/O mounted filesystem here, as
	 * _alpm_filecache_setup will never give us a non-writable directory */

	/* round up the size of each file to the nearest block and accumulate */
	for(j = 0; j < num_files; j++) {
		cachedir_mp->max_blocks_needed += (file_sizes[j] + cachedir_mp->fsp.f_bsize + 1) /
			cachedir_mp->fsp.f_bsize;
	}

	if(check_mountpoint(handle, cachedir_mp)) {
		error = 1;
	}

finish:
	mount_point_list_free(mount_points);

	if(error) {
		RET_ERR(handle, ALPM_ERR_DISK_SPACE, -1);
	}

	return 0;
}
Exemple #2
0
int main( int argc, char *argv[] )
{		
	int res;
	PGconn *conn;
	struct fuse_args args = FUSE_ARGS_INIT( argc, argv );
	PgFuseOptions pgfuse;
	PgFuseData userdata;
	const char *value;
	
	memset( &pgfuse, 0, sizeof( pgfuse ) );
	pgfuse.multi_threaded = 1;
	pgfuse.block_size = DEFAULT_BLOCK_SIZE;
	
	if( fuse_opt_parse( &args, &pgfuse, pgfuse_opts, pgfuse_opt_proc ) == -1 ) {
		if( pgfuse.print_help ) {
			/* print our options */
			print_usage( basename( argv[0] ) );
			fflush( stdout );
			/* print options of FUSE itself */
			argv[1] = "-ho";
			argv[2] = "mountpoint";
			(void)dup2( STDOUT_FILENO, STDERR_FILENO ); /* force fuse help to stdout */
			fuse_main( 2, argv, &pgfuse_oper, NULL);
			exit( EXIT_SUCCESS );
		}
		if( pgfuse.print_version ) {
			printf( "%s\n", PGFUSE_VERSION );
			exit( EXIT_SUCCESS );
		}
		exit( EXIT_FAILURE );
	}
		
	if( pgfuse.conninfo == NULL ) {
		fprintf( stderr, "Missing Postgresql connection data\n" );
		fprintf( stderr, "See '%s -h' for usage\n", basename( argv[0] ) );
		exit( EXIT_FAILURE );
	}
		
	/* just test if the connection can be established, do the
	 * real connection in the fuse init function!
	 */
	conn = PQconnectdb( pgfuse.conninfo );
	if( PQstatus( conn ) != CONNECTION_OK ) {
		fprintf( stderr, "Connection to database failed: %s",
			PQerrorMessage( conn ) );
		PQfinish( conn );
		exit( EXIT_FAILURE );
	}

	/* test storage of timestamps (expecting uint64 as it is the
	 * standard for PostgreSQL 8.4 or newer). Otherwise bail out
	 * currently..
	 */

	value = PQparameterStatus( conn, "integer_datetimes" );
	if( value == NULL ) {
		fprintf( stderr, "PQ param integer_datetimes not available?\n"
		         "You use a too old version of PostgreSQL..can't continue.\n" );
		PQfinish( conn );
		exit( EXIT_FAILURE );
	}
	
	if( strcmp( value, "on" ) != 0 ) {
		fprintf( stderr, "Expecting UINT64 for timestamps, not doubles. You may use an old version of PostgreSQL (<8.4)\n"
		         "or PostgreSQL has been compiled with the deprecated compile option '--disable-integer-datetimes'\n" );
		PQfinish( conn );
		exit( EXIT_FAILURE );
	}

	openlog( basename( argv[0] ), LOG_PID, LOG_USER );	
		
	/* Compare blocksize given as parameter and blocksize in database */
	res = psql_get_block_size( conn, pgfuse.block_size );
	if( res < 0 ) {
		PQfinish( conn );
		exit( EXIT_FAILURE );
	}
	if( res != pgfuse.block_size ) {
		fprintf( stderr, "Blocksize parameter mismatch (is '%zu', in database we have '%zu') taking the later one!\n",
			pgfuse.block_size, (size_t)res );
		PQfinish( conn );
		exit( EXIT_FAILURE );
	}
	
	PQfinish( conn );

	/* check sanity of the mount point, remember it's permission and owner in
	 * case we want to inherit them or overrule them
	 */
	res = check_mountpoint( &pgfuse.mountpoint );
	if( res < 0 ) {
		/* something is fishy, bail out, check_mountpointed reported errors already */
		exit( EXIT_FAILURE );
	}
	
	memset( &userdata, 0, sizeof( PgFuseData ) );
	userdata.conninfo = pgfuse.conninfo;
	userdata.mountpoint = pgfuse.mountpoint;
	userdata.verbose = pgfuse.verbose;
	userdata.read_only = pgfuse.read_only;
	userdata.noatime = pgfuse.noatime;
	userdata.multi_threaded = pgfuse.multi_threaded;
	userdata.block_size = pgfuse.block_size;
	
	res = fuse_main( args.argc, args.argv, &pgfuse_oper, &userdata );
	
	closelog( );
	
	exit( res );
}
int _alpm_check_diskspace(alpm_handle_t *handle)
{
	alpm_list_t *mount_points, *i;
	alpm_mountpoint_t *root_mp;
	size_t replaces = 0, current = 0, numtargs;
	int error = 0;
	alpm_list_t *targ;
	alpm_trans_t *trans = handle->trans;

	numtargs = alpm_list_count(trans->add);
	mount_points = mount_point_list(handle);
	if(mount_points == NULL) {
		_alpm_log(handle, ALPM_LOG_ERROR, _("could not determine filesystem mount points\n"));
		return -1;
	}
	root_mp = match_mount_point(mount_points, handle->root);
	if(root_mp == NULL) {
		_alpm_log(handle, ALPM_LOG_ERROR, _("could not determine root mount point %s\n"),
				handle->root);
		error = 1;
		goto finish;
	}

	replaces = alpm_list_count(trans->remove);
	if(replaces) {
		numtargs += replaces;
		for(targ = trans->remove; targ; targ = targ->next, current++) {
			alpm_pkg_t *local_pkg;
			int percent = (current * 100) / numtargs;
			PROGRESS(handle, ALPM_PROGRESS_DISKSPACE_START, "", percent,
					numtargs, current);

			local_pkg = targ->data;
			calculate_removed_size(handle, mount_points, local_pkg);
		}
	}

	for(targ = trans->add; targ; targ = targ->next, current++) {
		alpm_pkg_t *pkg, *local_pkg;
		int percent = (current * 100) / numtargs;
		PROGRESS(handle, ALPM_PROGRESS_DISKSPACE_START, "", percent,
				numtargs, current);

		pkg = targ->data;
		/* is this package already installed? */
		local_pkg = _alpm_db_get_pkgfromcache(handle->db_local, pkg->name);
		if(local_pkg) {
			calculate_removed_size(handle, mount_points, local_pkg);
		}
		calculate_installed_size(handle, mount_points, pkg);

		for(i = mount_points; i; i = i->next) {
			alpm_mountpoint_t *data = i->data;
			if(data->blocks_needed > data->max_blocks_needed) {
				data->max_blocks_needed = data->blocks_needed;
			}
		}
	}

	PROGRESS(handle, ALPM_PROGRESS_DISKSPACE_START, "", 100,
			numtargs, current);

	for(i = mount_points; i; i = i->next) {
		alpm_mountpoint_t *data = i->data;
		if(data->used && data->read_only) {
			_alpm_log(handle, ALPM_LOG_ERROR, _("Partition %s is mounted read only\n"),
					data->mount_dir);
			error = 1;
		} else if(data->used & USED_INSTALL && check_mountpoint(handle, data)) {
			error = 1;
		}
	}

finish:
	mount_point_list_free(mount_points);

	if(error) {
		RET_ERR(handle, ALPM_ERR_DISK_SPACE, -1);
	}

	return 0;
}