Пример #1
0
int main(int argc, char *argv[])
{
	switch (argc) {
		case 1:
			printf("%i\n", getuid());
			return 0;

		case 2:
			if (!strcmp(argv[1], "-h"))
				return usage(0);

			if (*argv[1] == '-') {
				const char *name = argv[1] + 1;
				struct passwd *pwd = getpwnam(name);
				if (!pwd)
					errp("getpwnam(%s) failed", name);
				printf("%i\n", pwd->pw_uid);
			} else {
				const char *file = argv[1];
				struct stat st;
				if (lstat(file, &st))
					errp("lstat(%s) failed", file);
				printf("%i\n", st.st_uid);
			}
			return 0;
	}

	return usage(1);
}
Пример #2
0
/*
 * re/start kernel threads
 */
void
cpr_start_kernel_threads(void)
{
	DEBUG1(errp("starting kernel daemons..."));
	(void) callb_execute_class(CB_CL_CPR_DAEMON, CB_CODE_CPR_RESUME);
	DEBUG1(errp("done\n"));

	/* see table lock below */
	callb_unlock_table();
}
Пример #3
0
/*
 * Checks and makes sure all user threads are stopped
 */
static int
cpr_check_user_threads()
{
	kthread_id_t tp;
	int rc = 0;

	mutex_enter(&pidlock);
	tp = curthread->t_next;
	do {
		if (ttoproc(tp)->p_as == &kas || ttoproc(tp)->p_stat == SZOMB)
			continue;

		thread_lock(tp);
		/*
		 * make sure that we are off all the queues and in a stopped
		 * state.
		 */
		if (!CPR_ISTOPPED(tp)) {
			thread_unlock(tp);
			mutex_exit(&pidlock);

			if (count == CPR_UTSTOP_RETRY) {
			DEBUG1(errp("Suspend failed: cannt stop "
				"uthread\n"));
			cpr_err(CE_WARN, "Suspend cannot stop "
				"process %s (%p:%x).",
				ttoproc(tp)->p_user.u_psargs, (void *)tp,
				tp->t_state);
			cpr_err(CE_WARN, "Process may be waiting for"
				" network request, please try again.");
			}

			DEBUG2(errp("cant stop t=%p state=%x pfg=%x sched=%x\n",
			tp, tp->t_state, tp->t_proc_flag, tp->t_schedflag));
			DEBUG2(errp("proc %p state=%x pid=%d\n",
				ttoproc(tp), ttoproc(tp)->p_stat,
				ttoproc(tp)->p_pidp->pid_id));
			return (1);
		}
		thread_unlock(tp);

	} while ((tp = tp->t_next) != curthread && rc == 0);

	mutex_exit(&pidlock);
	return (0);
}
Пример #4
0
static int file_open(struct tcmu_device *dev)
{
	struct file_state *state;
	int64_t size;
	char *config;

	state = calloc(1, sizeof(*state));
	if (!state)
		return -ENOMEM;

	tcmu_set_dev_private(dev, state);

	state->block_size = tcmu_get_attribute(dev, "hw_block_size");
	if (state->block_size == -1) {
		errp("Could not get device block size\n");
		goto err;
	}

	size = tcmu_get_device_size(dev);
	if (size == -1) {
		errp("Could not get device size\n");
		goto err;
	}

	state->num_lbas = size / state->block_size;

	config = strchr(tcmu_get_dev_cfgstring(dev), '/');
	if (!config) {
		errp("no configuration found in cfgstring\n");
		goto err;
	}
	config += 1; /* get past '/' */

	state->fd = open(config, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
	if (state->fd == -1) {
		errp("could not open %s: %m\n", config);
		goto err;
	}

	return 0;

err:
	free(state);
	return -EINVAL;
}
Пример #5
0
/*
 * Stop kernel threads by using the callback mechanism.  If any thread
 * cannot be stopped, return failure.
 */
int
cpr_stop_kernel_threads(void)
{
	caddr_t	name;
	kthread_id_t tp;
	proc_t *p;

	callb_lock_table();	/* Note: we unlock the table in resume. */

	DEBUG1(errp("stopping kernel daemons..."));
	if ((name = callb_execute_class(CB_CL_CPR_DAEMON,
	    CB_CODE_CPR_CHKPT)) != (caddr_t)NULL) {
		cpr_err(CE_WARN,
		    "Could not stop \"%s\" kernel thread.  "
		    "Please try again later.", name);
		return (EBUSY);
	}

	/*
	 * We think we stopped all the kernel threads.  Just in case
	 * someone is not playing by the rules, take a spin through
	 * the threadlist and see if we can account for everybody.
	 */
	mutex_enter(&pidlock);
	tp = curthread->t_next;
	do {
		p = ttoproc(tp);
		if (p->p_as != &kas)
			continue;

		if (tp->t_flag & T_INTR_THREAD)
			continue;

		if (! callb_is_stopped(tp, &name)) {
			mutex_exit(&pidlock);
			cpr_err(CE_WARN,
			    "\"%s\" kernel thread not stopped.", name);
			return (EBUSY);
		}
	} while ((tp = tp->t_next) != curthread);
	mutex_exit(&pidlock);

	DEBUG1(errp("done\n"));
	return (0);
}
Пример #6
0
static int foo_handle_cmd(
	struct tcmu_device *dev,
	uint8_t *cdb,
	struct iovec *iovec,
	size_t iov_cnt,
	uint8_t *sense)
{
	struct foo_state *state = tcmu_get_dev_private(dev);
	uint8_t cmd;

	cmd = cdb[0];

	switch (cmd) {
	case INQUIRY:
		return tcmu_emulate_inquiry(dev, cdb, iovec, iov_cnt, sense);
		break;
	case TEST_UNIT_READY:
		return tcmu_emulate_test_unit_ready(cdb, iovec, iov_cnt, sense);
		break;
	case SERVICE_ACTION_IN_16:
		if (cdb[1] == READ_CAPACITY_16)
			return tcmu_emulate_read_capacity_16(state->num_lbas,
							     state->block_size,
							     cdb, iovec, iov_cnt, sense);
		else
			return TCMU_NOT_HANDLED;
		break;
	case MODE_SENSE:
	case MODE_SENSE_10:
		return tcmu_emulate_mode_sense(cdb, iovec, iov_cnt, sense);
		break;
	case MODE_SELECT:
	case MODE_SELECT_10:
		return tcmu_emulate_mode_select(cdb, iovec, iov_cnt, sense);
		break;
	case READ_6:
	case READ_10:
	case READ_12:
	case READ_16:
		// A real "read" implementation goes here!
		return set_medium_error(sense);

	case WRITE_6:
	case WRITE_10:
	case WRITE_12:
	case WRITE_16:
		// A real "write" implemention goes here!
		return SAM_STAT_GOOD;

	default:
		errp("unknown command %x\n", cdb[0]);
		return TCMU_NOT_HANDLED;
	}
}
Пример #7
0
// This function updates the shared memory with the outputs of the simulink model
void Airdata_SFL_UpdateOutputs()
{
	// Declare output data structures from the model
	// static: Memory will stay allocated and can be used in next call to the function
	static airdata_t	_airdata;	// Airdata output structure
	v3_t tas_alpha_beta;
	clock_gettime( CLOCK_REALTIME, &_airdata.timestamp);

	// Read data from simulink model
	_airdata.IAS 			= airdata[0];
	_airdata.CAS 			= airdata[1];
	_airdata.EAS 			= airdata[2];
	_airdata.TAS 			= airdata[3];
	_airdata.altitude 		= airdata[4];
	_airdata.alpha 			= airdata[5];
	_airdata.beta 			= airdata[6];
	_airdata.temperature 	= airdata[7];
	_airdata.voltage = airdata_sfl_data.voltage;
	_airdata.status = airdata_sfl_data.status;
	tas_alpha_beta.timestamp.tv_sec = _airdata.timestamp.tv_sec;
	tas_alpha_beta.timestamp.tv_nsec = _airdata.timestamp.tv_nsec;
	tas_alpha_beta.val[0] = _airdata.TAS;
	tas_alpha_beta.val[1] = _airdata.alpha;
	tas_alpha_beta.val[2] = _airdata.beta;

	// Output debug data
    dprintf("airdata_sfl: IAS = %f, CAS = %f\n EAS = %f, TAS = %f\n alpha = %f, beta = %f\n\n\n",
    		_airdata.IAS,
    		_airdata.CAS,
    		_airdata.EAS,
    		_airdata.TAS,
    		_airdata.alpha,
    		_airdata.beta
    	   );

	// Write data to shared memory slot
	// errp				Check for errors in function calls
	// SHM_WriteSlot	Write data to public slot
	errp(SHM_WriteSlot(cfg.shm_out_airdata, &_airdata, sizeof(_airdata)));
	errp(SHM_WriteSlot(cfg.shm_out_tas_alpha_beta, &tas_alpha_beta, sizeof(tas_alpha_beta)));
}
Пример #8
0
const char *qpkg_get_bindir(void)
{
	if (qpkg_bindir != NULL)
		return qpkg_bindir;
	if (getuid() == 0)
		return "/var/tmp/binpkgs";
	if (getenv("HOME") == NULL)
		errp("Your $HOME env var isn't set, aborting");
	xasprintf(&qpkg_bindir, "%s/binpkgs", getenv("HOME"));

	return qpkg_bindir;
}
Пример #9
0
void safe_timer(long long *tm, int period_mcs)
{
	uint64_t time_now;
	uint64_t period_ns;
	struct timespec wake_up_time;
	long long *dummy;
	
	dummy = tm;
	
	ifperrs(ClockTime(CLOCK_MONOTONIC, NULL, &time_now) == -1, AR_ERR_SYS_RESOURCES, strerror(errno));
	period_ns = period_mcs*1000;
	time_now = time_now - time_now % period_ns + period_ns; 
	wake_up_time.tv_sec = time_now/1000000000LL;
	wake_up_time.tv_nsec = time_now % 1000000000LL;
	
	errp(clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &wake_up_time, NULL));
}
Пример #10
0
/*
 * CPU ONLINE/OFFLINE CODE
 */
