Esempio n. 1
0
int os_main(int argc, char* argv[])
{
	adv_conf* context;
	char* section_map[1];

	context = conf_init();

	if (os_init(context) != 0)
		goto err_conf;

	inputb_reg(context, 1);
	inputb_reg_driver_all(context);

	if (conf_input_args_load(context, 0, "", &argc, argv, error_callback, 0) != 0)
		goto err_os;

	if (argc > 1) {
		fprintf(stderr, "Unknown argument '%s'\n", argv[1]);
		goto err_os;
	}

	section_map[0] = "";
	conf_section_set(context, section_map, 1);

	if (inputb_load(context) != 0)
		goto err_os;

	if (os_inner_init("AdvanceINPUT") != 0)
		goto err_os;

	if (inputb_init() != 0)
		goto err_os_inner;

	if (inputb_enable(0) != 0)
		goto err_input;

	run();

	inputb_disable();
	inputb_done();
	os_inner_done();
	os_done();
	conf_done(context);

	return EXIT_SUCCESS;

err_input:
	inputb_done();
err_os_inner:
	os_inner_done();
err_os:
	os_done();
err_conf:
	conf_done(context);
	return EXIT_FAILURE;

}
Esempio n. 2
0
int os_main(int argc, char* argv[])
{
	int keyboard_id;
	adv_conf* context;
	const char* s;
        char* section_map[1];
	const char** file_map;
	unsigned file_mac;
	int i;
	double latency_time;
	double buffer_time;
	double volume;
	unsigned rate;
	int attenuation;
	adv_bool opt_log;
	adv_bool opt_logsync;

	opt_log = 0;
	opt_logsync = 0;
	file_map = 0;
	file_mac = 0;

	context = conf_init();

	if (os_init(context) != 0)
		goto err_conf;

	mixer_reg(context);

	conf_int_register_limit_default(context, "sound_volume", -32, 0, 0);
	conf_int_register_limit_default(context, "sound_samplerate", 5000, 96000, 44100);
	conf_float_register_limit_default(context, "sound_latency", 0.01, 2.0, 0.1);
	conf_float_register_limit_default(context, "sound_buffer", 0.05, 2.0, 0.1);

	if (conf_input_args_load(context, 0, "", &argc, argv, error_callback, 0) != 0)
		goto err_os;

	file_map = malloc(argc * sizeof(const char*));

	for(i=1;i<argc;++i) {
		if (target_option_compare(argv[i], "log")) {
			opt_log = 1;
		} else if (target_option_compare(argv[i], "logsync")) {
			opt_logsync = 1;
		} else if (target_option_extract(argv[i]) == 0) {
			file_map[file_mac++] = argv[i];
		} else {
			target_err("Unknown command line option '%s'.\n", argv[i]);
			goto err_os;
		}
	}

	if (argc <= 1 || file_mac == 0) {
		target_err("Syntax: advs FILES...\n");
		goto err_os;
	}

	if (opt_log || opt_logsync) {
		const char* log = "advs.log";
		remove(log);
		log_init(log, opt_logsync);
        }

	section_map[0] = "";
	conf_section_set(context, section_map, 1);

	if (mixer_load(context) != 0) {
		goto err_os;
	}

	attenuation = conf_int_get_default(context, "sound_volume");
	latency_time = conf_float_get_default(context, "sound_latency");
	buffer_time = conf_float_get_default(context, "sound_buffer");
	rate = conf_int_get_default(context, "sound_samplerate");
	volume = 1.0;
	while (attenuation++ < 0)
		volume /= 1.122018454; /* = (10 ^ (1/20)) = 1dB */

	if (os_inner_init("AdvanceSOUND") != 0)
		goto err_os;

	if (file_mac > MIXER_CHANNEL_MAX) {
		target_err("Too many files\n");
		goto err_os_inner;
	}

	if (mixer_init(rate, file_mac, 1, buffer_time + latency_time, latency_time) != 0) {
		target_err("%s\n", error_get());
		goto err_os_inner;
	}

	mixer_volume(volume);

	for(i=0;i<file_mac;++i)
		run(i, file_map[i]);

	free(file_map);

	signal(SIGINT, sigint);

	while (!done) {
		for(i=0;i<file_mac;++i)
			if (mixer_is_playing(i))
				break;
		if (i==file_mac)
			break;

		mixer_poll();
		target_idle();
	}

	log_std(("s: shutdown\n"));

	mixer_done();

	os_inner_done();

	log_std(("s: the end\n"));

	if (opt_log || opt_logsync) {
		log_done();
	}

	os_done();
	conf_done(context);

	return EXIT_SUCCESS;

err_os_inner:
	os_inner_done();
	log_done();
err_os:
	os_done();
err_conf:
	conf_done(context);
err:
	return EXIT_FAILURE;

}
Esempio n. 3
0
int main(int argc, char* argv[])
{
	int c;
	struct snapraid_option opt;
	char conf[PATH_MAX];
	struct snapraid_state state;
	int operation;
	block_off_t blockstart;
	block_off_t blockcount;
	int ret;
	tommy_list filterlist_file;
	tommy_list filterlist_disk;
	int filter_missing;
	int filter_error;
	int plan;
	int olderthan;
	char* e;
	const char* command;
	const char* import_timestamp;
	const char* import_content;
	const char* log_file;
	int lock;
	const char* gen_conf;
	const char* run;
	int speedtest;
	int period;
	time_t t;
	struct tm* tm;
	int i;

	/* defaults */
	config(conf, sizeof(conf), argv[0]);
	memset(&opt, 0, sizeof(opt));
	opt.io_error_limit = 100;
	blockstart = 0;
	blockcount = 0;
	tommy_list_init(&filterlist_file);
	tommy_list_init(&filterlist_disk);
	period = 1000;
	filter_missing = 0;
	filter_error = 0;
	plan = SCRUB_AUTO;
	olderthan = SCRUB_AUTO;
	import_timestamp = 0;
	import_content = 0;
	log_file = 0;
	lock = 0;
	gen_conf = 0;
	speedtest = 0;
	run = 0;

	opterr = 0;
	while ((c =
#if HAVE_GETOPT_LONG
		getopt_long(argc, argv, OPTIONS, long_options, 0))
#else
		getopt(argc, argv, OPTIONS))
#endif
		!= EOF) {
		switch (c) {
		case 'c' :
			pathimport(conf, sizeof(conf), optarg);
			break;
		case 'f' : {
			struct snapraid_filter* filter = filter_alloc_file(1, optarg);
			if (!filter) {
				/* LCOV_EXCL_START */
				log_fatal("Invalid filter specification '%s'\n", optarg);
				log_fatal("Filters using relative paths are not supported. Ensure to add an initial slash\n");
				exit(EXIT_FAILURE);
				/* LCOV_EXCL_STOP */
			}
			tommy_list_insert_tail(&filterlist_file, &filter->node, filter);
		} break;
		case 'd' : {
			struct snapraid_filter* filter = filter_alloc_disk(1, optarg);
			if (!filter) {
				/* LCOV_EXCL_START */
				log_fatal("Invalid filter specification '%s'\n", optarg);
				exit(EXIT_FAILURE);
				/* LCOV_EXCL_STOP */
			}
			tommy_list_insert_tail(&filterlist_disk, &filter->node, filter);
		} break;
		case 'm' :
			filter_missing = 1;
			opt.expected_missing = 1;
			break;
		case 'e' :
			/* when processing only error, we filter both files and blocks */
			/* and we apply fixes only to synced ones */
			filter_error = 1;
			opt.badonly = 1;
			opt.syncedonly = 1;
			break;
		case 'p' :
			if (strcmp(optarg, "bad") == 0) {
				plan = SCRUB_BAD;
			} else if (strcmp(optarg, "new") == 0) {
				plan = SCRUB_NEW;
			} else if (strcmp(optarg, "full") == 0) {
				plan = SCRUB_FULL;
			} else {
				plan = strtoul(optarg, &e, 10);
				if (!e || *e || plan > 100) {
					/* LCOV_EXCL_START */
					log_fatal("Invalid plan/percentage '%s'\n", optarg);
					exit(EXIT_FAILURE);
					/* LCOV_EXCL_STOP */
				}
			}
			break;
		case 'o' :
			olderthan = strtoul(optarg, &e, 10);
			if (!e || *e || olderthan > 1000) {
				/* LCOV_EXCL_START */
				log_fatal("Invalid number of days '%s'\n", optarg);
				exit(EXIT_FAILURE);
				/* LCOV_EXCL_STOP */
			}
			break;
		case 'S' :
			blockstart = strtoul(optarg, &e, 0);
			if (!e || *e) {
				/* LCOV_EXCL_START */
				log_fatal("Invalid start position '%s'\n", optarg);
				exit(EXIT_FAILURE);
				/* LCOV_EXCL_STOP */
			}
			break;
		case 'B' :
			blockcount = strtoul(optarg, &e, 0);
			if (!e || *e) {
				/* LCOV_EXCL_START */
				log_fatal("Invalid count number '%s'\n", optarg);
				exit(EXIT_FAILURE);
				/* LCOV_EXCL_STOP */
			}
			break;
		case 'L' :
			opt.io_error_limit = strtoul(optarg, &e, 0);
			if (!e || *e) {
				/* LCOV_EXCL_START */
				log_fatal("Invalid error limit number '%s'\n", optarg);
				exit(EXIT_FAILURE);
				/* LCOV_EXCL_STOP */
			}
			break;
		case 'i' :
			if (import_timestamp) {
				/* LCOV_EXCL_START */
				log_fatal("Import directory '%s' already specified as '%s'\n", optarg, import_timestamp);
				exit(EXIT_FAILURE);
				/* LCOV_EXCL_STOP */
			}
			import_timestamp = optarg;
			break;
		case OPT_TEST_IMPORT_CONTENT :
			if (import_content) {
				/* LCOV_EXCL_START */
				log_fatal("Import directory '%s' already specified as '%s'\n", optarg, import_content);
				exit(EXIT_FAILURE);
				/* LCOV_EXCL_STOP */
			}
			import_content = optarg;
			break;
		case 'l' :
			if (log_file) {
				/* LCOV_EXCL_START */
				log_fatal("Log file '%s' already specified as '%s'\n", optarg, log_file);
				exit(EXIT_FAILURE);
				/* LCOV_EXCL_STOP */
			}
			log_file = optarg;
			break;
		case 'Z' :
			opt.force_zero = 1;
			break;
		case 'E' :
			opt.force_empty = 1;
			break;
		case 'U' :
			opt.force_uuid = 1;
			break;
		case 'D' :
			opt.force_device = 1;
			break;
		case 'N' :
			opt.force_nocopy = 1;
			break;
		case 'F' :
			opt.force_full = 1;
			break;
		case 'a' :
			opt.auditonly = 1;
			break;
		case 'h' :
			opt.prehash = 1;
			break;
		case 'v' :
			++msg_level;
			break;
		case 'q' :
			--msg_level;
			break;
		case 'G' :
			opt.gui = 1;
			break;
		case 'H' :
			usage();
			exit(EXIT_SUCCESS);
		case 'V' :
			version();
			exit(EXIT_SUCCESS);
		case 'T' :
			speedtest = 1;
			break;
		case 'C' :
			gen_conf = optarg;
			break;
		case OPT_TEST_KILL_AFTER_SYNC :
			opt.kill_after_sync = 1;
			break;
		case OPT_TEST_EXPECT_UNRECOVERABLE :
			opt.expect_unrecoverable = 1;
			break;
		case OPT_TEST_EXPECT_RECOVERABLE :
			opt.expect_recoverable = 1;
			break;
		case OPT_TEST_SKIP_SELF :
			opt.skip_self = 1;
			break;
		case OPT_TEST_SKIP_SIGN :
			opt.skip_sign = 1;
			break;
		case OPT_TEST_SKIP_FALLOCATE :
			opt.skip_fallocate = 1;
			break;
		case OPT_TEST_SKIP_SEQUENTIAL :
			opt.skip_sequential = 1;
			break;
		case OPT_TEST_SKIP_DEVICE :
			opt.skip_device = 1;
			period = 50; /* reduce period of the speed test */
			break;
		case OPT_TEST_SKIP_CONTENT_CHECK :
			opt.skip_content_check = 1;
			break;
		case OPT_TEST_SKIP_PARITY_ACCESS :
			opt.skip_parity_access = 1;
			break;
		case OPT_TEST_SKIP_DISK_ACCESS :
			opt.skip_disk_access = 1;
			break;
		case OPT_TEST_FORCE_MURMUR3 :
			opt.force_murmur3 = 1;
			break;
		case OPT_TEST_FORCE_SPOOKY2 :
			opt.force_spooky2 = 1;
			break;
		case OPT_TEST_SKIP_LOCK :
			opt.skip_lock = 1;
			break;
		case OPT_TEST_FORCE_ORDER_PHYSICAL :
			opt.force_order = SORT_PHYSICAL;
			break;
		case OPT_TEST_FORCE_ORDER_INODE :
			opt.force_order = SORT_INODE;
			break;
		case OPT_TEST_FORCE_ORDER_ALPHA :
			opt.force_order = SORT_ALPHA;
			break;
		case OPT_TEST_FORCE_ORDER_DIR :
			opt.force_order = SORT_DIR;
			break;
		case OPT_TEST_FORCE_SCRUB_AT :
			opt.force_scrub_at = atoi(optarg);
			break;
		case OPT_TEST_FORCE_SCRUB_EVEN :
			opt.force_scrub_even = 1;
			break;
		case OPT_TEST_FORCE_CONTENT_WRITE :
			opt.force_content_write = 1;
			break;
		case OPT_TEST_EXPECT_FAILURE :
			/* invert the exit codes */
			exit_success = 1;
			exit_failure = 0;
			break;
		case OPT_TEST_EXPECT_NEED_SYNC :
			/* invert the exit codes */
			exit_success = 1;
			exit_sync_needed = 0;
			break;
		case OPT_TEST_RUN :
			run = optarg;
			break;
		case OPT_TEST_FORCE_SCAN_WINFIND :
			opt.force_scan_winfind = 1;
			break;
		case OPT_TEST_FORCE_PROGRESS :
			opt.force_progress = 1;
			break;
		case OPT_TEST_FORCE_AUTOSAVE_AT :
			opt.force_autosave_at = atoi(optarg);
			break;
		case OPT_TEST_FAKE_DEVICE :
			opt.fake_device = 1;
			break;
		case OPT_NO_WARNINGS :
			opt.no_warnings = 1;
			break;
		default :
			/* LCOV_EXCL_START */
			log_fatal("Unknown option '%c'\n", (char)c);
			exit(EXIT_FAILURE);
			/* LCOV_EXCL_STOP */
		}
	}

	os_init(opt.force_scan_winfind);
	raid_init();
	crc32c_init();

	if (speedtest != 0) {
		speed(period);
		os_done();
		exit(EXIT_SUCCESS);
	}

	if (gen_conf != 0) {
		generate_configuration(gen_conf);
		os_done();
		exit(EXIT_SUCCESS);
	}

	if (optind + 1 != argc) {
		/* LCOV_EXCL_START */
		usage();
		exit(EXIT_FAILURE);
		/* LCOV_EXCL_STOP */
	}

	command = argv[optind];
	if (strcmp(command, "diff") == 0) {
		operation = OPERATION_DIFF;
	} else if (strcmp(argv[optind], "sync") == 0) {
		operation = OPERATION_SYNC;
	} else if (strcmp(argv[optind], "check") == 0) {
		operation = OPERATION_CHECK;
	} else if (strcmp(argv[optind], "fix") == 0) {
		operation = OPERATION_FIX;
	} else if (strcmp(argv[optind], "test-dry") == 0) {
		operation = OPERATION_DRY;
	} else if (strcmp(argv[optind], "dup") == 0) {
		operation = OPERATION_DUP;
	} else if (strcmp(argv[optind], "list") == 0) {
		operation = OPERATION_LIST;
	} else if (strcmp(argv[optind], "pool") == 0) {
		operation = OPERATION_POOL;
	} else if (strcmp(argv[optind], "rehash") == 0) {
		operation = OPERATION_REHASH;
	} else if (strcmp(argv[optind], "scrub") == 0) {
		operation = OPERATION_SCRUB;
	} else if (strcmp(argv[optind], "status") == 0) {
		operation = OPERATION_STATUS;
	} else if (strcmp(argv[optind], "test-rewrite") == 0) {
		operation = OPERATION_REWRITE;
	} else if (strcmp(argv[optind], "test-read") == 0) {
		operation = OPERATION_READ;
	} else if (strcmp(argv[optind], "test-nano") == 0) {
		operation = OPERATION_NANO;
	} else if (strcmp(argv[optind], "up") == 0) {
		operation = OPERATION_SPINUP;
	} else if (strcmp(argv[optind], "down") == 0) {
		operation = OPERATION_SPINDOWN;
	} else if (strcmp(argv[optind], "devices") == 0) {
		operation = OPERATION_DEVICES;
	} else if (strcmp(argv[optind], "smart") == 0) {
		operation = OPERATION_SMART;
	} else {
		/* LCOV_EXCL_START */
		log_fatal("Unknown command '%s'\n", argv[optind]);
		exit(EXIT_FAILURE);
		/* LCOV_EXCL_STOP */
	}

	/* check options compatibility */
	switch (operation) {
	case OPERATION_CHECK :
		break;
	default :
		if (opt.auditonly) {
			/* LCOV_EXCL_START */
			log_fatal("You cannot use -a, --audit-only with the '%s' command\n", command);
			exit(EXIT_FAILURE);
			/* LCOV_EXCL_STOP */
		}
	}

	switch (operation) {
	case OPERATION_FIX :
		break;
	default :
		if (opt.force_device) {
			/* LCOV_EXCL_START */
			log_fatal("You cannot use -D, --force-device with the '%s' command\n", command);
			exit(EXIT_FAILURE);
			/* LCOV_EXCL_STOP */
		}
	}

	switch (operation) {
	case OPERATION_SYNC :
	case OPERATION_CHECK :
	case OPERATION_FIX :
		break;
	default :
		if (opt.force_nocopy) {
			/* LCOV_EXCL_START */
			log_fatal("You cannot use -N, --force-nocopy with the '%s' command\n", command);
			exit(EXIT_FAILURE);
			/* LCOV_EXCL_STOP */
		}
	}

	switch (operation) {
	case OPERATION_SYNC :
		break;
	default :
		if (opt.prehash) {
			/* LCOV_EXCL_START */
			log_fatal("You cannot use -h, --pre-hash with the '%s' command\n", command);
			exit(EXIT_FAILURE);
			/* LCOV_EXCL_STOP */
		}

		if (opt.force_full) {
			/* LCOV_EXCL_START */
			log_fatal("You cannot use -F, --force-full with the '%s' command\n", command);
			exit(EXIT_FAILURE);
			/* LCOV_EXCL_STOP */
		}
	}

	if (opt.force_full && opt.force_nocopy) {
		/* LCOV_EXCL_START */
		log_fatal("You cannot use the -F, --force-full and -N, --force-nocopy options at the same time\n");
		exit(EXIT_FAILURE);
		/* LCOV_EXCL_STOP */
	}

	if (opt.prehash && opt.force_nocopy) {
		/* LCOV_EXCL_START */
		log_fatal("You cannot use the -h, --pre-hash and -N, --force-nocopy options at the same time\n");
		exit(EXIT_FAILURE);
		/* LCOV_EXCL_STOP */
	}

	switch (operation) {
	case OPERATION_CHECK :
	case OPERATION_FIX :
	case OPERATION_DRY :
		break;
	default :
		if (!tommy_list_empty(&filterlist_file)) {
			/* LCOV_EXCL_START */
			log_fatal("You cannot use -f, --filter with the '%s' command\n", command);
			exit(EXIT_FAILURE);
			/* LCOV_EXCL_STOP */
		}
		if (!tommy_list_empty(&filterlist_disk)) {
			/* LCOV_EXCL_START */
			log_fatal("You cannot use -d, --filter-disk with the '%s' command\n", command);
			exit(EXIT_FAILURE);
			/* LCOV_EXCL_STOP */
		}
		if (filter_missing != 0) {
			/* LCOV_EXCL_START */
			log_fatal("You cannot use -m, --filter-missing with the '%s' command\n", command);
			exit(EXIT_FAILURE);
			/* LCOV_EXCL_STOP */
		}
		if (filter_error != 0) {
			/* LCOV_EXCL_START */
			log_fatal("You cannot use -e, --filter-error with the '%s' command\n", command);
			exit(EXIT_FAILURE);
			/* LCOV_EXCL_STOP */
		}
	}

	/* errors must be always fixed on all disks */
	/* becasue we don't keep the information on what disk is the error */
	if (filter_error != 0 && !tommy_list_empty(&filterlist_disk)) {
		/* LCOV_EXCL_START */
		log_fatal("You cannot use -e, --filter-error and -d, --filter-disk at the same time\n");
		exit(EXIT_FAILURE);
		/* LCOV_EXCL_STOP */
	}

	switch (operation) {
	case OPERATION_CHECK :
	case OPERATION_FIX :
		break;
	default :
		if (import_timestamp != 0 || import_content != 0) {
			/* LCOV_EXCL_START */
			log_fatal("You cannot import with the '%s' command\n", command);
			exit(EXIT_FAILURE);
			/* LCOV_EXCL_STOP */
		}
	}

	switch (operation) {
	case OPERATION_LIST :
	case OPERATION_DUP :
	case OPERATION_STATUS :
	case OPERATION_REWRITE :
	case OPERATION_READ :
	case OPERATION_REHASH :
	case OPERATION_SPINUP : /* we want to do it in different threads to avoid blocking */
		/* avoid to check and access data disks if not needed */
		opt.skip_disk_access = 1;
		break;
	}

	switch (operation) {
	case OPERATION_DIFF :
	case OPERATION_LIST :
	case OPERATION_DUP :
	case OPERATION_POOL :
	case OPERATION_STATUS :
	case OPERATION_REWRITE :
	case OPERATION_READ :
	case OPERATION_REHASH :
	case OPERATION_NANO :
	case OPERATION_SPINUP : /* we want to do it in different threads to avoid blocking */
		/* avoid to check and access parity disks if not needed */
		opt.skip_parity_access = 1;
		break;
	}

	switch (operation) {
	case OPERATION_FIX :
	case OPERATION_CHECK :
		/* avoid to stop processing if a content file is not accessible */
		opt.skip_content_access = 1;
		break;
	}

	switch (operation) {
	case OPERATION_DIFF :
	case OPERATION_LIST :
	case OPERATION_DUP :
	case OPERATION_POOL :
	case OPERATION_NANO :
	case OPERATION_SPINUP :
	case OPERATION_SPINDOWN :
	case OPERATION_DEVICES :
	case OPERATION_SMART :
		opt.skip_self = 1;
		break;
	}

	switch (operation) {
	case OPERATION_DEVICES :
	case OPERATION_SMART :
		/* we may need to use these commands during operations */
		opt.skip_lock = 1;
		break;
	}

	/* open the log file */
	log_open(log_file);

	/* print generic info into the log */
	t = time(0);
	tm = localtime(&t);
	log_tag("version:%s\n", PACKAGE_VERSION);
	log_tag("unixtime:%" PRIi64 "\n", (int64_t)t);
	if (tm) {
		char datetime[64];
		strftime(datetime, sizeof(datetime), "%Y-%m-%d %H:%M:%S", tm);
		log_tag("time:%s\n", datetime);
	}
	log_tag("command:%s\n", command);
	for (i = 0; i < argc; ++i)
		log_tag("argv:%u:%s\n", i, argv[i]);
	log_flush();

	if (!opt.skip_self)
		selftest();

	state_init(&state);

	/* read the configuration file */
	state_config(&state, conf, command, &opt, &filterlist_disk);

	/* set the raid mode */
	raid_mode(state.raid_mode);

