int main ( int argc , char ** argv ) {
	
	if(argc != 3 ) {		
		
		printf("Usage %s file.in file.out\n" , argv[0] );
		return 0;
	}
	
	/* Inits */
	BM_init();
	flags_init();
	/* END Inits */
	
	/* Read input */
	FILE * fin = fopen ( argv[1] , "r");
	FILE * fout = fopen ( argv[2] , "w" );
	STATE p_st = state_read ( fin );
	//state_print(p_st,fout);
	
	STATE n_st = state_read ( fin );
	//state_print(n_st,fout);
	fclose(fin);
	/* END Read Input */
	
	/* Sets */
	cur_state_set ( p_st );
	/* END Sets */
	
	/* Output */
	
	move_print ( determine_move ( n_st ) , fout );
	fclose(fout);
	cur_state_free();
	/* END Output */
	
	
	return 0;
}
Exemple #2
0
void view_load(view *V, const char *name)
{
    FILE *fp;

    if ((fp = fopen(name, "r")))
    {
        state s;

        while (state_read(fp, &s))
            state_insert(V, V->n, &s);

        fclose(fp);
    }
}
Exemple #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;
}
int main(int argc, char **argv) {
	int ret, i;

	FILE *cfg = cfg_open();
	char *statedir = cfg_get_default(cfg, "statedir", STATEDIR);
	cfg_close(cfg);

	for (i = 0; gpios[i].dev; i++) {
		int err = gpio_init(&gpios[i]);
		if (err) {
			fprintf(stderr, "could not init gpio \"%s\": %d!\n", gpios[i].name, err);
			return 1;
		}
	}

	char buffer[EVENT_BUF_LEN];

	state.fd = inotify_init();
	if(state.fd < 0) {
		fprintf(stderr, "Could not init inotify!\n");
		return 1;
	}

	ret = mkdir(statedir, 0775);
	if (ret < 0 && errno != EEXIST) {
		fprintf(stderr, "Could not create statedir: %d\n", ret);
		return 1;
	}

	ret = chmod(statedir, 0775);
	if (ret < 0) {
		fprintf(stderr, "Cannot fix rights on statedir: %d\n", ret);
		return 1;
	}

	state.wd = inotify_add_watch(state.fd, statedir, IN_MODIFY | IN_DELETE);

	state.doorstate = DOOR_UNKNOWN;

	for(;;) {
		int len = read(state.fd, buffer, EVENT_BUF_LEN);
		sleep(1);
		len = read(state.fd, buffer, EVENT_BUF_LEN);

		if(!state_read(statedir, &state.keyholder_id, &state.keyholder_name, &state.status, &state.message)) {
			fprintf(stderr, "Could not read state!\n");
			return 1;
		}

		printf("new state: id=%d name=%s status=%d message=%s\n", state.keyholder_id, state.keyholder_name, state.status, state.message);

		switch(state.status) {
			case STATE_NONE:
				lock();
				state.doorstate = DOOR_LOCKED;
				break;
			case STATE_KEYHOLDER:
			case STATE_MEMBER:
			case STATE_OPEN:
			case STATE_OPEN_PLUS:
				unlock();
				state.doorstate = DOOR_UNLOCKED;
				break;
			case STATE_UNKNOWN:
			default:
				state.doorstate = DOOR_UNKNOWN;
				break;
		}

		free(state.keyholder_name);
		free(state.message);
	}

	inotify_rm_watch(state.fd, state.wd);
	close(state.fd);
}
Exemple #5
0
u8 *cmd_restore_game(u8 *c)
{
	u8 *code_ret;	// result to pass at the end
	u8 newline_orig;	// d0d orig
	FILE *rest_stream;
	//u8 msg[200];
	u8 *msg;
	
	clock_state = 1;
	code_ret = c;
	newline_orig = msgstate.newline_char;
	msgstate.newline_char = '@';
	
	if (save_dir == 0)
		save_dir = vstring_new(0, 200);
	if (save_filename == 0)
		save_filename = vstring_new(0, 250);
	
	if (state_get_info('r') != 0)
	{
		if (strlen(save_filename->data) > strlen(save_dir->data))
			msg = alloca(200 + strlen(save_filename->data));
		else
			msg = alloca(200 + strlen(save_dir->data));
		if (state_name_auto[0] == 0)
		{
			sprintf(msg, "About to restore the game\ndescribed as:\n\n%s\n\nfrom file:\n %s\n\n%s",
				save_description, save_filename->data, "Press ENTER to continue.\nPress ESC to cancel.");
			message_box_draw(msg, 0, 0x23, 0);
			if ( user_bolean_poll() == 0)
				goto rest_end;
		}
		dir_preset_change(DIR_PRESET_GAME);
		rest_stream = fopen(save_filename->data, "rb");
		if ( rest_stream == 0)
		{
			sprintf(msg, "Can't open file:\n %s", save_filename->data);
			message_box(msg);
		}
		else
		{
			fseek(rest_stream, 0x1F, SEEK_SET);
			if (state_read(rest_stream, &state) == 0)
				goto loc2630;
			if (state_read(rest_stream, objtable) == 0)
				goto loc2630;
			if (state_read(rest_stream, inv_obj_table) == 0)
				goto loc2630;
			if (state_read(rest_stream, inv_obj_string) == 0)
				goto loc2630;
			if (state_read(rest_stream, script_head) == 0)
				goto loc2630;
			if (state_read(rest_stream, scan_start_list) != 0)
				goto loc2647;
		loc2630:
			fclose(rest_stream);
			message_box("Error in restoring game.\nPress ENTER to quit.");
			agi_exit();  // can't recover.. we possibly just overwrote some of the
					// structures with stuff
		loc2647:
			fclose(rest_stream);
			decrypt_string(inv_obj_string, inv_obj_string+inv_obj_string_size);
			state.var[V20_COMPUTER] = computer_type;
			state.var[V26_MONITORTYPE] = display_type;
			state.var[V08_FREEMEM] = 10;
			
			if (computer_type == 0)
				state.var[V22_SNDTYPE] = 1;
			else
			{
				state.var[V22_SNDTYPE] = 3;
				flag_set(F11_NEWLOGIC0);
			}
			state_reload();
			control_state_clear();
			flag_set(F12_RESTORE);
			volumes_close();
			code_ret = 0;
			menu_enable_all();
		}
	}
rest_end:
	cmd_close_window(0);
	msgstate.newline_char = newline_orig;
	clock_state = 0;
	return code_ret;
}