int
cpr_mp_offline(void)
{
	cpu_t *cp, *bootcpu;
	int rc = 0;
	int brought_up_boot = 0;

	/*
	 * Do nothing for UP.
	 */
	if (ncpus == 1)
		return (0);

	mutex_enter(&cpu_lock);

	cpr_save_mp_state();

	bootcpu = i_cpr_bootcpu();
	if (!CPU_ACTIVE(bootcpu)) {
		if ((rc = cpr_p_online(bootcpu, CPU_CPR_ONLINE))) {
			mutex_exit(&cpu_lock);
			return (rc);
		}
		brought_up_boot = 1;
	}

	cp = cpu_list;
	do {
		if (cp == bootcpu)
			continue;
		if (cp->cpu_flags & CPU_OFFLINE)
			continue;
		if ((rc = cpr_p_online(cp, CPU_CPR_OFFLINE))) {
			mutex_exit(&cpu_lock);
			return (rc);
		}
	} while ((cp = cp->cpu_next) != cpu_list);
	if (brought_up_boot && (cpr_debug & (LEVEL1 | LEVEL6)))
		errp("changed cpu %p to state %d\n", bootcpu, CPU_CPR_ONLINE);
	mutex_exit(&cpu_lock);

	return (rc);
}
Пример #11
0
static void * corr_data_thread_func(void*  arg)
{
	char			buffer[MAX_GPS_CORRECTION_SIZE];
	int				err;
	gps_corr_t		gps_corr;
	int				received_bytes;
    struct termios 	termios_p;

	if(config.queue_corr_data == 0) {
    	if(tcgetattr(fd_corr_data_read, &termios_p)==0) {
    		termios_p.c_cc[VTIME] = 5; // 2*0.1s = 0.2s
    		termios_p.c_cc[VMIN] = 1;
    		tcsetattr(fd_corr_data_read, TCSADRAIN, &termios_p);
    	}
    }

	while(1) {
		if(config.queue_corr_data != 0) {
			memset(&gps_corr, 0, sizeof(gps_corr));
			errp(Q_ReadSlot(config.queue_corr_data, &gps_corr, sizeof(gps_corr), &received_bytes));
			gps_corr.size = ntohl(gps_corr.size);
			ifperr(gps_corr.size > MAX_GPS_CORRECTION_SIZE, AR_ERR_CONSI);
//			fprintf(stderr, "got <%d> bytes from queue, <%d> bytes corr. data\n", received_bytes, gps_corr.size);
			err = write(fd, gps_corr.buffer, gps_corr.size);
//			fprintf(stderr, "    wrote <%d> bytes to fd\n", err);
			if(err != gps_corr.size) {
				perrs(AR_ERR_IO_ERROR, "can not write GPS corr. data from queue to ser. device\n");
			}
		} else {
			err = read(fd_corr_data_read, buffer, MAX_GPS_CORRECTION_SIZE);
			if(err>0) {
				err = write(fd, buffer, err);
				if(err <= 0) {
					perrs(AR_ERR_IO_ERROR, "can not write GPS corr. data from ser. device to ser. device\n");
				}
				//fprintf(stderr, "    wrote <%d> bytes to fd\n", err);
			} else if (err < 0) {
				perrs(AR_ERR_IO_ERROR, "can not read GPS corr. data from ser. device\n");
			}
		}
	}
	return 0;
}
Пример #12
0
// This function updates the inputs to the simulink model
void Airdata_SFL_UpdateInputs()
{
	// Declare input data structures to the model

	// !!!! CHANGE THIS HERE!!!
	// Read airdata from shared memory
	// -> errp					Makro from ar_err library to check for errors
	// -> SHM_Priv_ReadSlot		Reads data from private (only to this process) shared memory slot
	errp(SHM_Priv_ReadSlot(AR_SHM_PRIV_SLOT_AIRDATA_SFL, &airdata_sfl_data, sizeof(airdata_sfl_data)));

	// Set data in simulation from structure
	airdata_sfl_P.IAS_S_Value 			= airdata_sfl_data.IAS;
	airdata_sfl_P.TAS_S_Value 			= airdata_sfl_data.TAS;
	airdata_sfl_P.altitude_S_Value		= airdata_sfl_data.altitude;
	airdata_sfl_P.alpha_S_Value 		= airdata_sfl_data.alpha;
	airdata_sfl_P.beta_S_Value 			= airdata_sfl_data.beta;
	airdata_sfl_P.temperature_S_Value 	= airdata_sfl_data.temperature;
	airdata_sfl_P.voltage_S_Value 		= airdata_sfl_data.voltage;
	airdata_sfl_P.status_S_Value 		= airdata_sfl_data.status;
}
Пример #13
0
void read_corr_data_loop()
{
	int				err;
	gps_corr_t		gps_corr;

	struct termios 	termios_p;
	if(tcgetattr(fd, &termios_p)==0) {
		termios_p.c_cc[VTIME] = 5; // 2*0.1s = 0.2s
		termios_p.c_cc[VMIN] = 1;
		tcsetattr(fd, TCSANOW, &termios_p);
	}

	while(1) {
		memset(&gps_corr, 0, sizeof(gps_corr));
		err = read(fd, gps_corr.buffer, MAX_GPS_CORRECTION_SIZE);
		if(err>0) {
			//printf("len=%i\n",err);
			gps_corr.size = htonl(err);
			errp(Q_WriteSlot(config.queue_corr_data_1, &gps_corr, sizeof(gps_corr.size) + err));
			if(config.queue_corr_data_2 != 0) {
				errp(Q_WriteSlot(config.queue_corr_data_2, &gps_corr, sizeof(gps_corr.size) + err));
			}
			if(config.queue_corr_data_3 != 0) {
				errp(Q_WriteSlot(config.queue_corr_data_3, &gps_corr, sizeof(gps_corr.size) + err));
			}
			if(config.queue_corr_data_4 != 0) {
				errp(Q_WriteSlot(config.queue_corr_data_4, &gps_corr, sizeof(gps_corr.size) + err));
			}
			if(config.queue_corr_data_5 != 0) {
				errp(Q_WriteSlot(config.queue_corr_data_5, &gps_corr, sizeof(gps_corr.size) + err));
			}
			if(config.queue_corr_data_6 != 0) {
				errp(Q_WriteSlot(config.queue_corr_data_6, &gps_corr, sizeof(gps_corr.size) + err));
			}
			safe_timer(NULL, 10000);
		} else {
			gps_corr.size = 0;
			perrs(AR_ERR_IO_ERROR, "can not read GPS corr. data from ser. device\n");
		}
	}
}
Пример #14
0
static int
qglsa_run_action(const char *overlay, qglsa_action action, const char *fixed_list,
                 bool all_glsas, unsigned int ind, int argc, char **argv)
{
	int i;
	DIR *dir;
	struct dirent *dentry;
	char *buf;
	size_t buflen = 0;
	char *s, *p;
	int overlay_fd, glsa_fd;

	overlay_fd = open(overlay, O_RDONLY|O_CLOEXEC|O_PATH);
	glsa_fd = openat(overlay_fd, "metadata/glsa", O_RDONLY|O_CLOEXEC);

	switch (action) {
	/*case GLSA_FIX:*/
	case GLSA_INJECT:
		buf = NULL;
		for (i = ind; i < argc; ++i) {
			free(buf);
			xasprintf(&buf, "glsa-%s.xml", argv[i]);
			if (faccessat(glsa_fd, buf, R_OK, 0)) {
				warnp("Skipping invalid GLSA '%s'", argv[i]);
				continue;
			}
			if (fixed_list) {
				if (strstr(fixed_list, argv[i])) {
					warn("Skipping already installed GLSA %s", argv[i]);
					continue;
				}
			}
			if (action == GLSA_FIX) {
				printf("Fixing GLSA %s%s%s\n", GREEN, argv[i], NORM);
				continue;
			} else if (action == GLSA_INJECT)
				printf("Injecting GLSA %s%s%s\n", GREEN, argv[i], NORM);
			qglsa_append_to_list(argv[i]);
		}
		free(buf);
		break;

	default:
		if ((dir = fdopendir(glsa_fd)) == NULL)
			return EXIT_FAILURE;

		buf = NULL;
		buflen = 0;
		while ((dentry = readdir(dir)) != NULL) {
			/* validate this file as a proper glsa */
			char glsa_id[20];
			if (strncmp(dentry->d_name, "glsa-", 5))
				continue;
			if ((s = strchr(dentry->d_name, '.')) == NULL || memcmp(s, ".xml\0", 5))
				continue;
			size_t len = s - dentry->d_name;
			if (len >= sizeof(glsa_id) || len <= 5)
				continue;
			memcpy(glsa_id, dentry->d_name + 5, len - 5);
			glsa_id[len - 5] = '\0';

			/* see if we want to skip glsa's already fixed */
			if (!all_glsas && fixed_list) {
				if (strstr(fixed_list, glsa_id))
					continue;
			}

			/* load the glsa into memory */
			if (!eat_file_at(glsa_fd, dentry->d_name, &buf, &buflen))
				errp("could not eat %s", dentry->d_name);

			/* now lets figure out what to do with this memory */
			switch (action) {
			case GLSA_LIST:
				s = qglsa_get_xml_tag(buf, "title");
				printf("%s%s%s: %s", GREEN, glsa_id, NORM, s);
				if (verbose) {
					int num_shown = 0;
					p = qglsa_get_xml_tag(buf, "affected");
					if (p) {
						printf(" (");
						while (p++) {
							s = qglsa_get_xml_tag_attribute(p, "package", "name");
							if (s) {
								if (verbose < 2 && ++num_shown > 3) {
									printf(" ...");
									break;
								}
								printf(" %s", s);
							} else
								break;
							p = strstr(p, "</package>");
						}
						printf(" )");
					}
				}
				printf("\n");
				break;
			case GLSA_DUMP:
				s = qglsa_get_xml_tag(buf, "title");
				printf("%s%s%s: %s\n", GREEN, glsa_id, NORM, s);
				s = qglsa_get_xml_tag(buf, "bug");
				printf("  %sRef%s: http://bugs.gentoo.org/%s\n", BLUE, NORM, s);
				s = qglsa_get_xml_tag(buf, "access");
				printf("  %saccess%s: %s\n", BLUE, NORM, s);
				s = qglsa_get_xml_tag(buf, "synopsis");
				printf("  %ssynopsis%s:\n%s\n", BLUE, NORM, s);
				s = qglsa_get_xml_tag(buf, "affected");
				printf("  %saffected%s:\n%s\n", BLUE, NORM, s);
				if (verbose) {
					s = qglsa_get_xml_tag(buf, "description");
					printf("  %sdescription%s:\n%s\n", BLUE, NORM, s);
					s = qglsa_get_xml_tag(buf, "workaround");
					printf("  %sworkaround%s:\n%s\n", BLUE, NORM, s);
				}
				break;
			}
		}
		closedir(dir);
	}

	close(glsa_fd);
	close(overlay_fd);

	return EXIT_SUCCESS;
}
Пример #15
0
int qpkg_main(int argc, char **argv)
{
	q_vdb_ctx *ctx;
	q_vdb_cat_ctx *cat_ctx;
	q_vdb_pkg_ctx *pkg_ctx;
	size_t s, pkgs_made;
	int i;
	struct stat st;
	char buf[BUFSIZE];
	const char *bindir;
	depend_atom *atom;
	int restrict_chmod = 0;
	int qclean = 0;

	while ((i = GETOPT_LONG(QPKG, qpkg, "")) != -1) {
		switch (i) {
		case 'E': eclean = qclean = 1; break;
		case 'c': qclean = 1; break;
		case 'p': pretend = 1; break;
		case 'P':
			restrict_chmod = 1;
			free(qpkg_bindir);
			qpkg_bindir = xstrdup(optarg);
			if (access(qpkg_bindir, W_OK) != 0)
				errp("%s", qpkg_bindir);
			break;
		COMMON_GETOPTS_CASES(qpkg)
		}
	}
	if (qclean)
		return qpkg_clean(qpkg_bindir == NULL ? pkgdir : qpkg_bindir);

	if (argc == optind)
		qpkg_usage(EXIT_FAILURE);

	/* setup temp dirs */
	i = 0;
	bindir = qpkg_get_bindir();
	if (*bindir != '/')
		err("'%s' is not a valid package destination", bindir);
retry_mkdir:
	if (mkdir(bindir, 0750) == -1) {
		lstat(bindir, &st);
		if (!S_ISDIR(st.st_mode)) {
			unlink(bindir);
			if (!i++) goto retry_mkdir;
			errp("could not create temp bindir '%s'", bindir);
		}
		if (!restrict_chmod)
			if (chmod(bindir, 0750))
				errp("could not chmod(0750) temp bindir '%s'", bindir);
	}

	/* we have to change to the root so that we can feed the full paths
	 * to tar when we create the binary package. */
	xchdir(portroot);

	/* first process any arguments which point to /var/db/pkg */
	pkgs_made = 0;
	s = strlen(portvdb);
	for (i = optind; i < argc; ++i) {
		size_t asize = strlen(argv[i]);
		if (asize == 0) {
			argv[i] = NULL;
			continue;
		}
		if (argv[i][asize-1] == '/')
			argv[i][asize-1] = '\0';
		if (!strncmp(portvdb, argv[i], s))
			memmove(argv[i], argv[i]+s+1, asize-s);
		else if (argv[i][0] == '/' && !strncmp(portvdb, argv[i]+1, s))
			memmove(argv[i], argv[i]+s+2, asize-s-1);
		else
			continue;

		atom = atom_explode(argv[i]);
		if (atom) {
			if (!qpkg_make(atom)) ++pkgs_made;
			atom_implode(atom);
		} else
			warn("could not explode '%s'", argv[i]);
		argv[i] = NULL;
	}

	/* now try to run through vdb and locate matches for user inputs */
	ctx = q_vdb_open(portroot, portvdb);
	if (!ctx)
		return EXIT_FAILURE;

	/* scan all the categories */
	while ((cat_ctx = q_vdb_next_cat(ctx))) {
		/* scan all the packages in this category */
		const char *catname = cat_ctx->name;
		while ((pkg_ctx = q_vdb_next_pkg(cat_ctx))) {
			const char *pkgname = pkg_ctx->name;

			/* see if user wants any of these packages */
			snprintf(buf, sizeof(buf), "%s/%s", catname, pkgname);
			atom = atom_explode(buf);
			if (!atom) {
				warn("could not explode '%s'", buf);
				goto next_pkg;
			}
			snprintf(buf, sizeof(buf), "%s/%s", atom->CATEGORY, atom->PN);
			for (i = optind; i < argc; ++i) {
				if (!argv[i]) continue;

				if (!strcmp(argv[i], atom->PN) ||
						!strcmp(argv[i], atom->P) ||
						!strcmp(argv[i], buf) ||
						!strcmp(argv[i], "world"))
					if (!qpkg_make(atom))
						++pkgs_made;
			}
			atom_implode(atom);

 next_pkg:
			q_vdb_close_pkg(pkg_ctx);
		}
	}

	s = (argc - optind) - pkgs_made;
	if (s && !pretend)
		printf(" %s*%s %i package%s could not be matched :/\n",
				RED, NORM, (int)s, (s > 1 ? "s" : ""));
	if (pkgs_made)
		qprintf(" %s*%s Packages can be found in %s\n", GREEN, NORM, bindir);

	return (pkgs_made ? EXIT_SUCCESS : EXIT_FAILURE);
}
Пример #16
0
int qsearch_main(int argc, char **argv)
{
	FILE *fp;
	char *ebuild = NULL;
	char last[126] = "";
	char *p, *q, *str;
	char *search_me = NULL;
	char show_homepage = 0, show_name_only = 0;
	char search_desc = 0, search_all = 0, search_name = 1, search_cache = CACHE_EBUILD;
	const char *search_vars[] = { "DESCRIPTION=", "HOMEPAGE=" };
	size_t search_len, ebuild_len;
	int i, idx=0;

	DBG("argc=%d argv[0]=%s argv[1]=%s",
	    argc, argv[0], argc > 1 ? argv[1] : "NULL?");

	while ((i = GETOPT_LONG(QSEARCH, qsearch, "")) != -1) {
		switch (i) {
		COMMON_GETOPTS_CASES(qsearch)
		case 'a': search_all = 1; break;
		case 'c': search_cache = CACHE_METADATA; break;
		case 'e': search_cache = CACHE_EBUILD; break;
		case 's': search_desc = 0; search_name = 1; break;
		case 'S': search_desc = 1; search_name = 0; break;
		case 'N': show_name_only = 1; break;
		case 'H': show_homepage = 1, idx = 1; break;
		}
	}

	if (search_all) {
		search_desc = 1;
		search_name = 0;
	} else {
		if (argc == optind)
			qsearch_usage(EXIT_FAILURE);
		search_me = argv[optind];
	}
#ifdef TESTING
	/* FIXME: hardcoded */
	if ((search_cache == CACHE_EBUILD) && (access("/usr/portage/.qsearch.x", R_OK) == 0)) {
		if ((fp = fopen("/usr/portage/.qsearch.x", "r")) != NULL) {
			search_len = strlen(search_me);
			while (fgets(buf, sizeof(buf), fp) != NULL) {
				if (strlen(buf) <= search_len)
					continue;
				/* add regexp, color highlighting and basename checks */
				if (strncmp(buf, search_me, search_len) == 0) {
					fputs(buf, stdout);
				}
			}
			fclose(fp);
			return 0;
		}
	}
#endif
	last[0] = 0;
	fp = fopen(initialize_flat(search_cache, false), "r");
	if (!fp)
		return 1;

	int portdir_fd = open(portdir, O_RDONLY|O_CLOEXEC|O_PATH);
	if (portdir_fd < 0)
		errp("open(%s) failed", portdir);

	q = NULL; /* Silence a gcc warning. */
	search_len = strlen(search_vars[idx]);

	while (getline(&ebuild, &ebuild_len, fp) != -1) {
		if ((p = strchr(ebuild, '\n')) != NULL)
			*p = 0;
		if (!ebuild[0])
			continue;

		switch (search_cache) {

		case CACHE_METADATA: {
			portage_cache *pcache;
			if ((pcache = cache_read_file(ebuild)) != NULL) {
				if (strcmp(pcache->atom->PN, last) != 0) {
					strncpy(last, pcache->atom->PN, sizeof(last));
					if ((rematch(search_me, (search_desc ? pcache->DESCRIPTION : ebuild), REG_EXTENDED | REG_ICASE) == 0) || search_all)
						printf("%s%s/%s%s%s %s\n", BOLD, pcache->atom->CATEGORY, BLUE,
						       pcache->atom->PN, NORM,
						       (show_name_only ? "" :
						        (show_homepage ? pcache->HOMEPAGE : pcache->DESCRIPTION)));
				}
				cache_free(pcache);
			} else {
				if (!reinitialize)
					warnf("(cache update pending) %s", ebuild);
				reinitialize = 1;
			}
			break;
		}

		case CACHE_EBUILD: {
			FILE *ebuildfp;
			str = xstrdup(ebuild);
			p = dirname(str);

			if (strcmp(p, last) != 0) {
				bool show_it = false;
				strncpy(last, p, sizeof(last));
				if (search_name) {
					if (rematch(search_me, basename(last), REG_EXTENDED | REG_ICASE) != 0) {
						goto no_cache_ebuild_match;
					} else {
						q = NULL;
						show_it = true;
					}
				}

				int fd = openat(portdir_fd, ebuild, O_RDONLY|O_CLOEXEC);
				if (fd != -1) {
					ebuildfp = fdopen(fd, "r");
					if (ebuildfp == NULL) {
						close(fd);
						continue;
					}
				} else {
					if (!reinitialize)
						warnfp("(cache update pending) %s", ebuild);
					reinitialize = 1;
					goto no_cache_ebuild_match;
				}

				char *buf = NULL;
				size_t buflen;
				while (getline(&buf, &buflen, ebuildfp) != -1) {
					if (strlen(buf) <= search_len)
						continue;
					if (strncmp(buf, search_vars[idx], search_len) != 0)
						continue;
					if ((q = strrchr(buf, '"')) != NULL)
						*q = 0;
					if (strlen(buf) <= search_len)
						break;
					q = buf + search_len + 1;
					if (!search_all && !search_name && rematch(search_me, q, REG_EXTENDED | REG_ICASE) != 0)
						break;
					show_it = true;
					break;
				}

				if (show_it) {
					printf("%s%s/%s%s%s %s\n",
						BOLD, dirname(p), BLUE, basename(p), NORM,
						(show_name_only ? "" : q ? : "<no DESCRIPTION found>"));
				}

				free(buf);
				fclose(ebuildfp);
			}
no_cache_ebuild_match:
			free(str);

			break;
		} /* case CACHE_EBUILD */
		} /* switch (search_cache) */
	}
Пример #17
0
int qgrep_main(int argc, char **argv)
{
	int i;
	int count = 0;
	char *p;
	char do_count, do_regex, do_eclass, do_installed, do_list;
	char show_filename, skip_comments, invert_list, show_name;
	char per_file_output;
	FILE *fp = NULL;
	DIR *eclass_dir = NULL;
	DIR *vdb_dir = NULL;
	DIR *cat_dir = NULL;
	struct dirent *dentry;
	char ebuild[_Q_PATH_MAX];
	char name[_Q_PATH_MAX];
	char *label;
	int reflags = 0;
	char invert_match = 0;
	regex_t preg, skip_preg;
	char *skip_pattern = NULL;
	depend_atom** include_atoms = NULL;
	unsigned long int context_optarg;
	char num_lines_before = 0;
	char num_lines_after = 0;
	qgrep_buf_t *buf_list;
	int need_separator = 0;
	char status = 1;

	QGREP_STR_FUNC strfunc = strstr;

	do_count = do_regex = do_eclass = do_installed = do_list = 0;
	show_filename = skip_comments = invert_list = show_name = 0;

	while ((i = GETOPT_LONG(QGREP, qgrep, "")) != -1) {
		switch (i) {
		case 'I': invert_match = 1; break;
		case 'i':
			strfunc = strcasestr;
			reflags |= REG_ICASE;
			break;
		case 'c': do_count = 1; break;
		case 'l': do_list = 1; break;
		case 'L': do_list = invert_list = 1; break;
		case 'e': do_regex = 1; break;
		case 'x':
			do_regex = 1;
			reflags |= REG_EXTENDED;
			break;
		case 'J': do_installed = 1; break;
		case 'E': do_eclass = 1; break;
		case 'H': show_filename = 1; break;
		case 'N': show_name = 1; break;
		case 's': skip_comments = 1; break;
		case 'S': skip_pattern = optarg; break;
		case 'B':
		case 'A':
			errno = 0;
			context_optarg = strtol(optarg, &p, 10);
			if (errno != 0)
				errp("%s: not a valid integer", optarg);
			else if (p == optarg || *p != '\0')
				err("%s: not a valid integer", optarg);
			if (context_optarg > 254)
				err("%s: silly value!", optarg);
			if (i == 'B')
				num_lines_before = context_optarg;
			else
				num_lines_after = context_optarg;
			break;
		COMMON_GETOPTS_CASES(qgrep)
		}
	}
	if (argc == optind)
		qgrep_usage(EXIT_FAILURE);

	if (do_list && do_count) {
		warn("%s and --count are incompatible options. The former wins.",
				(invert_list ? "--invert-list" : "--list"));
		do_count = 0;
	}

	if (show_name && show_filename) {
		warn("--with-name and --with-filename are incompatible options. The former wins.");
		show_filename = 0;
	}

	if (do_list && num_lines_before) {
		warn("%s and --before are incompatible options. The former wins.",
				(invert_list ? "--invert-list" : "--list"));
		num_lines_before = 0;
	}

	if (do_list && num_lines_after) {
		warn("%s and --after are incompatible options. The former wins.",
				(invert_list ? "--invert-list" : "--list"));
		num_lines_after = 0;
	}

	if (do_count && num_lines_before) {
		warn("--count and --before are incompatible options. The former wins.");
		num_lines_before = 0;
	}

	if (do_count && num_lines_after) {
		warn("--count and --after are incompatible options. The former wins.");
		num_lines_after = 0;
	}

	if (do_installed && do_eclass) {
		warn("--installed and --eclass are incompatible options. The former wins.");
		do_eclass = 0;
	}

	/* do we report results once per file or per line ? */
	per_file_output = do_count || (do_list && (!verbose || invert_list));
	/* label for prefixing matching lines or listing matching files */
	label = (show_name ? name : ((verbose || show_filename || do_list) ? ebuild : NULL));

	if (argc > (optind + 1)) {
		include_atoms = xcalloc(sizeof(depend_atom*), (argc - optind - 1));
		for (i = (optind + 1); i < argc; i++)
			if ((include_atoms[i - optind - 1] = atom_explode(argv[i])) == NULL)
				warn("%s: invalid atom, will be ignored", argv[i]);
	}

	/* pre-compile regexps once for all */
	if (do_regex) {
		if (invert_match || *RED == '\0')
			reflags |= REG_NOSUB;
		xregcomp(&preg, argv[optind], reflags);
		reflags |= REG_NOSUB;
		if (skip_pattern)
			xregcomp(&skip_preg, skip_pattern, reflags);
	}

	/* allocate a circular buffers list for --before */
	buf_list = qgrep_buf_list_alloc(num_lines_before + 1);

	size_t n;
	char *overlay;
	array_for_each(overlays, n, overlay) {

		/* go look either in ebuilds or eclasses or VDB */
		if (!do_eclass && !do_installed) {
			fp = fopen(initialize_flat(overlay, CACHE_EBUILD, false), "re");
			if (fp == NULL)
				continue;
			xchdir(overlay);
		} else if (do_eclass) {
			xchdir(overlay);
			if ((eclass_dir = opendir("eclass")) == NULL) {
				if (errno != ENOENT)
					warnp("opendir(\"%s/eclass\") failed", overlay);
				continue;
			}
		} else { /* if (do_install) */
			char buf[_Q_PATH_MAX];
			snprintf(buf, sizeof(buf), "%s/%s", portroot, portvdb);
			xchdir(buf);
			if ((vdb_dir = opendir(".")) == NULL)
				errp("could not opendir(%s/%s) for ROOT/VDB", portroot, portvdb);
		}

		/* iteration is either over ebuilds or eclasses */
		while (do_eclass
				? ((dentry = readdir(eclass_dir))
					&& snprintf(ebuild, sizeof(ebuild), "eclass/%s", dentry->d_name))
				: (do_installed
					? (get_next_installed_ebuild(ebuild, vdb_dir, &dentry, &cat_dir) != NULL)
					: (fgets(ebuild, sizeof(ebuild), fp) != NULL))) {
			FILE *newfp;

			/* filter badly named files, prepare eclass or package name, etc. */
			if (do_eclass) {
				if ((p = strrchr(ebuild, '.')) == NULL)
					continue;
				if (strcmp(p, ".eclass"))
					continue;
				if (show_name || (include_atoms != NULL)) {
					/* cut ".eclass" */
					*p = '\0';
					/* and skip "eclass/" */
					snprintf(name, sizeof(name), "%s", ebuild + 7);
					/* restore the filepath */
					*p = '.';
				}
			} else {
				if ((p = strchr(ebuild, '\n')) != NULL)
					*p = '\0';
				if (show_name || (include_atoms != NULL)) {
					/* cut ".ebuild" */
					if (p == NULL)
						p = ebuild + strlen(ebuild);
					*(p-7) = '\0';
					/* cut "/foo/" from "cat/foo/foo-x.y" */
					if ((p = strchr(ebuild, '/')) == NULL)
						continue;
					*(p++) = '\0';
					/* find head of the ebuild basename */
					if ((p = strchr(p, '/')) == NULL)
						continue;
					/* find	start of the pkg name */
					snprintf(name, sizeof(name), "%s/%s", ebuild, (p+1));
					/* restore the filepath */
					*p = '/';
					*(p + strlen(p)) = '.';
					ebuild[strlen(ebuild)] = '/';
				}
			}

			/* filter the files we grep when there are extra args */
			if (include_atoms != NULL)
				if (!qgrep_name_match(name, (argc - optind - 1), include_atoms))
					continue;

			if ((newfp = fopen(ebuild, "r")) != NULL) {
				int lineno = 0;
				char remaining_after_context = 0;
				count = 0;
				/* if there have been some matches already, then a separator will be needed */
				need_separator = (!status) && (num_lines_before || num_lines_after);
				/* whatever is in the circular buffers list is no more a valid context */
				qgrep_buf_list_invalidate(buf_list);

				/* reading a new line always happen in the next buffer of the list */
				while ((buf_list = buf_list->next)
						&& (fgets(buf_list->buf, sizeof(buf_list->buf), newfp)) != NULL) {
					lineno++;
					buf_list->valid = 1;

					/* cleanup EOL */
					if ((p = strrchr(buf_list->buf, '\n')) != NULL)
						*p = 0;
					if ((p = strrchr(buf_list->buf, '\r')) != NULL)
						*p = 0;

					if (skip_comments) {
						/* reject comments line ("^[ \t]*#") */
						p = buf_list->buf;
						while (*p == ' ' || *p == '\t') p++;
						if (*p == '#')
							goto print_after_context;
					}

					if (skip_pattern) {
						/* reject some other lines which match an optional pattern */
						if (!do_regex) {
							if (strfunc(buf_list->buf, skip_pattern) != NULL)
								goto print_after_context;
						} else {
							if (regexec(&skip_preg, buf_list->buf, 0, NULL, 0) == 0)
								goto print_after_context;
						}
					}

					/* four ways to match a line (with/without inversion and regexp) */
					if (!invert_match) {
						if (do_regex == 0) {
							if (strfunc(buf_list->buf, argv[optind]) == NULL)
								goto print_after_context;
						} else {
							if (regexec(&preg, buf_list->buf, 0, NULL, 0) != 0)
								goto print_after_context;
						}
					} else {
						if (do_regex == 0) {
							if (strfunc(buf_list->buf, argv[optind]) != NULL)
								goto print_after_context;
						} else {
							if (regexec(&preg, buf_list->buf, 0, NULL, 0) == 0)
								goto print_after_context;
						}
					}

					count++;
					status = 0; /* got a match, exit status should be 0 */
					if (per_file_output)
						continue; /* matching files are listed out of this loop */

					if ((need_separator > 0)
							&& (num_lines_before || num_lines_after))
						printf("--\n");
					/* "need_separator" is not a flag, but a counter, so that
					 * adjacent contextes are not separated */
					need_separator = 0 - num_lines_before;
					if (!do_list) {
						/* print the leading context */
						qgrep_print_before_context(buf_list, num_lines_before, label,
								((verbose > 1) ? lineno : -1));
						/* print matching line */
						if (invert_match || *RED == '\0')
							qgrep_print_matching_line_nocolor(buf_list, label,
								((verbose > 1) ? lineno : -1));
						else if (do_regex)
							qgrep_print_matching_line_regcolor(buf_list, label,
								((verbose > 1) ? lineno : -1), &preg);
						else
							qgrep_print_matching_line_strcolor(buf_list, label,
								((verbose > 1) ? lineno : -1), strfunc, argv[optind]);
					} else {
						/* in verbose do_list mode, list the file once per match */
						printf("%s", label);
						if (verbose > 1)
							printf(":%d", lineno);
						putchar('\n');
					}
					/* init count down of trailing context lines */
					remaining_after_context = num_lines_after;
					continue;

 print_after_context:
					/* print some trailing context lines when needed */
					if (!remaining_after_context) {
						if (!status)
							/* we're getting closer to the need of a separator between
							 * current match block and the next one */
							++need_separator;
					} else {
						qgrep_print_context_line(buf_list, label,
								((verbose > 1) ? lineno : -1));
						--remaining_after_context;
					}
				}
				fclose(newfp);
				if (!per_file_output)
					continue; /* matches were already displayed, line per line */
				if (do_count && count) {
					if (label != NULL)
						/* -c without -v/-N/-H only outputs
						 * the matches count of the file */
						printf("%s:", label);
					printf("%d\n", count);
				} else if ((count && !invert_list) || (!count && invert_list))
					printf("%s\n", label); /* do_list == 1, or we wouldn't be here */
			}
		}
		if (do_eclass)
			closedir(eclass_dir);
		else if (!do_installed)
			fclose(fp);

		if (do_installed)
			break;
	}

	if (do_regex)
		regfree(&preg);
	if (do_regex && skip_pattern)
		regfree(&skip_preg);
	if (include_atoms != NULL) {
		for (i = 0; i < (argc - optind - 1); i++)
			if (include_atoms[i] != NULL)
				atom_implode(include_atoms[i]);
		free(include_atoms);
	}
	qgrep_buf_list_free(buf_list);

	return status;
}
Пример #18
0
void
xchdir(const char *path)
{
	if (unlikely(chdir(path) != 0))
		errp("chdir(%s) failed", path);
}
Пример #19
0
/*
 * Return scsi status or TCMU_NOT_HANDLED
 */
static int file_handle_cmd(
	struct tcmu_device *dev,
	uint8_t *cdb,
	struct iovec *iovec,
	size_t iov_cnt,
	uint8_t *sense)
{
	struct file_state *state = tcmu_get_dev_private(dev);
	uint8_t cmd;
	int remaining;
	size_t ret;

	cmd = cdb[0];

	switch (cmd) {
	case INQUIRY:
		return tcmu_emulate_inquiry(dev, cdb, iovec, iov_cnt, sense);
		break;
	case TEST_UNIT_READY:
		return tcmu_emulate_test_unit_ready(cdb, iovec, iov_cnt, sense);
		break;
	case SERVICE_ACTION_IN_16:
		if (cdb[1] == READ_CAPACITY_16)
			return tcmu_emulate_read_capacity_16(state->num_lbas,
							     state->block_size,
							     cdb, iovec, iov_cnt, sense);
		else
			return TCMU_NOT_HANDLED;
		break;
	case MODE_SENSE:
	case MODE_SENSE_10:
		return tcmu_emulate_mode_sense(cdb, iovec, iov_cnt, sense);
		break;
	case MODE_SELECT:
	case MODE_SELECT_10:
		return tcmu_emulate_mode_select(cdb, iovec, iov_cnt, sense);
		break;
	case READ_6:
	case READ_10:
	case READ_12:
	case READ_16:
	{
		void *buf;
		uint64_t offset = state->block_size * tcmu_get_lba(cdb);
		int length = tcmu_get_xfer_length(cdb) * state->block_size;

		ret = lseek(state->fd, offset, SEEK_SET);
		if (ret == -1) {
			errp("lseek failed: %m\n");
			return set_medium_error(sense);
		}

		/* Using this buf DTRT even if seek is beyond EOF */
		buf = malloc(length);
		if (!buf)
			return set_medium_error(sense);
		memset(buf, 0, length);

		ret = read(state->fd, buf, length);
		if (ret == -1) {
			errp("read failed: %m\n");
			free(buf);
			return set_medium_error(sense);
		}

		tcmu_memcpy_into_iovec(iovec, iov_cnt, buf, length);

		free(buf);

		return SAM_STAT_GOOD;
	}
	break;
	case WRITE_6:
	case WRITE_10:
	case WRITE_12:
	case WRITE_16:
	{
		uint64_t offset = state->block_size * tcmu_get_lba(cdb);
		int length = be16toh(*((uint16_t *)&cdb[7])) * state->block_size;

		ret = lseek(state->fd, offset, SEEK_SET);
		if (ret == -1) {
			errp("lseek failed: %m\n");
			return set_medium_error(sense);
		}

		remaining = length;

		while (remaining) {
			unsigned int to_copy;

			to_copy = (remaining > iovec->iov_len) ? iovec->iov_len : remaining;

			ret = write(state->fd, iovec->iov_base, to_copy);
			if (ret == -1) {
				errp("Could not write: %m\n");
				return set_medium_error(sense);
			}

			remaining -= to_copy;
			iovec++;
		}

		return SAM_STAT_GOOD;
	}
	break;
	default:
		errp("unknown command %x\n", cdb[0]);
		return TCMU_NOT_HANDLED;
	}
}
Пример #20
0
int main(int argc, char **argv)
{
	struct tcmulib_context *tcmulib_cxt;
	struct pollfd pollfds[16];
	int i;
	int ret;

	/* If any TCMU devices that exist that match subtype,
	   handler->added() will now be called from within
	   tcmulib_initialize(). */
	tcmulib_cxt = tcmulib_initialize(&foo_handler, 1, errp);
	if (tcmulib_cxt <= 0) {
		errp("tcmulib_initialize failed with %p\n", tcmulib_cxt);
		exit(1);
	}

	while (1) {
		pollfds[0].fd = tcmulib_get_master_fd(tcmulib_cxt);
		pollfds[0].events = POLLIN;
		pollfds[0].revents = 0;

		for (i = 0; i < dev_array_len; i++) {
			pollfds[i+1].fd = tcmu_get_dev_fd(tcmu_dev_array[i]);
			pollfds[i+1].events = POLLIN;
			pollfds[i+1].revents = 0;
		}

		ret = poll(pollfds, dev_array_len+1, -1);

		if (ret <= 0) {
			errp("poll() returned %d, exiting\n", ret);
			exit(1);
		}

		if (pollfds[0].revents) {
			/* If any tcmu devices have been added or removed, the
			   added() and removed() handler callbacks will be called
			   from within this. */
			tcmulib_master_fd_ready(tcmulib_cxt);

			/* Since devices (may) have changed, re-poll() instead of
			   processing per-device fds. */
			continue;
		}

		for (i = 0; i < dev_array_len; i++) {
			if (pollfds[i+1].revents) {
				struct tcmulib_cmd *cmd;
				struct tcmu_device *dev = tcmu_dev_array[i];

				while ((cmd = tcmulib_get_next_command(dev)) != NULL) {
					ret = foo_handle_cmd(dev,
							     cmd->cdb,
							     cmd->iovec,
							     cmd->iov_cnt,
							     cmd->sense_buf);
					tcmulib_command_complete(dev, cmd, ret);
				}

				tcmulib_processing_complete(dev);
			}
		}
	}

	return 0;
}
Пример #21
0
int main(int argc, char *argv[])
{
	int 				policy;
	struct 	sched_param param;
	pthread_attr_t 		attr;
	char				buffer[1024];
	int 				err;

	dprintf("init\n");
	if(argc != 2) {
		perr(AR_ERR_BAD_INIT_PARAM);
		printf("Useage: %s INSTANCE\n", AR_MODULE_NAME);
		return(AR_ERR_BAD_INIT_PARAM);
	}

	memset(&config, 0, sizeof(config));
	erret(init_config(AR_MODULE_NAME, atoi(argv[1]), &config.base));
	erret(read_config_int(config.base.name, 	"PRIORITY", &config.priority));
	erret(read_config_int(config.base.name, 	"PRIORITY_DGPS_CORR_DATA", &config.priority_dgps_corr_data));
	erret(read_config_string(config.base.name,	"DEVICE", config.ser_device, sizeof(config.ser_device)));
	err = read_config_int_tab(config.base.name, "QUEUE_INDEX", "QUEUE_IN_GPS_CORR", &config.queue_corr_data);
	if(err != 0) {
		erret(read_config_string(config.base.name,	"DEVICE_CORR_DATA_READ", config.ser_device_corr_data_read, sizeof(config.ser_device_corr_data_read)));
//		fprintf(stderr, "DGPS correction data from ser. device <%s>\n", config.ser_device_corr_data_read);
	} else {
//		fprintf(stderr, "DGPS correction data from queue <%d>\n", config.queue_corr_data);
	}
	memset(buffer, 0, sizeof(buffer));
	config.corr_mode = -1;
	erret(read_config_string(config.base.name,	"CORRECTION_MODE", buffer, sizeof(buffer)));
	if(strnicmp(buffer, "RTCA", strlen("RTCA")) == 0) {
		config.corr_mode = OEM4_RTCA_MODE;
	} else if(strnicmp(buffer, "RTCM", strlen("RTCM")) == 0) {
		config.corr_mode = OEM4_RTCM_MODE;
	} else {
		perrs(AR_ERR_BAD_INIT_PARAM, "Correction data mode not specified (RTCA | RTCM).");
	//	return(AR_ERR_BAD_INIT_PARAM);
	}
	erret(read_config_int_tab(config.base.name, "SHM_INDEX", "SHM_OUT_GPS_POS",	&config.ishm_pos_out));
	erret(read_config_int_tab(config.base.name, "SHM_INDEX", "SHM_OUT_GPS_VEL",	&config.ishm_vel_out));
	if(read_config_int(config.base.name, "UTC_OFFSET", &config.utc_offset)) {
		config.utc_offset = 15;
	}

	erret(SHM_Init());
	erret(SHM_InitSlot(config.ishm_pos_out, sizeof(gps_pos_novatel_t)));
	erret(SHM_InitSlot(config.ishm_vel_out, sizeof(gps_vel_novatel_t)));

	if(config.queue_corr_data != 0) {
		erret(Q_Init());
		erret(Q_InitSlot(config.queue_corr_data, sizeof(gps_corr_t), MAX_GPS_CORRECTION_Q_ITEMS_NUMBER, 1));
	} else if (strlen(config.ser_device_corr_data_read)>0){
		erret(open_comport(&fd_corr_data_read, config.ser_device_corr_data_read, O_RDWR, 115200));
	}

	erret(open_comport(&fd, config.ser_device, O_RDWR, 57600));
	if(0){
		struct termios 	termios_p;
		if(tcgetattr(fd, &termios_p)==0) {
			termios_p.c_cc[VTIME] = 1; // 2*0.1s = 0.2s
			termios_p.c_cc[VMIN] = 0;
			tcsetattr(fd, TCSADRAIN, &termios_p);
		} else fprintf(stderr, "failed to set read timeout\n");
	}


	//create thread for reading and writing of the correction data:
	ifret(pthread_getschedparam(pthread_self(), &policy, &param), AR_ERR_SYS_RESOURCES);
	param.sched_priority = config.priority_dgps_corr_data;
	pthread_attr_init( &attr );
	ifret(pthread_attr_setschedparam(&attr, &param), AR_ERR_SYS_RESOURCES);
	ifret(pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED), AR_ERR_SYS_RESOURCES);
	ifret(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED), AR_ERR_SYS_RESOURCES);
	if(config.corr_mode == OEM4_RTCA_MODE) {
		ifret(write(fd, OEM4_INIT_ROVER_RTCA, strlen(OEM4_INIT_ROVER_RTCA))==-1, AR_ERR_IO_ERROR);
		ifret(pthread_create(&pthreads[0], &attr, &corr_data_thread_func, NULL), AR_ERR_SYS_RESOURCES);
	} else if(config.corr_mode == OEM4_RTCM_MODE) {
		ifret(write(fd, OEM4_INIT_ROVER_RTCM, strlen(OEM4_INIT_ROVER_RTCM))==-1, AR_ERR_IO_ERROR);
		ifret(pthread_create(&pthreads[0], &attr, &corr_data_thread_func, NULL), AR_ERR_SYS_RESOURCES);
	} else
	{
		ifret(write(fd, OEM4_INIT_ROVER_COM1, strlen(OEM4_INIT_ROVER_COM1))==-1, AR_ERR_IO_ERROR);
		printf("running without differential data\n");
	}


	ifret(pthread_getschedparam(pthread_self(), &policy, &param), AR_ERR_SYS_RESOURCES);
	param.sched_priority = config.priority;
	ifret(pthread_setschedparam(pthread_self(), policy, &param), AR_ERR_SYS_RESOURCES);
	while(1) {
		errp(read_data());
	}
	return 0;
}
Пример #22
0
int
cpr_alloc_statefile(int alloc_retry)
{
	register int rc = 0;
	char *str;

	/*
	 * Statefile size validation. If checkpoint the first time, disk blocks
	 * allocation will be done; otherwise, just do file size check.
	 * if statefile allocation is being retried, C_VP will be inited
	 */
	if (alloc_retry) {
		str = "\n-->Retrying statefile allocation...";
		if (cpr_debug & (LEVEL1 | LEVEL7))
			errp(str);
		if (C_VP->v_type != VBLK)
			(void) VOP_DUMPCTL(C_VP, DUMP_FREE, NULL);
	} else {
		/*
		 * Open an exiting file for writing, the state file needs to be
		 * pre-allocated since we can't and don't want to do allocation
		 * during checkpoint (too much of the OS is disabled).
		 *    - do a preliminary size checking here, if it is too small,
		 *	allocate more space internally and retry.
		 *    - check the vp to make sure it's the right type.
		 */
		char *path = cpr_build_statefile_path();

		if (path == NULL)
			return (ENXIO);
		else if (rc = cpr_verify_statefile_path())
			return (rc);

		if (rc = vn_open(path, UIO_SYSSPACE,
		    FCREAT|FWRITE, 0600, &C_VP, CRCREAT, 0)) {
			cpr_err(CE_WARN, "cannot open statefile %s", path);
			return (rc);
		}
	}

	/*
	 * Only ufs and block special statefiles supported
	 */
	if (C_VP->v_type != VREG && C_VP->v_type != VBLK) {
		cpr_err(CE_CONT,
		    "Statefile must be regular file or block special file.");
		return (EACCES);
	}

	if (rc = cpr_statefile_ok(C_VP, alloc_retry))
		return (rc);

	if (C_VP->v_type != VBLK) {
		/*
		 * sync out the fs change due to the statefile reservation.
		 */
		(void) VFS_SYNC(C_VP->v_vfsp, 0, CRED());

		/*
		 * Validate disk blocks allocation for the state file.
		 * Ask the file system prepare itself for the dump operation.
		 */
		if (rc = VOP_DUMPCTL(C_VP, DUMP_ALLOC, NULL)) {
			cpr_err(CE_CONT, "Error allocating "
			    "blocks for cpr statefile.");
			return (rc);
		}
	}
	return (0);
}
Пример #23
0
static int tcmu_glfs_open(struct tcmu_device *dev)
{
	struct glfs_state *gfsp;
	int ret = 0;
	char *config;
	struct stat st;
	int attribute;

	gfsp = calloc(1, sizeof(*gfsp));
	if (!gfsp)
		return -ENOMEM;

	tcmu_set_dev_private(dev, gfsp);

	attribute = tcmu_get_attribute(dev, "hw_block_size");
	if (attribute == -1) {
		errp("Could not get hw_block_size setting\n");
		goto fail;
	}
	gfsp->block_size = attribute;

	config = strchr(tcmu_get_dev_cfgstring(dev), '/');
	if (!config) {
		errp("no configuration found in cfgstring\n");
		goto fail;
	}
	config += 1; /* get past '/' */

	if (parse_imagepath(config, &gfsp->servername, &gfsp->volname, &gfsp->pathname) == -1) {
		errp("servername, volname, or pathname not set\n");
		goto fail;
	}

	gfsp->fs = glfs_new(gfsp->volname);
	if (!gfsp->fs) {
		errp("glfs_new failed\n");
		goto fail;
	}

	ret = glfs_set_volfile_server(gfsp->fs, "tcp", gfsp->servername,
				      GLUSTER_PORT);
	if (ret) {
		errp("glfs_set_volfile_server failed: %m\n");
		goto fail;
	}


	ret = glfs_init(gfsp->fs);
	if (ret) {
		errp("glfs_init failed: %m\n");
		goto fail;
	}

	gfsp->gfd = glfs_open(gfsp->fs, gfsp->pathname, ALLOWED_BSOFLAGS);
	if (!gfsp->gfd) {
		errp("glfs_open failed: %m\n");
		goto fail;
	}

	ret = glfs_lstat(gfsp->fs, gfsp->pathname, &st);
	if (ret) {
		errp("glfs_lstat failed: %m\n");
		goto fail;
	}

	if (st.st_size != tcmu_get_device_size(dev)) {
		errp("device size and backing size disagree: "
		       "device %lld backing %lld\n",
		       tcmu_get_device_size(dev),
		       (long long) st.st_size);
		goto fail;
	}

	return 0;

fail:
	if (gfsp->gfd)
		glfs_close(gfsp->gfd);
	if (gfsp->fs)
		glfs_fini(gfsp->fs);
	free(gfsp->volname);
	free(gfsp->pathname);
	free(gfsp->servername);
	free(gfsp);

	return -EIO;
}
Пример #24
0
/*
 * do a simple estimate of the space needed to hold the statefile
 * taking compression into account, but be fairly conservative
 * so we have a better chance of completing; when dump fails,
 * the retry cost is fairly high.
 *
 * Do disk blocks allocation for the state file if no space has
 * been allocated yet. Since the state file will not be removed,
 * allocation should only be done once.
 */