#if HAVE_LOCKFILE
	/* create the lock file */
	if (!opt.skip_lock && state.lockfile[0]) {
		lock = lock_lock(state.lockfile);
		if (lock == -1) {
			/* LCOV_EXCL_START */
			if (errno != EWOULDBLOCK) {
				log_fatal("Error creating the lock file '%s'. %s.\n", state.lockfile, strerror(errno));
			} else {
				log_fatal("The lock file '%s' is already locked!\n", state.lockfile);
				log_fatal("SnapRAID is already in use!\n");
			}
			exit(EXIT_FAILURE);
			/* LCOV_EXCL_STOP */
		}
	}
#else
	(void)lock;
#endif

	if (operation == OPERATION_DIFF) {
		state_read(&state);

		ret = state_diff(&state);

		/* abort if sync needed */
		if (ret > 0)
			exit(EXIT_SYNC_NEEDED);
	} else if (operation == OPERATION_SYNC) {

		/* in the next state read ensures to clear all the past hashes in case */
		/* we are reading from an incomplete sync */
		/* The undeterminated hash are only for CHG/DELETED blocks for which we don't */
		/* know if the previous interrupted sync was able to update or not the parity. */
		/* The sync process instead needs to trust this information because it's used */
		/* to avoid to recompute the parity if all the input are equals as before. */

		/* In these cases we don't know if the old state is still the one */
		/* stored inside the parity, because after an aborted sync, the parity */
		/* may be or may be not have been updated with the data that may be now */
		/* deleted. Then we reset the hash to a bogus value. */

		/* An example for CHG blocks is: */
		/* - One file is added creating a CHG block with ZERO state */
		/* - Sync aborted after updating the parity to the new state, */
		/*   but without saving the content file representing this new BLK state. */
		/* - File is now deleted after the aborted sync */
		/* - Sync again, deleting the blocks overt the CHG ones */
		/*   with the hash of CHG blocks not represeting the real parity state */

		/* An example for DELETED blocks is: */
		/* - One file is deleted creating DELETED blocks */
		/* - Sync aborted after, updating the parity to the new state, */
		/*   but without saving the content file representing this new EMPTY state. */
		/* - Another file is added again over the DELETE ones */
		/*   with the hash of DELETED blocks not represeting the real parity state */
		state.clear_past_hash = 1;

		state_read(&state);

		state_scan(&state);

		/* refresh the size info before the content write */
		state_refresh(&state);

		memory();

		/* intercept signals while operating */
		signal_init();

		/* save the new state before the sync */
		/* this allow to recover the case of the changes in the array after an aborted sync. */

		/* for example, think at this case: */
		/* - add some files at the array */
		/* - run a sync command, it will recompute the parity adding the new files */
		/* - abort the sync command before it stores the new content file */
		/* - delete the not yet synced files from the array */
		/* - run a new sync command */

		/* the new sync command has now way to know that the parity file was modified */
		/* because the files triggering these changes are now deleted */
		/* and they aren't listed in the content file */

		if (state.need_write)
			state_write(&state);

		/* run a test command if required */
		if (run != 0) {
			ret = system(run); /* ignore error */
			if (ret != 0) {
				/* LCOV_EXCL_START */
				log_fatal("Error in running command '%s'.\n", run);
				exit(EXIT_FAILURE);
				/* LCOV_EXCL_STOP */
			}
		}

		/* waits some time to ensure that any concurrent modification done at the files, */
		/* using the same mtime read by the scan process, will be read by sync. */
		/* Note that any later modification done, potentially not read by sync, will have */
		/* a different mtime, and it will be syncronized at the next sync. */
		/* The worst case is the FAT filesystem with a two seconds resolution for mtime. */
		/* If you don't use FAT, the wait is not needed, because most filesystems have now */
		/* at least microseconds resolution, but better to be safe. */
		if (!opt.skip_self)
			sleep(2);

		ret = state_sync(&state, blockstart, blockcount);

		/* save the new state if required */
		if (!opt.kill_after_sync && (state.need_write || state.opt.force_content_write))
			state_write(&state);

		/* abort if required */
		if (ret != 0) {
			/* LCOV_EXCL_START */
			exit(EXIT_FAILURE);
			/* LCOV_EXCL_STOP */
		}
	} else if (operation == OPERATION_DRY) {
		state_read(&state);

		/* filter */
		state_skip(&state);
		state_filter(&state, &filterlist_file, &filterlist_disk, filter_missing, filter_error);

		memory();

		/* intercept signals while operating */
		signal_init();

		state_dry(&state, blockstart, blockcount);
	} else if (operation == OPERATION_REHASH) {
		state_read(&state);

		/* intercept signals while operating */
		signal_init();

		state_rehash(&state);

		/* save the new state if required */
		if (state.need_write)
			state_write(&state);
	} else if (operation == OPERATION_SCRUB) {
		state_read(&state);

		memory();

		/* intercept signals while operating */
		signal_init();

		ret = state_scrub(&state, plan, olderthan);

		/* save the new state if required */
		if (state.need_write || state.opt.force_content_write)
			state_write(&state);

		/* abort if required */
		if (ret != 0) {
			/* LCOV_EXCL_START */
			exit(EXIT_FAILURE);
			/* LCOV_EXCL_STOP */
		}
	} else if (operation == OPERATION_REWRITE) {
		state_read(&state);

		/* intercept signals while operating */
		signal_init();

		state_write(&state);

		memory();
	} else if (operation == OPERATION_READ) {
		state_read(&state);

		memory();
	} else if (operation == OPERATION_NANO) {
		state_read(&state);

		state_nano(&state);

		/* intercept signals while operating */
		signal_init();

		state_write(&state);

		memory();
	} else if (operation == OPERATION_SPINUP) {
		state_device(&state, DEVICE_UP);
	} else if (operation == OPERATION_SPINDOWN) {
		state_device(&state, DEVICE_DOWN);
	} else if (operation == OPERATION_DEVICES) {
		state_device(&state, DEVICE_LIST);
	} else if (operation == OPERATION_SMART) {
		state_device(&state, DEVICE_SMART);
	} else if (operation == OPERATION_STATUS) {
		state_read(&state);

		memory();

		state_status(&state);
	} else if (operation == OPERATION_DUP) {
		state_read(&state);

		state_dup(&state);
	} else if (operation == OPERATION_LIST) {
		state_read(&state);

		state_list(&state);
	} else if (operation == OPERATION_POOL) {
		state_read(&state);

		state_pool(&state);
	} else {
		state_read(&state);

		/* if we are also trying to recover */
		if (!state.opt.auditonly) {
			/* import the user specified dirs */
			if (import_timestamp != 0)
				state_search(&state, import_timestamp);
			if (import_content != 0)
				state_import(&state, import_content);

			/* import from all the array */
			if (!state.opt.force_nocopy)
				state_search_array(&state);
		}

		/* filter */
		state_skip(&state);
		state_filter(&state, &filterlist_file, &filterlist_disk, filter_missing, filter_error);

		memory();

		/* intercept signals while operating */
		signal_init();

		if (operation == OPERATION_CHECK) {
			ret = state_check(&state, 0, blockstart, blockcount);
		} else { /* it's fix */
			ret = state_check(&state, 1, blockstart, blockcount);
		}

		/* abort if required */
		if (ret != 0) {
			/* LCOV_EXCL_START */
			exit(EXIT_FAILURE);
			/* LCOV_EXCL_STOP */
		}
	}

	/* close log file */
	log_close(log_file);

