Beispiel #1
0
void
main()
{
  char *hello = "Hello ";
  char *world = (char *)0x4000000;
  mode();
  req_init();
  time_init();
  vga_init();
  kmi_init();
  uart_puts(hello);
  uart_puts(world);
  sti();
  syscall(65);
  mode();
  return;
}
Beispiel #2
0
int single_drive_main(struct fuse_args *args, struct ltfs_fuse_data *priv)
{
	int ret;
	char *index_rules_utf8;
	char fsname[strlen(priv->devname) + 16];
	char *invalid_start;
#ifdef __APPLE__
	char *opt_volname = NULL;
#endif
	char *mountpoint = NULL;
	struct fuse_args tmpa=FUSE_ARGS_INIT(0, NULL);
	int i;
	bool is_worm;
	
#ifdef HP_mingw_BUILD
	(void) i;
	(void) tmpa;
	(void) mountpoint;
#endif /* HP_mingw_BUILD */

	/*  Setup signal handler to terminate cleanly */
	ret = ltfs_set_signal_handlers();
	if (ret < 0) {
		ltfsmsg(LTFS_ERR, "10013E");
		return 1;
	}

	/* Validate rollback_mount option */
	if (priv->rollback_str) {
		errno = 0;
		priv->rollback_gen = strtoul(priv->rollback_str, &invalid_start, 0);
		if( (*invalid_start != '\0') || priv->rollback_gen == 0 ) {
			ltfsmsg(LTFS_ERR, "14091E", priv->rollback_str);
			return 1;
		}
	}

	/*
	 * HP change: HP drives don't support the append only mode functionality.
	 * All the options and messages related to that are disabled. Code remains
	 * but is non-functional.
	 */
	/* Validate append_only_mode */
	if (priv->str_append_only_mode) {
		if (strcasecmp(priv->str_append_only_mode, "on") == 0)
			priv->append_only_mode = 1;
		else if (strcasecmp(priv->str_append_only_mode, "off") == 0)
			priv->append_only_mode = 0;
		else {
			ltfsmsg(LTFS_ERR, "14115E", priv->str_append_only_mode);
			return 1;
		}
	} else {
		/* The append_only_mode will always be 0 in our environment. */
		priv->append_only_mode = 0;
	}

	if (priv->eject == 0 && priv->append_only_mode != 0) {
		/* Append only mode need to eject a cartridge at unmount to clear the mode on drive setting */
		/* To avoid cartridge ejection at unmount, disable append only mode at the moount with noeject option */
		priv->append_only_mode = 0;
		/*ltfsmsg(LTFS_INFO, "14095I");*/
	}

	/* If the local inode space is big enough, have FUSE pass through our UIDs as inode
	 * numbers instead of generating its own. */
	if (sizeof(ino_t) >= 8) {
		ret = fuse_opt_add_arg(args, "-ouse_ino");
		if (ret < 0) {
			/* Could not enable FUSE option */
			ltfsmsg(LTFS_ERR, "14001E", "use_ino", ret);
			return 1;
		}
	}

	/* Set file system name to "ltfs:devname" in case FUSE doesn't pick it up */
	snprintf(fsname, sizeof(fsname), "-ofsname=ltfs:%s", priv->devname);
	ret = fuse_opt_add_arg(args, fsname);
	if (ret < 0) {
		/* Could not enable FUSE option */
		ltfsmsg(LTFS_ERR, "14001E", "fsname", ret);
		return 1;
	}

	/* Allocate the LTFS volume structure */
	if (ltfs_volume_alloc("ltfs", &priv->data) < 0) {
		/* Could not allocate LTFS volume structure */
		ltfsmsg(LTFS_ERR, "14011E");
		return 1;
	}
	ltfs_use_atime(priv->atime, priv->data);

	/*
	 * OSR
	 *
	 * In our MinGW environment, we mount the device on access. This
	 * processing is deferred until ltfs_fuse_mount
	 *
	 */
#ifndef HP_mingw_BUILD
	if (ltfs_device_open(priv->devname, priv->driver_plugin.ops, priv->data) < 0) {
		/* Could not open device */
		ltfsmsg(LTFS_ERR, "10004E", priv->devname);
		ltfs_volume_free(&priv->data);
		return 1;
	}

	if (priv->release_device) {
		ltfs_release_medium(priv->data);
		ltfs_device_close(priv->data);
		ltfs_volume_free(&priv->data);
		return 0;
	}

	/* Parse backend options */
	if (ltfs_parse_tape_backend_opts(args, priv->data)) {
		/* Backend option parsing failed */
		ltfsmsg(LTFS_ERR, "14012E");
		ltfs_volume_free(&priv->data);
		return 1;
	}

	if (priv->kmi_backend_name) {
		if (kmi_init(&priv->kmi_plugin, priv->data) < 0) {
			/* Encryption function disabled. */
			ltfsmsg(LTFS_ERR, "14089E");
			ltfs_volume_free(&priv->data);
			return 1;
		}

		if (ltfs_parse_kmi_backend_opts(args, priv->data)) {
			/* Backend option parsing failed */
			ltfsmsg(LTFS_ERR, "14090E");
			ltfs_volume_free(&priv->data);
			return 1;
		}

		if (tape_clear_key(priv->data->device, priv->data->kmi_handle) < 0)
			return 1;
	}

	/* Setup tape drive */
	priv->data->append_only_mode = (bool)priv->append_only_mode;
	if (ltfs_setup_device(priv->data)) {
		ltfsmsg(LTFS_ERR, "14075E");
		ltfs_volume_free(&priv->data);
		return 1;
	}

	/* Check EOD validation is skipped or not */
	if (priv->skip_eod_check) {
		ltfsmsg(LTFS_INFO, "14076I");
		ltfsmsg(LTFS_INFO, "14077I");
		ltfs_set_eod_check(! priv->skip_eod_check, priv->data);
	}

	/* Validate symbolic link type */
	priv->data->livelink = false;
	if (priv->symlink_str) {
		if (strcasecmp(priv->symlink_str, "live") == 0)
			priv->data->livelink = true;
		else if (strcasecmp(priv->symlink_str, "posix") == 0)
			priv->data->livelink = false;
		else {
			ltfsmsg(LTFS_ERR, "14093E", priv->symlink_str);
			return 1;
		}
		ltfsmsg(LTFS_INFO, "14092I", priv->symlink_str);
	}

	/* Mount the volume */
	ltfs_set_traverse_mode(TRAVERSE_BACKWARD, priv->data);
	if (ltfs_mount(false, false, false, false, priv->rollback_gen, priv->data) < 0) {
		ltfsmsg(LTFS_ERR, "14013E");
		ltfs_volume_free(&priv->data);
		return 1;
	}

	ret = tape_get_worm_status(priv->data->device, &is_worm);
	if (ret != 0 || is_worm) {
		ltfsmsg(LTFS_ERR, "14116E", ret);
		ltfs_volume_free(&priv->data);
		return 1;
	}

	/* Set up index criteria */
	if (priv->index_rules) {
		ret = pathname_format(priv->index_rules, &index_rules_utf8, false, false);
		if (ret < 0) {
			/* Could not format data placement rules. */
			ltfsmsg(LTFS_ERR, "14016E", ret);
			ltfs_volume_free(&priv->data);
			return 1;
		}
		ret = ltfs_override_policy(index_rules_utf8, false, priv->data);
		free(index_rules_utf8);
		if (ret == -LTFS_POLICY_IMMUTABLE) {
			/* Volume doesn't allow override. Ignoring user-specified criteria. */
			ltfsmsg(LTFS_WARN, "14015W");
		} else if (ret < 0) {
			/* Could not parse data placement rules */
			ltfsmsg(LTFS_ERR, "14017E", ret);
			ltfs_volume_free(&priv->data);
			return 1;
		}
	}

	/* Configure I/O scheduler cache */
	ltfs_set_scheduler_cache(priv->min_pool_size, priv->max_pool_size, priv->data);

	/* mount read-only if underlying medium is write-protected */
	ret = ltfs_get_tape_readonly(priv->data);
	if (ret < 0 && ret != -LTFS_WRITE_PROTECT && ret != -LTFS_WRITE_ERROR && ret != -LTFS_NO_SPACE &&
		ret != -LTFS_LESS_SPACE) { /* No other errors are expected. */
		/* Could not get read-only status of medium */
		ltfsmsg(LTFS_ERR, "14018E");
		ltfs_volume_free(&priv->data);
		return 1;
	} else if (ret == -LTFS_WRITE_PROTECT || ret == -LTFS_WRITE_ERROR || ret == -LTFS_NO_SPACE || ret == -LTFS_LESS_SPACE || priv->rollback_gen != 0) {
		if (ret == -LTFS_WRITE_PROTECT || ret == -LTFS_WRITE_ERROR || ret == -LTFS_NO_SPACE) {
			ret = ltfs_get_partition_readonly(ltfs_ip_id(priv->data), priv->data);
			if (ret == -LTFS_WRITE_PROTECT || ret == -LTFS_WRITE_ERROR) {
				if (priv->data->rollback_mount) {
					/* The cartridge will be mounted as read-only if a valid generation number is supplied with
					 * rollback_mount
					 */
					ltfsmsg(LTFS_INFO, "14072I", priv->rollback_gen);
				} else {
					if (ltfs_get_tape_logically_readonly(priv->data) == -LTFS_LOGICAL_WRITE_PROTECT) {
						/* The tape is logically write protected i.e. incompatible medium*/
						ltfsmsg(LTFS_INFO, "14118I");
					}else {
						/* The tape is really write protected */
						ltfsmsg(LTFS_INFO, "14019I");
					}
				}
			} else if (ret == -LTFS_NO_SPACE) {
				/* The index partition is in early warning zone. To be mounted read-only */
				ltfsmsg(LTFS_INFO, "14073I");
			} else { /* 0 or -LTFS_LESS_SPACE */
				/* The data partition may be in early warning zone. To be mounted read-only */
				ltfsmsg(LTFS_INFO, "14074I");
			}
		} else if (ret == -LTFS_LESS_SPACE)
			ltfsmsg(LTFS_INFO, "14071I");
		/*else
			ltfsmsg(LTFS_INFO, "14072I", priv->rollback_gen);*/

		ret = fuse_opt_add_arg(args, "-oro");
		if (ret < 0) {
			/* Could not set FUSE option */
			ltfsmsg(LTFS_ERR, "14001E", "ro", ret);
			ltfs_volume_free(&priv->data);
			return 1;
		}
	}

#else
	/* OSR */
	/* Save the arguments so we can parse them later at the init
	 * callback
	 */
	priv->args = args;

#endif /* HP_mingw_BUILD */

	/*  Cleanup signal handler */
	ret = ltfs_unset_signal_handlers();
	if (ret < 0) {
		ltfsmsg(LTFS_ERR, "10014E");
		return 1;
	}

#ifdef __APPLE__
	/*
	 *  Set the volume name (logical) when LTFS runs on OS X
	 */
	if (priv->data->index->volume_name) {
		ret = asprintf(&opt_volname, "-ovolname=%s(%s)", priv->data->index->volume_name, "ltfs");
		if (ret < 0) {
			/* Memory allocation failed */
			ltfsmsg(LTFS_ERR, "10001E", "option string for volume name");
			ltfs_volume_free(&priv->data);
			return 1;
		}

		ret = fuse_opt_add_arg(args, opt_volname);
		if (ret < 0) {
			/* Could not set FUSE option */
			ltfsmsg(LTFS_ERR, "14001E", "volname", ret);
			ltfs_volume_free(&priv->data);
			free(opt_volname);
			return 1;
		}
	}
#endif /* __APPLE__ */

	/* Not supported on Windows. TODO: Verify this again.*/
#ifndef HP_mingw_BUILD
	/* Get and store mount point */
	for ( i=0; i<args->argc; i++) {
		fuse_opt_add_arg(&tmpa, args->argv[i]);
	}
	ret = fuse_parse_cmdline( &tmpa, &mountpoint, NULL, NULL);
	fuse_opt_free_args(&tmpa);
	if (ret < 0 || mountpoint == NULL) {
		ltfsmsg(LTFS_ERR, "14094E", ret);
		ltfs_volume_free(&priv->data);
		return 1;
	}
	priv->data->mountpoint = mountpoint;
	priv->data->mountpoint_len = strlen(mountpoint);
#endif /* HP_mingw_BUILD */

	/* now we can safely call FUSE */
	ltfsmsg(LTFS_INFO, "14111I");
	ltfsmsg(LTFS_INFO, "14112I");
	ltfsmsg(LTFS_INFO, "14113I");
	ret = fuse_main(args->argc, args->argv, &ltfs_ops, priv);

	/*  Setup signal handler again to terminate cleanly */
	ret = ltfs_set_signal_handlers();
	if (ret < 0) {
		ltfsmsg(LTFS_ERR, "10013E");
		return 1;
	}

	/*
	 * OSR
	 *
	 * In our MinGW environment, we stay running after the device is
	 * dismounted/ejected. This processing is deferred until
	 * ltfs_fuse_unmount
	 *
	 */
#ifndef HP_mingw_BUILD
	if (priv->eject)
		ltfs_eject_tape(priv->data);

	ltfs_device_close(priv->data);
#endif /* HP_mingw_BUILD */

	/* close the volume */
#ifdef __APPLE__
	if (opt_volname)
		free(opt_volname);
#endif /* __APPLE__ */
	ltfs_volume_free(&priv->data);
	ltfs_unset_signal_handlers();

	return ret;
}
Beispiel #3
0
int ltfsck(struct ltfs_volume *vol, struct other_check_opts *opt, void *args)
{
	int ret, ret_close;
	struct libltfs_plugin backend; /* tape driver backend */
	struct libltfs_plugin kmi; /* key manager interface backend */

	/* load the backend, open the tape device, and load a tape */
	ret = plugin_load(&backend, "driver", opt->backend_path, opt->config);
	if (ret < 0) {
		ltfsmsg(LTFS_ERR, "16010E", opt->backend_path, ret);
		return LTFSCK_OPERATIONAL_ERROR;
	}
	if (opt->kmi_backend_name) {
		ret = plugin_load(&kmi, "kmi", opt->kmi_backend_name, opt->config);
		if (ret < 0) {
			ltfsmsg(LTFS_ERR, "16102E", opt->kmi_backend_name);
			return LTFSCK_OPERATIONAL_ERROR;
		}
	}

	ret = LTFSCK_OPERATIONAL_ERROR;
	if (ltfs_device_open(opt->devname, backend.ops, vol) < 0) {
		ltfsmsg(LTFS_ERR, "16011E", opt->devname);
		goto out_unload_backend;
	}
	ret = ltfs_parse_tape_backend_opts(args, vol);
	if (ret < 0) {
		ltfsmsg(LTFS_ERR, "16106E");
		goto out_unload_backend;
	}
	if (opt->kmi_backend_name) {
		ret = kmi_init(&kmi, vol);
		if (ret < 0) {
			ltfsmsg(LTFS_ERR, "16104E", opt->devname, ret);
			goto out_unload_backend;
		}

		ret = ltfs_parse_kmi_backend_opts(args, vol);
		if (ret < 0) {
			ltfsmsg(LTFS_ERR, "16105E");
			goto out_unload_backend;
		}

		ret = tape_clear_key(vol->device, vol->kmi_handle);
		if (ret < 0)
			goto out_unload_backend;
	}
	{
		int i = 0;
		struct fuse_args *a = args;

		for (i = 0; i < a->argc && a->argv[i]; ++i) {
			if (!strcmp(a->argv[i], "-o")) {
				ltfsmsg(LTFS_ERR, "16107E", a->argv[i], a->argv[i + 1] ? a->argv[i + 1] : "");
				ret = LTFSCK_USAGE_SYNTAX_ERROR;
				goto out_unload_backend;
			}
		}
	}
	vol->append_only_mode = false;
	vol->set_pew = false;
	if (ltfs_setup_device(vol)) {
		ltfsmsg(LTFS_ERR, "16092E", opt->devname);
		goto out_close;
	}

	switch (opt->op_mode) {
	case MODE_CHECK:
		ltfsmsg(LTFS_INFO, "16014I", opt->devname);
		opt->full_index_info = false;
		ret = check_ltfs_volume(vol, opt);
		break;
	case MODE_ROLLBACK:
		ltfsmsg(LTFS_INFO, "16015I", opt->devname);
		opt->full_index_info = false;
		switch(opt->search_mode) {
		case SEARCH_BY_GEN:
			ret = rollback(vol, opt);
			break;
		default:
			ltfsmsg(LTFS_ERR, "16016E");
			ret = LTFSCK_USAGE_SYNTAX_ERROR;
			break;
		}
		break;
	case MODE_VERIFY:
		ltfsmsg(LTFS_INFO, "16017I", opt->devname);
		opt->full_index_info = false;
		switch(opt->search_mode) {
		case SEARCH_BY_GEN:
			ret = rollback(vol, opt);
			if (ret == LTFSCK_CORRECTED)
				ret = LTFSCK_NO_ERRORS;
			break;
		default:
			ltfsmsg(LTFS_ERR, "16016E");
			show_usage(opt->prg_name, opt->config, false);
			ret = LTFSCK_USAGE_SYNTAX_ERROR;
			break;
		}
		break;
	case MODE_LIST_POINT:
		ltfsmsg(LTFS_INFO, "16018I", opt->devname);
		ret = list_rollback_points(vol, opt);
		break;
	default:
		ltfsmsg(LTFS_ERR, "16019E");
		ret = LTFSCK_USAGE_SYNTAX_ERROR;
		break;
	}

	/* close the tape device and unload the backend */
out_close:
	ltfs_device_close(vol);
	ltfs_volume_free(&vol);
	ltfs_unset_signal_handlers();
out_unload_backend:
	ret_close = plugin_unload(&backend);
	if (ret == 0 && ret_close < 0) {
		ltfsmsg(LTFS_WARN, "16020W", ret_close);
		ret = LTFSCK_OPERATIONAL_ERROR;
	}
	if (opt->kmi_backend_name) {
		ret_close = plugin_unload(&kmi);
		if (ret == 0 && ret_close < 0) {
			ltfsmsg(LTFS_WARN, "16103W");
			ret = LTFSCK_OPERATIONAL_ERROR;
		}
	}
	if (ret == LTFSCK_CORRECTED)
		ret = LTFSCK_NO_ERRORS;

	return ret;
}
Beispiel #4
0
int unformat_tape(struct ltfs_volume *vol, struct other_format_opts *opt, void *args)
{
	int ret = MKLTFS_OPERATIONAL_ERROR;
	struct libltfs_plugin backend; /* tape driver backend */
	struct libltfs_plugin kmi; /* key manager interface backend */

	/* load the backend, open the tape device, and load a tape */
	ltfsmsg(LTFS_DEBUG, "15006D");
	ret = plugin_load(&backend, "driver", opt->backend_path, opt->config);
	if (ret < 0) {
		ltfsmsg(LTFS_ERR, "15008E", opt->backend_path);
		return MKLTFS_OPERATIONAL_ERROR;
	}
	if (opt->kmi_backend_name) {
		ret = plugin_load(&kmi, "kmi", opt->kmi_backend_name, opt->config);
		if (ret < 0) {
			ltfsmsg(LTFS_ERR, "15050E", opt->kmi_backend_name);
			return MKLTFS_OPERATIONAL_ERROR;
		}
	}
	ret = ltfs_device_open(opt->devname, backend.ops, vol);
	if (ret < 0) {
		ltfsmsg(LTFS_ERR, "15009E", opt->devname, ret);
		ret = MKLTFS_OPERATIONAL_ERROR;
		goto out_unload_backend;
	}
	if (opt->kmi_backend_name) {
		ret = kmi_init(&kmi, vol);
		if (ret < 0) {
			ltfsmsg(LTFS_ERR, "15052E", opt->devname, ret);
			goto out_unload_backend;
		}

		ret = ltfs_parse_kmi_backend_opts(args, vol);
		if (ret < 0) {
			ltfsmsg(LTFS_ERR, "15053E");
			goto out_unload_backend;
		}

		ret = tape_clear_key(vol->device, vol->kmi_handle);
		if (ret < 0)
			goto out_unload_backend;
	}
	{
		int i = 0;
		struct fuse_args *a = args;

		for (i = 0; i < a->argc && a->argv[i]; ++i) {
			if (!strcmp(a->argv[i], "-o")) {
				ltfsmsg(LTFS_ERR, "15055E", a->argv[i], a->argv[i + 1] ? a->argv[i + 1] : "");
				ret = MKLTFS_USAGE_SYNTAX_ERROR;
				goto out_unload_backend;
			}
		}
	}
	vol->append_only_mode = false;
	vol->set_pew = false;
	ret = ltfs_setup_device(vol);
	if (ret < 0) {
		ltfsmsg(LTFS_ERR, "15044E");
		ret = MKLTFS_OPERATIONAL_ERROR;
		goto out_close;
	}
	ltfsmsg(LTFS_DEBUG, "15007D");

	/* Donot unformat if tape is already unformated */
	ret = tape_check_unformat_ok(vol->device);
	if (ret < 0) {
		ltfsmsg(LTFS_ERR, "15494E");
		goto out_close;
	}

	/* Create 1 partition cartridge */
	ret = ltfs_unformat_tape(vol, opt->long_wipe);
	if (ret < 0) {
		if (ret == -LTFS_INTERRUPTED) {
			ltfsmsg(LTFS_ERR, "15046E");
			ret = MKLTFS_CANCELED_BY_USER;
		}else if (ret == -EDEV_WRITE_PROTECTED_WORM) {
			ltfsmsg(LTFS_ERR, "15062E");
			ret = MKLTFS_USAGE_SYNTAX_ERROR;
		}else {
			ltfsmsg(LTFS_ERR, "15038E");
			ret = MKLTFS_OPERATIONAL_ERROR;
		}
		goto out_close;
	}

	ret = MKLTFS_UNFORMATTED;

	/* close the tape device and unload the backend */
	ltfsmsg(LTFS_DEBUG, "15020D");

out_close:
	ltfs_device_close(vol);
	ltfs_volume_free(&vol);
	ltfs_unset_signal_handlers();
	if (ret == MKLTFS_UNFORMATTED)
		ltfsmsg(LTFS_DEBUG, "15022D");
out_unload_backend:
	if (ret == MKLTFS_UNFORMATTED) {
		ret = plugin_unload(&backend);
		if (ret < 0)
			ltfsmsg(LTFS_WARN, "15021W");
		if (opt->kmi_backend_name) {
			ret = plugin_unload(&kmi);
			if (ret < 0)
				ltfsmsg(LTFS_WARN, "15051W");
		}
		ret = MKLTFS_UNFORMATTED;
	} else {
		plugin_unload(&backend);
		if (opt->kmi_backend_name)
			plugin_unload(&kmi);
	}

	if (ret == MKLTFS_UNFORMATTED)
		ltfsmsg(LTFS_INFO, "15040I");
	else
		ltfsmsg(LTFS_INFO, "15039I");

	return ret;
}
Beispiel #5
0
int format_tape(struct ltfs_volume *vol, struct other_format_opts *opt, void *args)
{
	int ret = MKLTFS_OPERATIONAL_ERROR;
	struct device_capacity cap;
	struct libltfs_plugin backend; /* tape driver backend */
	struct libltfs_plugin kmi; /* key manager interface backend */
	struct ltfs_volume *dummy_vol;
	bool is_worm;

	ret = ltfs_set_volume_name(opt->volume_name, vol);
	if (ret < 0)
		return MKLTFS_OPERATIONAL_ERROR;
	ret = ltfs_reset_capacity(!opt->keep_capacity, vol);
	if (ret < 0) {
		return MKLTFS_OPERATIONAL_ERROR;
	}

	/* load the backend, open the tape device, and load a tape */
	ltfsmsg(LTFS_DEBUG, "15006D");
	ret = plugin_load(&backend, "driver", opt->backend_path, opt->config);
	if (ret < 0) {
		ltfsmsg(LTFS_ERR, "15008E", opt->backend_path);
		return MKLTFS_OPERATIONAL_ERROR;
	}
	if (opt->kmi_backend_name) {
		ret = plugin_load(&kmi, "kmi", opt->kmi_backend_name, opt->config);
		if (ret < 0) {
			ltfsmsg(LTFS_ERR, "15050E", opt->kmi_backend_name);
			return MKLTFS_OPERATIONAL_ERROR;
		}
	}
	ret = ltfs_device_open(opt->devname, backend.ops, vol);
	if (ret < 0) {
		ltfsmsg(LTFS_ERR, "15009E", opt->devname, ret);
		ret = MKLTFS_OPERATIONAL_ERROR;
		goto out_unload_backend;
	}
	ret = ltfs_parse_tape_backend_opts(args, vol);
	if (ret < 0) {
		ltfsmsg(LTFS_ERR, "15054E");
		goto out_unload_backend;
	}
	if (opt->kmi_backend_name) {
		ret = kmi_init(&kmi, vol);
		if (ret < 0) {
			ltfsmsg(LTFS_ERR, "15052E", opt->devname, ret);
			goto out_unload_backend;
		}

		ret = ltfs_parse_kmi_backend_opts(args, vol);
		if (ret < 0) {
			ltfsmsg(LTFS_ERR, "15053E");
			goto out_unload_backend;
		}

		ret = tape_clear_key(vol->device, vol->kmi_handle);
		if (ret < 0)
			goto out_unload_backend;
	}
	{
		int i = 0;
		struct fuse_args *a = args;

		for (i = 0; i < a->argc && a->argv[i]; ++i) {
			if (!strcmp(a->argv[i], "-o")) {
				ltfsmsg(LTFS_ERR, "15055E", a->argv[i], a->argv[i + 1] ? a->argv[i + 1] : "");
				ret = MKLTFS_USAGE_SYNTAX_ERROR;
				goto out_unload_backend;
			}
		}
	}
	vol->append_only_mode = false;
	vol->set_pew = false;
	ret = ltfs_setup_device(vol);
	if (ret < 0) {
		ltfsmsg(LTFS_ERR, "15044E");
		ret = MKLTFS_OPERATIONAL_ERROR;
		goto out_close;
	}
	ltfsmsg(LTFS_DEBUG, "15007D");
	
	/*
	 * HP
	 * Load and check write-protect status before proceeding
	 */

	/* Make sure there's a tape loaded: */
	ret = tape_load_tape(vol->device, vol->kmi_handle);
	if (ret < 0) {
		if (ret == -LTFS_UNSUPPORTED_MEDIUM)
			ltfsmsg(LTFS_ERR, "11299E");
		else
			ltfsmsg(LTFS_ERR, "11093E", ret);
		goto out_close;
	}

	/* Make sure it's not logically write protected i.e. incompatible medium*/
	ret = tape_logically_read_only(vol->device);
	if (ret == -LTFS_LOGICAL_WRITE_PROTECT) {
		ltfsmsg(LTFS_ERR, "11330E");
		goto out_close;
	}

	/* TODO: Make sure it's not Write-Protected: */
	ret = tape_read_only(vol->device, 0);
	if (ret == -LTFS_WRITE_PROTECT) {
		ltfsmsg(LTFS_ERR, "11095E");
		goto out_close;
	}

	ltfs_set_partition_map(DATA_PART_ID, INDEX_PART_ID, DATA_PART_NUM, INDEX_PART_NUM, vol);

	/* Check target medium state */
	if (! opt->force) {
		ltfsmsg(LTFS_INFO, "15049I", "mount");
		ret = ltfs_volume_alloc("mkltfs", &dummy_vol);
		if (ret < 0) {
			ret = MKLTFS_OPERATIONAL_ERROR;
			goto out_close;
		}
		dummy_vol->device = vol->device;
		dummy_vol->kmi_handle = vol->kmi_handle;
		ret = ltfs_start_mount(true, dummy_vol);
		dummy_vol->device = NULL;
		dummy_vol->kmi_handle = NULL;
		if (ret != -LTFS_NOT_PARTITIONED && ret != -LTFS_LABEL_INVALID && ret != -LTFS_LABEL_MISMATCH) {
			if (ret == 0) {
				ltfsmsg(LTFS_ERR, "15047E", ret);
				ltfsmsg(LTFS_INFO, "15048I");
			}
			else if (ret == -EDEV_KEY_REQUIRED) {
				ltfsmsg(LTFS_ERR, "15056E");
				ltfsmsg(LTFS_INFO, "15057I");
			}
			ret = MKLTFS_USAGE_SYNTAX_ERROR;
			ltfs_volume_free(&dummy_vol);
			goto out_close;
		}
		ltfs_volume_free(&dummy_vol);
	}
	else {
		ltfsmsg(LTFS_INFO, "15049I", "load");
		ret = tape_load_tape(vol->device, vol->kmi_handle);
		if (ret < 0) {
			if (ret == -LTFS_UNSUPPORTED_MEDIUM)
				ltfsmsg(LTFS_ERR, "11298E");
			else
				ltfsmsg(LTFS_ERR, "11006E");

			ret = MKLTFS_OPERATIONAL_ERROR;
			goto out_close;
		}
	}

	if (tape_get_worm_status(vol->device, &is_worm) < 0) {
		ret = MKLTFS_OPERATIONAL_ERROR;
		goto out_close;
	}

	/* Set up index data: filter rules */
	ret = index_criteria_set_allow_update(is_worm? false : opt->allow_update, vol);
	if (ret < 0) {
		ltfsmsg(LTFS_ERR, "15014E", ret);
		ret = MKLTFS_OPERATIONAL_ERROR;
		goto out_close;
	}

	if (opt->filterrules) {
		if (is_worm) {
			ltfsmsg(LTFS_ERR, "15060E");
			ret = MKLTFS_USAGE_SYNTAX_ERROR;
			goto out_close;
		}

		ret = ltfs_override_policy(opt->filterrules, true, vol);
		if (ret < 0) {
			ltfsmsg(LTFS_ERR, "15015E", ret);
			ret = MKLTFS_OPERATIONAL_ERROR;
			goto out_close;
		}
	}

	/* Create partitions and write labels and indices to the tape */
	ltfsmsg(LTFS_INFO, "15010I", DATA_PART_ID, DATA_PART_NUM);
	ltfsmsg(LTFS_INFO, "15011I", INDEX_PART_ID, INDEX_PART_NUM);
	ret = ltfs_format_tape(vol);
	if (ret < 0) {
		if (ret == -LTFS_INTERRUPTED) {
			ltfsmsg(LTFS_ERR, "15045E");
			ret = MKLTFS_CANCELED_BY_USER;
		}else if (ret == -EDEV_WRITE_PROTECTED_WORM) {
			ltfsmsg(LTFS_ERR, "15061E");
			ret = MKLTFS_USAGE_SYNTAX_ERROR;
		}else {
			ltfsmsg(LTFS_ERR, "15012E");
			if (ret == -LTFS_WRITE_PROTECT || ret == -LTFS_WRITE_ERROR)
				ret = MKLTFS_USAGE_SYNTAX_ERROR;
			else
				ret = MKLTFS_OPERATIONAL_ERROR;
		}
		goto out_close;
	}
	ltfsmsg(LTFS_INFO, "15013I", ltfs_get_volume_uuid(vol));
	if (! opt->quiet)
		fprintf(stderr, "\n");

	/* Print volume capacity as GB (10^9 Bytes - SI) */
	memset(&cap, 0, sizeof(cap));
	ltfs_capacity_data(&cap, vol);
	ltfsmsg(LTFS_INFO, "15019I", (unsigned long long)LTFS_CALC_VOLUME_SIZE(cap.total_dp,
													opt->blocksize, BYTE_MULTIPLIER));

/* Separate implementation for MAM attributes exist. */													  
#if 0													  
	vol->t_attr = (struct tape_attr *) calloc(1, sizeof(struct tape_attr));
	if (! vol->t_attr) {
		ltfsmsg(LTFS_ERR, "10001E", "format_tape: vol->t_attr");
		goto out_close;
	}

	/* set Tape Attribute to vol->t_attr */
	set_tape_attribute(vol, vol->t_attr);

	ret = tape_format_attribute_to_cm(vol->device, vol->t_attr);
	if (ret < 0) {
		free(vol->t_attr);
		ltfsmsg(LTFS_ERR, "15058E", "format_tape");
	}
#endif /* 0 */
	ret = MKLTFS_NO_ERRORS;

	/* close the tape device and unload the backend */
	ltfsmsg(LTFS_DEBUG, "15020D");

out_close:
	ltfs_device_close(vol);
	ltfs_volume_free(&vol);
	ltfs_unset_signal_handlers();
	if (ret == MKLTFS_NO_ERRORS)
		ltfsmsg(LTFS_DEBUG, "15022D");
out_unload_backend:
	if (ret == MKLTFS_NO_ERRORS) {
		ret = plugin_unload(&backend);
		if (ret < 0)
			ltfsmsg(LTFS_WARN, "15021W");
		if (opt->kmi_backend_name) {
			ret = plugin_unload(&kmi);
			if (ret < 0)
				ltfsmsg(LTFS_WARN, "15051W");
		}
		ret = MKLTFS_NO_ERRORS;
	} else {
		plugin_unload(&backend);
		if (opt->kmi_backend_name)
			plugin_unload(&kmi);
	}

	if (ret == MKLTFS_NO_ERRORS)
		ltfsmsg(LTFS_INFO, "15024I");
	else
		ltfsmsg(LTFS_INFO, "15023I");

	return ret;
}