static int
cpr_statefile_ok(vnode_t *vp, int alloc_retry)
{
	extern size_t cpr_bitmap_size;
	struct inode *ip = VTOI(vp);
	const int UCOMP_RATE = 20; /* comp. ratio*10 for user pages */
	u_longlong_t size, isize, ksize, raw_data;
	char *str, *est_fmt;
	size_t space;
	int error;

	/*
	 * number of pages short for swapping.
	 */
	STAT->cs_nosw_pages = k_anoninfo.ani_mem_resv;
	if (STAT->cs_nosw_pages < 0)
		STAT->cs_nosw_pages = 0;

	str = "cpr_statefile_ok:";

	DEBUG9(errp("Phys swap: max=%lu resv=%lu\n",
	    k_anoninfo.ani_max, k_anoninfo.ani_phys_resv));
	DEBUG9(errp("Mem swap: max=%ld resv=%lu\n",
	    MAX(availrmem - swapfs_minfree, 0),
	    k_anoninfo.ani_mem_resv));
	DEBUG9(errp("Total available swap: %ld\n",
		CURRENT_TOTAL_AVAILABLE_SWAP));

	/*
	 * try increasing filesize by 15%
	 */
	if (alloc_retry) {
		/*
		 * block device doesn't get any bigger
		 */
		if (vp->v_type == VBLK) {
			if (cpr_debug & (LEVEL1 | LEVEL6))
				errp("Retry statefile on special file\n");
			return (ENOMEM);
		} else {
			rw_enter(&ip->i_contents, RW_READER);
			size = (ip->i_size * SIZE_RATE) / INTEGRAL;
			rw_exit(&ip->i_contents);
		}
		if (cpr_debug & (LEVEL1 | LEVEL6))
			errp("Retry statefile size = %lld\n", size);
	} else {
		u_longlong_t cpd_size;
		pgcnt_t npages, nback;
		int ndvram;

		ndvram = 0;
		(void) callb_execute_class(CB_CL_CPR_FB,
		    (int)(uintptr_t)&ndvram);
		if (cpr_debug & (LEVEL1 | LEVEL6))
			errp("ndvram size = %d\n", ndvram);

		/*
		 * estimate 1 cpd_t for every (CPR_MAXCONTIG / 2) pages
		 */
		npages = cpr_count_kpages(REGULAR_BITMAP, cpr_nobit);
		cpd_size = sizeof (cpd_t) * (npages / (CPR_MAXCONTIG / 2));
		raw_data = cpd_size + cpr_bitmap_size;
		ksize = ndvram + mmu_ptob(npages);

		est_fmt = "%s estimated size with "
		    "%scompression %lld, ksize %lld\n";
		nback = mmu_ptob(STAT->cs_nosw_pages);
		if (CPR->c_flags & C_COMPRESSING) {
			size = ((ksize * COMPRESS_PERCENT) / INTEGRAL) +
			    raw_data + ((nback * 10) / UCOMP_RATE);
			DEBUG1(errp(est_fmt, str, "", size, ksize));
		} else {
			size = ksize + raw_data + nback;
			DEBUG1(errp(est_fmt, str, "no ", size, ksize));
		}
	}

	/*
	 * All this is much simpler for a block device
	 */
	if (vp->v_type == VBLK) {
		space = cpr_get_devsize(vp->v_rdev);
		if (cpr_debug & (LEVEL1 | LEVEL6))
			errp("statefile dev size %lu\n", space);

		/*
		 * Export the estimated filesize info, this value will be
		 * compared before dumping out the statefile in the case of
		 * no compression.
		 */
		STAT->cs_est_statefsz = size;
		if (cpr_debug & (LEVEL1 | LEVEL6))
			errp("%s Estimated statefile size %llu, space %lu\n",
			    str, size, space);
		if (size > space) {
			cpr_err(CE_CONT, "Statefile partition too small.");
			return (ENOMEM);
		}
		return (0);
	} else {
		if (CPR->c_alloc_cnt++ > C_MAX_ALLOC_RETRY) {
			cpr_err(CE_CONT, "Statefile allocation retry failed\n");
			return (ENOMEM);
		}

		/*
		 * Estimate space needed for the state file.
		 *
		 * State file size in bytes:
		 * 	kernel size + non-cache pte seg +
		 *	bitmap size + cpr state file headers size
		 * (round up to fs->fs_bsize)
		 */
		size = blkroundup(ip->i_fs, size);

		/*
		 * Export the estimated filesize info, this value will be
		 * compared before dumping out the statefile in the case of
		 * no compression.
		 */
		STAT->cs_est_statefsz = size;
		error = cpr_grow_statefile(vp, size);
		if (cpr_debug & (LEVEL1 | LEVEL6)) {
			rw_enter(&ip->i_contents, RW_READER);
			isize = ip->i_size;
			rw_exit(&ip->i_contents);
			errp("%s Estimated statefile size %lld, i_size %lld\n",
			    str, size, isize);
		}

		return (error);
	}
}
Пример #25
0
/*
 * Return scsi status or TCMU_NOT_HANDLED
 */