#if HAVE_LOCKFILE
	if (!opt.skip_lock && state.lockfile[0]) {
		if (lock_unlock(lock) == -1) {
			/* LCOV_EXCL_START */
			log_fatal("Error closing the lock file '%s'. %s.\n", state.lockfile, strerror(errno));
			exit(EXIT_FAILURE);
			/* LCOV_EXCL_STOP */
		}
	}
#endif

	state_done(&state);
	tommy_list_foreach(&filterlist_file, (tommy_foreach_func*)filter_free);
	tommy_list_foreach(&filterlist_disk, (tommy_foreach_func*)filter_free);

	os_done();

	return EXIT_SUCCESS;
}
Esempio n. 4
0
int os_main(int argc, char* argv[])
{
	adv_crtc_container selected;
	adv_crtc_container_iterator i;
	const char* opt_rc;
	adv_bool opt_log;
	adv_bool opt_logsync;
	int j;
	adv_error res;
	char* section_map[1];
	char buffer[1024];

	opt_rc = 0;
	opt_log = 0;
	opt_logsync = 0;
	the_advance = advance_mame;
	the_sound_flag = 1;

	the_config = conf_init();

	if (os_init(the_config)!=0) {
		target_err("Error initializing the OS support.\n");
		goto err_conf;
	}

	video_reg(the_config, 1);
	monitor_register(the_config);
	crtc_container_register(the_config);
	generate_interpolate_register(the_config);
	gtf_register(the_config);
	inputb_reg(the_config, 1);
	inputb_reg_driver_all(the_config);
	
	/* MSDOS requires a special driver sub set */
#ifndef __MSDOS__
	video_reg_driver_all(the_config);
#endif

	if (conf_input_args_load(the_config, 1, "", &argc, argv, error_callback, 0) != 0)
		goto err_os;

	for(j=1;j<argc;++j) {
		if (target_option_compare(argv[j], "rc") && j+1<argc) {
			opt_rc = argv[++j];
		} else if (target_option_compare(argv[j], "log")) {
			opt_log = 1;
		} else if (target_option_compare(argv[j], "logsync")) {
			opt_logsync = 1;
		} else if (target_option_compare(argv[j], "nosound")) {
			the_sound_flag = 0;
		} else if (target_option_compare(argv[j], "advmamev")) {
			the_advance = advance_mame;
		} else if (target_option_compare(argv[j], "advmessv")) {
			the_advance = advance_mess;
		} else if (target_option_compare(argv[j], "advpacv")) {
			the_advance = advance_pac;
		} else if (target_option_compare(argv[j], "advmenuv")) {
			the_advance = advance_menu;
#ifdef __MSDOS__
		} else if (target_option_compare(argv[j], "vgav")) {
			the_advance = advance_vga;
		} else if (target_option_compare(argv[j], "vbev")) {
			the_advance = advance_vbe;
#endif
#ifdef __WIN32__
		} else if (target_option_compare(argv[j], "videowv")) {
			the_advance = advance_videow;
#endif
		} else {
			target_err("Unknown option %s\n", argv[j]);
			goto err;
		}
	}

#ifdef __MSDOS__
	/* WARNING the MSDOS drivers are registered after the command line management. */
	/* It implyes that you cannot specify any driver options on the command line */
	msdos_rut();

	if (the_advance == advance_vga) {
		if (the_advance_vga_active) {
			target_err("The AdvanceVGA utility is active. Disable it before running vgav.\n");
			goto err;
		}
		video_reg_driver(the_config, &video_vgaline_driver);
	} else if (the_advance == advance_vbe) {
		if (the_advance_vbe_active) {
			target_err("The AdvanceVBE utility is active. Disable it before running vbev.\n");
			goto err;
		}
		video_reg_driver(the_config, &video_vbeline_driver);
		video_reg_driver(the_config, &video_vgaline_driver); /* for the text modes */
	} else {
		video_reg_driver_all(the_config);
	}
#endif

	if (!opt_rc) {
		switch (the_advance) {
			case advance_vbe : opt_rc = "vbe.rc"; break;
			case advance_vga : opt_rc = "vga.rc"; break;
			case advance_menu : opt_rc = file_config_file_home("advmenu.rc"); break;
			case advance_mame : opt_rc = file_config_file_home("advmame.rc"); break;
			case advance_mess : opt_rc = file_config_file_home("advmess.rc"); break;
			case advance_pac : opt_rc = file_config_file_home("advpac.rc"); break;
			case advance_videow : opt_rc = file_config_file_home("videow.rc"); break;
			default : opt_rc = "advv.rc"; break;
		}
	}

	if (access(opt_rc, R_OK)!=0) {
		target_err("Configuration file %s not found.\n", opt_rc);
		goto err_os;
	}

	if (conf_input_file_load_adv(the_config, 0, opt_rc, opt_rc, 1, 1, STANDARD, sizeof(STANDARD)/sizeof(STANDARD[0]), error_callback, 0) != 0)
		goto err_os;

	if (opt_log || opt_logsync) {
		const char* log = "advv.log";
		remove(log);
		log_init(log, opt_logsync);
        }

	log_std(("v: %s %s\n", __DATE__, __TIME__));

	section_map[0] = "";
	conf_section_set(the_config, section_map, 1);

	if (video_load(the_config, "") != 0) {
		target_err("Error loading the video options from the configuration file %s.\n", opt_rc);
		target_err("%s\n", error_get());
		goto err_os;
	}

	if (inputb_load(the_config) != 0) {
		target_err("%s\n", error_get());
		goto err_os;
	}

	/* NOTE: After this command all the target_err() string must */
	/* have \n\r at the end to ensure correct newline in graphics mode. */

	if (os_inner_init("AdvanceVIDEO") != 0) {
		goto err_os;
	}

	if (adv_video_init() != 0) {
		target_err("%s\n\r", error_get());
		troubleshotting();
		goto err_os_inner;
	}

	if (video_blit_init() != 0) {
		target_err("%s\n\r", error_get());
		goto err_video;
	}

	if (the_advance != advance_vbe && the_advance != advance_vga) {
		if ((video_mode_generate_driver_flags(VIDEO_DRIVER_FLAGS_MODE_GRAPH_MASK, 0) & VIDEO_DRIVER_FLAGS_PROGRAMMABLE_CLOCK) == 0) {
			target_err("No active video driver is able to program your video board.\n\r");
			troubleshotting();
			goto err_blit;
		}
	}

	if (inputb_init() != 0) {
		target_err("%s\n\r", error_get());
		goto err_blit;
	}

	if (monitor_load(the_config, &the_monitor) != 0) {
		target_err("Error loading the clock options from the configuration file %s.\n\r", opt_rc);
		target_err("%s\n\r", error_get());
		goto err_input;
	}

	monitor_print(buffer, sizeof(buffer), &the_monitor);
	log_std(("v: clock %s\n", buffer));

	/* load generate_linear config */
	res = generate_interpolate_load(the_config, &the_interpolate);
	if (res<0) {
		target_err("Error loading the format options from the configuration file %s.\n\r", opt_rc);
		target_err("%s\n\r", error_get());
		goto err_input;
	}
	if (res>0) {
		generate_default_vga(&the_interpolate.map[0].gen);
		the_interpolate.map[0].hclock = 31500;
		the_interpolate.mac = 1;
	}

	/* load generate_linear config */
	res = gtf_load(the_config, &the_gtf);
	if (res<0) {
		target_err("Error loading the gtf options from the configuration file %s.\n\r", opt_rc);
		target_err("%s\n\r", error_get());
		goto err_input;
	}
	if (res>0) {
		gtf_default_vga(&the_gtf);
	}

	/* all mode */
	crtc_container_init(&selected);

	/* insert modes */
	crtc_container_insert_default_all(&selected);

	/* sort */
	crtc_container_init(&the_modes);
	for(crtc_container_iterator_begin(&i, &selected);!crtc_container_iterator_is_end(&i);crtc_container_iterator_next(&i)) {
		adv_crtc* crtc = crtc_container_iterator_get(&i);
		crtc_container_insert_sort(&the_modes, crtc, crtc_compare);
	}
	crtc_container_done(&selected);

	/* load selected */
	crtc_container_init(&selected);

	if (crtc_container_load(the_config, &selected) != 0) {
		target_err("%s\n\r", error_get());
		goto err_input;
	}

	/* union set */
	for(crtc_container_iterator_begin(&i, &selected);!crtc_container_iterator_is_end(&i);crtc_container_iterator_next(&i)) {
		adv_crtc* crtc = crtc_container_iterator_get(&i);
		adv_bool has = crtc_container_has(&the_modes, crtc, crtc_compare) != 0;
		if (has)
			crtc_container_remove(&the_modes, crtc_select_by_compare, crtc);
		crtc->user_flags |= MODE_FLAGS_USER_BIT0;
		crtc_container_insert_sort(&the_modes, crtc, crtc_compare);
	}
	crtc_container_done(&selected);

	the_modes_modified = 0;

	if (text_init(&the_modes, &the_monitor) != 0) {
		goto err_input;
	}

	if (inputb_enable(0) != 0) {
		goto err_text;
	}

	sound_signal();

	menu_run();

	log_std(("v: shutdown\n"));

	inputb_disable();

	text_done();

	crtc_container_done(&the_modes);

	inputb_done();

	video_blit_done();

	adv_video_done();

	os_inner_done();

	log_std(("v: the end\n"));

	if (opt_log || opt_logsync) {
		log_done();
	}

	os_done();

	conf_save(the_config, 0, 0, error_callback, 0);

	conf_done(the_config);

	return EXIT_SUCCESS;

err_text:
	text_done();
err_input:
	inputb_done();
err_blit:
	video_blit_done();
err_video:
	adv_video_done();
err_os_inner:
	os_inner_done();
err_os:
	if (opt_log || opt_logsync) {
		log_done();
	}
	os_done();
err_conf:
	conf_done(the_config);
err:
	return EXIT_FAILURE;
}
Esempio n. 5
0
int os_main(int argc, char* argv[])
{
	int i;
	adv_conf* context;
	const char* section_map[1];
	adv_bool opt_log;
	adv_bool opt_logsync;

	opt_log = 0;
	opt_logsync = 0;

	context = conf_init();

	if (os_init(context) != 0)
		goto err_conf;

	joystickb_reg(context, 1);
	joystickb_reg_driver_all(context);

	if (conf_input_args_load(context, 0, "", &argc, argv, error_callback, 0) != 0)
		goto err_os;

	for (i = 1; i < argc; ++i) {
		if (target_option_compare(argv[i], "log")) {
			opt_log = 1;
		} else if (target_option_compare(argv[i], "logsync")) {
			opt_logsync = 1;
		} else {
			fprintf(stderr, "Unknown argument '%s'\n", argv[1]);
			goto err_os;
		}
	}

	if (opt_log || opt_logsync) {
		const char* log = "advj.log";
		remove(log);
		log_init(log, opt_logsync);
	}

	log_std(("j: %s %s %s %s\n", "AdvanceJOYSTICK", ADV_VERSION, __DATE__, __TIME__));

	section_map[0] = "";
	conf_section_set(context, section_map, 1);

	if (joystickb_load(context) != 0)
		goto err_os;

	if (os_inner_init("AdvanceJOYSTICK") != 0)
		goto err_os;

	if (joystickb_init() != 0) {
		target_err("%s\n", error_get());
		goto err_os_inner;
	}

	probe();
	calibrate();
	run();

	joystickb_done();
	os_inner_done();

	log_std(("j: the end\n"));

	if (opt_log || opt_logsync) {
		log_done();
	}

	os_done();
	conf_done(context);

	return EXIT_SUCCESS;

err_os_inner:
	os_inner_done();
	log_done();
err_os:
	os_done();
err_conf:
	conf_done(context);
	return EXIT_FAILURE;
}