int tcmu_glfs_handle_cmd(
	struct tcmu_device *dev,
	struct tcmulib_cmd *tcmulib_cmd)
{
	uint8_t *cdb = tcmulib_cmd->cdb;
	struct iovec *iovec = tcmulib_cmd->iovec;
	size_t iov_cnt = tcmulib_cmd->iov_cnt;
	uint8_t *sense = tcmulib_cmd->sense_buf;
	struct glfs_state *state = tcmu_get_dev_private(dev);
	uint8_t cmd;

	glfs_fd_t *gfd = state->gfd;
	int ret;
	uint32_t length;
	int result = SAM_STAT_GOOD;
	char *tmpbuf;
	uint64_t offset = state->block_size * tcmu_get_lba(cdb);
	uint32_t tl     = state->block_size * tcmu_get_xfer_length(cdb);
	int do_verify = 0;
	uint32_t cmp_offset;
	ret = length = 0;

	cmd = cdb[0];

	switch (cmd) {
	case INQUIRY:
		return tcmu_emulate_inquiry(dev, cdb, iovec, iov_cnt, sense);
		break;
	case TEST_UNIT_READY:
		return tcmu_emulate_test_unit_ready(cdb, iovec, iov_cnt, sense);
		break;
	case SERVICE_ACTION_IN_16:
		if (cdb[1] == READ_CAPACITY_16) {
			long long size;
			unsigned long long num_lbas;

			size = tcmu_get_device_size(dev);
			if (size == -1) {
				errp("Could not get device size\n");
				return TCMU_NOT_HANDLED;
			}

			num_lbas = size / state->block_size;

			return tcmu_emulate_read_capacity_16(num_lbas, state->block_size,
							     cdb, iovec, iov_cnt, sense);
		} else {
			return TCMU_NOT_HANDLED;
		}
		break;
	case MODE_SENSE:
	case MODE_SENSE_10:
		return tcmu_emulate_mode_sense(cdb, iovec, iov_cnt, sense);
		break;
	case MODE_SELECT:
	case MODE_SELECT_10:
		return tcmu_emulate_mode_select(cdb, iovec, iov_cnt, sense);
		break;
	case COMPARE_AND_WRITE:
		/* Blocks are transferred twice, first the set that
		 * we compare to the existing data, and second the set
		 * to write if the compare was successful.
		 */
		length = tl / 2;

		tmpbuf = malloc(length);
		if (!tmpbuf) {
			result = tcmu_set_sense_data(sense, HARDWARE_ERROR,
						     ASC_INTERNAL_TARGET_FAILURE, NULL);
			break;
		}

		ret = glfs_pread(gfd, tmpbuf, length, offset, SEEK_SET);

		if (ret != length) {
			result = set_medium_error(sense);
			free(tmpbuf);
			break;
		}

		cmp_offset = tcmu_compare_with_iovec(tmpbuf, iovec, length);
		if (cmp_offset != -1) {
			result = tcmu_set_sense_data(sense, MISCOMPARE,
						     ASC_MISCOMPARE_DURING_VERIFY_OPERATION,
						     &cmp_offset);
			free(tmpbuf);
			break;
		}

		free(tmpbuf);

		tcmu_seek_in_iovec(iovec, length);
		goto write;
	case SYNCHRONIZE_CACHE:
	case SYNCHRONIZE_CACHE_16:
		if (cdb[1] & 0x2)
			result = tcmu_set_sense_data(sense, ILLEGAL_REQUEST,
						     ASC_INVALID_FIELD_IN_CDB, NULL);
		else
			glfs_fdatasync(gfd);
		break;
	case WRITE_VERIFY:
	case WRITE_VERIFY_12:
	case WRITE_VERIFY_16:
		do_verify = 1;
	case WRITE_6:
	case WRITE_10:
	case WRITE_12:
	case WRITE_16:
		length = tl;
write:
		ret = glfs_pwritev(gfd, iovec, iov_cnt, offset, ALLOWED_BSOFLAGS);

		if (ret == length) {
			/* Sync if FUA */
			if ((cmd != WRITE_6) && (cdb[1] & 0x8))
				glfs_fdatasync(gfd);
		} else {
			errp("Error on write %x %x\n", ret, length);
			result = set_medium_error(sense);
			break;
		}

		if (!do_verify)
			break;

		tmpbuf = malloc(length);
		if (!tmpbuf) {
			result = tcmu_set_sense_data(sense, HARDWARE_ERROR,
						     ASC_INTERNAL_TARGET_FAILURE, NULL);
			break;
		}

		ret = glfs_pread(gfd, tmpbuf, length, offset, ALLOWED_BSOFLAGS);

		if (ret != length) {
			result = set_medium_error(sense);
			free(tmpbuf);
			break;
		}

		cmp_offset = tcmu_compare_with_iovec(tmpbuf, iovec, length);
		if (cmp_offset != -1)
			result = tcmu_set_sense_data(sense, MISCOMPARE,
					    ASC_MISCOMPARE_DURING_VERIFY_OPERATION,
					    &cmp_offset);
		free(tmpbuf);
		break;

	case WRITE_SAME:
	case WRITE_SAME_16:
		errp("WRITE_SAME called, but has vpd b2 been implemented?\n");
		result = tcmu_set_sense_data(sense, ILLEGAL_REQUEST,
					     ASC_INVALID_FIELD_IN_CDB, NULL);
		break;

#if 0
		/* WRITE_SAME used to punch hole in file */
		if (cdb[1] & 0x08) {
			ret = glfs_discard(gfd, offset, tl);
			if (ret != 0) {
				result = tcmu_set_sense_data(sense, HARDWARE_ERROR,
						    ASC_INTERNAL_TARGET_FAILURE, NULL);
			}
			break;
		}
		while (tl > 0) {
			size_t blocksize = state->block_size;
			uint32_t val32;
			uint64_t val64;

			assert(iovec->iov_len >= 8);

			switch (cdb[1] & 0x06) {
			case 0x02: /* PBDATA==0 LBDATA==1 */
				val32 = htobe32(offset);
				memcpy(iovec->iov_base, &val32, 4);
				break;
			case 0x04: /* PBDATA==1 LBDATA==0 */
				/* physical sector format */
				/* hey this is wrong val! But how to fix? */
				val64 = htobe64(offset);
				memcpy(iovec->iov_base, &val64, 8);
				break;
			default:
				/* FIXME */
				errp("PBDATA and LBDATA set!!!\n");
			}

			ret = glfs_pwritev(gfd, iovec, blocksize,
					offset, ALLOWED_BSOFLAGS);

			if (ret != blocksize)
				result = set_medium_error(sense);

			offset += blocksize;
			tl     -= blocksize;
		}
		break;
#endif
	case READ_6:
	case READ_10:
	case READ_12:
	case READ_16:
		length = tcmu_iovec_length(iovec, iov_cnt);
		ret = glfs_preadv(gfd, iovec, iov_cnt, offset, SEEK_SET);

		if (ret != length) {
			errp("Error on read %x %x\n", ret, length);
			result = set_medium_error(sense);
		}
		break;
	case UNMAP:
		/* TODO: implement UNMAP */
		result = tcmu_set_sense_data(sense, ILLEGAL_REQUEST,
					     ASC_INVALID_FIELD_IN_CDB, NULL);
		break;
	default:
		result = TCMU_NOT_HANDLED;
		break;
	}

	dbgp("io done %p %x %d %u\n", cdb, cmd, result, length);

	if (result == TCMU_NOT_HANDLED)
		dbgp("io not handled %p %x %x %d %d %llu\n",
		     cdb, result, cmd, ret, length, (unsigned long long)offset);
	else if (result != SAM_STAT_GOOD) {
		errp("io error %p %x %x %d %d %llu\n",
		     cdb, result, cmd, ret, length, (unsigned long long)offset);
	}

	return result;
}
Пример #26
0
int qgrep_main(int argc, char **argv)
{
	int i;
	char *p;
	bool do_eclass;
	bool do_installed;
	DIR *eclass_dir = NULL;
	struct dirent *dentry = NULL;
	int reflags = 0;
	unsigned long int context_optarg;
	char status = 1;
	size_t n;
	char *overlay;

	struct qgrep_grepargs args = {
		.do_count = 0,
		.do_regex = 0,
		.do_list = 0,
		.show_filename = 0,
		.show_name = 0,
		.skip_comments = 0,
		.invert_list = 0,
		.invert_match = 0,
		.skip_pattern = NULL,
		.num_lines_before = 0,
		.num_lines_after = 0,
		.buf_list = NULL,
		.query = NULL,
		.strfunc = strstr,
		.include_atoms = NULL,
		.portdir = NULL,
	};

	do_eclass = do_installed = 0;

	while ((i = GETOPT_LONG(QGREP, qgrep, "")) != -1) {
		switch (i) {
		case 'I': args.invert_match = true;               break;
		case 'i':
			args.strfunc = strcasestr;
			reflags |= REG_ICASE;
			break;
		case 'c': args.do_count = true;                   break;
		case 'l': args.do_list = true;                    break;
		case 'L': args.do_list = args.invert_list = true; break;
		case 'e': args.do_regex = true;                   break;
		case 'x':
			args.do_regex = true;
			reflags |= REG_EXTENDED;
			break;
		case 'J': do_installed = true;                    break;
		case 'E': do_eclass = true;                       break;
		case 'H': args.show_filename = true;              break;
		case 'N': args.show_name = true;                  break;
		case 's': args.skip_comments = true;              break;
		case 'R': args.show_repo = args.show_name = true; break;
		case 'S': args.skip_pattern = optarg;             break;
		case 'B':
		case 'A':
			errno = 0;
			context_optarg = strtol(optarg, &p, 10);
			if (errno != 0)
				errp("%s: not a valid integer", optarg);
			else if (p == optarg || *p != '\0')
				err("%s: not a valid integer", optarg);
			if (context_optarg > 254)
				err("%s: silly value!", optarg);
			if (i == 'B')
				args.num_lines_before = context_optarg;
			else
				args.num_lines_after = context_optarg;
			break;
		COMMON_GETOPTS_CASES(qgrep)
		}
	}
	if (argc == optind)
		qgrep_usage(EXIT_FAILURE);

	if (args.do_list && args.do_count) {
		warn("%s and --count are incompatible options. The former wins.",
				(args.invert_list ? "--invert-list" : "--list"));
		args.do_count = false;
	}

	if (args.show_name && args.show_filename) {
		warn("--with-name and --with-filename are incompatible options. "
				"The former wins.");
		args.show_filename = false;
	}

	if (args.do_list && args.num_lines_before) {
		warn("%s and --before are incompatible options. The former wins.",
				(args.invert_list ? "--invert-list" : "--list"));
		args.num_lines_before = 0;
	}

	if (args.do_list && args.num_lines_after) {
		warn("%s and --after are incompatible options. The former wins.",
				(args.invert_list ? "--invert-list" : "--list"));
		args.num_lines_after = 0;
	}

	if (args.do_count && args.num_lines_before) {
		warn("--count and --before are incompatible options. The former wins.");
		args.num_lines_before = 0;
	}

	if (args.do_count && args.num_lines_after) {
		warn("--count and --after are incompatible options. The former wins.");
		args.num_lines_after = 0;
	}

	if (do_installed && do_eclass) {
		warn("--installed and --eclass are incompatible options. "
				"The former wins.");
		do_eclass = false;
	}

	if (argc > (optind + 1)) {
		depend_atom **d = args.include_atoms =
			xcalloc(sizeof(depend_atom *), (argc - optind - 1) + 1);
		for (i = (optind + 1); i < argc; i++) {
			*d = atom_explode(argv[i]);
			if (*d == NULL) {
				warn("%s: invalid atom, will be ignored", argv[i]);
			} else {
				d++;
			}
		}
		*d = NULL;
	}

	/* make it easier to see what needs to be printed */
	if (!args.show_name && (verbose || args.do_list))
		args.show_filename = true;

	/* pre-compile regexps once for all */
	if (args.do_regex) {
		if (args.invert_match || *RED == '\0')
			reflags |= REG_NOSUB;
		xregcomp(&args.preg, argv[optind], reflags);
		reflags |= REG_NOSUB;
		if (args.skip_pattern)
			xregcomp(&args.skip_preg, args.skip_pattern, reflags);
	}
	args.query = argv[optind];

	/* allocate a circular buffers list for --before */
	args.buf_list = qgrep_buf_list_alloc(args.num_lines_before + 1);

	array_for_each(overlays, n, overlay) {
		args.portdir = overlay;
		if (do_eclass) {
			char buf[_Q_PATH_MAX];
			char name[_Q_PATH_MAX];
			char *label;
			int efd;

			snprintf(buf, sizeof(buf), "%s/%s/eclass", portroot, overlay);
			efd = open(buf, O_RDONLY|O_CLOEXEC);
			if (efd == -1 || (eclass_dir = fdopendir(efd)) == NULL) {
				if (errno != ENOENT)
					warnp("opendir(\"%s/eclass\") failed", overlay);
				continue;
			}
			while ((dentry = readdir(eclass_dir)) != NULL) {
				if (strstr(dentry->d_name, ".eclass") == NULL)
					continue;
				/* filter the files we grep when there are extra args */
				if (args.include_atoms != NULL) {
					depend_atom **d;
					for (d = args.include_atoms; *d != NULL; d++) {
						if ((*d)->PN != NULL && strncmp(dentry->d_name,
									(*d)->PN, strlen((*d)->PN)) == 0)
							break;
					}
					if (*d == NULL)
						continue;
				}

				label = NULL;
				if (args.show_name) {
					snprintf(name, sizeof(name), "%s%.*s%s", BLUE,
							(int)(strlen(dentry->d_name) - 7), dentry->d_name,
							NORM);
					label = name;
				} else if (args.show_filename) {
					snprintf(name, sizeof(name), "eclass/%s", dentry->d_name);
					label = name;
				}
				status = qgrep_grepat(efd, dentry->d_name, label, &args);
			}
			closedir(eclass_dir);
		} else if (do_installed) {
			status = q_vdb_foreach_pkg(portroot, portvdb,
					qgrep_vdb_cb, &args, NULL);
		} else { /* do_ebuild */
			status = cache_foreach_pkg(portroot, overlay,
					qgrep_cache_cb, &args, NULL);
		}
	}

	if (args.do_regex)
		regfree(&args.preg);
	if (args.do_regex && args.skip_pattern)
		regfree(&args.skip_preg);
	if (args.include_atoms != NULL) {
		for (i = 0; i < (argc - optind - 1); i++)
			if (args.include_atoms[i] != NULL)
				atom_implode(args.include_atoms[i]);
		free(args.include_atoms);
	}
	qgrep_buf_list_free(args.buf_list);

	return status;
}