コード例 #1
0
ファイル: process.c プロジェクト: FatSunHYS/OSCourseDesign
int os_process_parent(int pid)
{
	char stat[STAT_PATH_LEN];
	char data[256];
	int parent, n, fd;

	if(pid == -1) return(-1);

	snprintf(stat, sizeof(stat), "/proc/%d/stat", pid);
	fd = os_open_file(stat, of_read(OPENFLAGS()), 0);
	if(fd < 0){
		printk("Couldn't open '%s', err = %d\n", stat, -fd);
		return(FAILURE_PID);
	}

	n = os_read_file(fd, data, sizeof(data));
	os_close_file(fd);

	if(n < 0){
		printk("Couldn't read '%s', err = %d\n", stat, -n);
		return(FAILURE_PID);
	}

	parent = FAILURE_PID;
	n = sscanf(data, "%*d " COMM_SCANF " %*c %d", &parent);
	if(n != 1)
		printk("Failed to scan '%s'\n", data);

	return(parent);
}
コード例 #2
0
static ssize_t hostaudio_read(struct file *file, char __user *buffer,
			      size_t count, loff_t *ppos)
{
	struct hostaudio_state *state = file->private_data;
	void *kbuf;
	int err;

#ifdef DEBUG
	printk(KERN_DEBUG "hostaudio: read called, count = %d\n", count);
#endif

	kbuf = kmalloc(count, GFP_KERNEL);
	if (kbuf == NULL)
		return -ENOMEM;

	err = os_read_file(state->fd, kbuf, count);
	if (err < 0)
		goto out;

	if (copy_to_user(buffer, kbuf, err))
		err = -EFAULT;

out:
	kfree(kbuf);
	return err;
}
コード例 #3
0
ファイル: process.c プロジェクト: FatSunHYS/OSCourseDesign
unsigned long os_process_pc(int pid)
{
	char proc_stat[STAT_PATH_LEN], buf[256];
	unsigned long pc;
	int fd, err;

	sprintf(proc_stat, "/proc/%d/stat", pid);
	fd = os_open_file(proc_stat, of_read(OPENFLAGS()), 0);
	if(fd < 0){
		printk("os_process_pc - couldn't open '%s', err = %d\n",
		       proc_stat, -fd);
		return(ARBITRARY_ADDR);
	}
	err = os_read_file(fd, buf, sizeof(buf));
	if(err < 0){
		printk("os_process_pc - couldn't read '%s', err = %d\n",
		       proc_stat, -err);
		os_close_file(fd);
		return(ARBITRARY_ADDR);
	}
	os_close_file(fd);
	pc = ARBITRARY_ADDR;
	if(sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d "
		  "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
		  "%*d %*d %*d %*d %*d %lu", &pc) != 1){
		printk("os_process_pc - couldn't find pc in '%s'\n", buf);
	}
	return(pc);
}
コード例 #4
0
ファイル: sigio.c プロジェクト: 274914765/C
static irqreturn_t sigio_interrupt(int irq, void *data)
{
    char c;

    os_read_file(sigio_irq_fd, &c, sizeof(c));
    reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ);
    return IRQ_HANDLED;
}
コード例 #5
0
void switch_to_tt(void *prev, void *next)
{
	struct task_struct *from, *to, *prev_sched;
	unsigned long flags;
	int err, vtalrm, alrm, prof, cpu;
	char c;

	from = prev;
	to = next;

	cpu = from->thread_info->cpu;
	if(cpu == 0)
		forward_interrupts(to->thread.mode.tt.extern_pid);
#ifdef CONFIG_SMP
	forward_ipi(cpu_data[cpu].ipi_pipe[0], to->thread.mode.tt.extern_pid);
#endif
	local_irq_save(flags);

	vtalrm = change_sig(SIGVTALRM, 0);
	alrm = change_sig(SIGALRM, 0);
	prof = change_sig(SIGPROF, 0);

	forward_pending_sigio(to->thread.mode.tt.extern_pid);

	c = 0;

	err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c));
	if(err != sizeof(c))
		panic("write of switch_pipe failed, err = %d", -err);

	if(from->thread.mode.tt.switch_pipe[0] == -1)
		os_kill_process(os_getpid(), 0);

	err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, sizeof(c));
	if(err != sizeof(c))
		panic("read of switch_pipe failed, errno = %d", -err);

	/* If the process that we have just scheduled away from has exited,
	 * then it needs to be killed here.  The reason is that, even though
	 * it will kill itself when it next runs, that may be too late.  Its
	 * stack will be freed, possibly before then, and if that happens,
	 * we have a use-after-free situation.  So, it gets killed here
	 * in case it has not already killed itself.
	 */
	prev_sched = current->thread.prev_sched;
        if(prev_sched->thread.mode.tt.switch_pipe[0] == -1)
		os_kill_process(prev_sched->thread.mode.tt.extern_pid, 1);

	change_sig(SIGVTALRM, vtalrm);
	change_sig(SIGALRM, alrm);
	change_sig(SIGPROF, prof);

	arch_switch();

	flush_tlb_all();
	local_irq_restore(flags);
}
コード例 #6
0
void suspend_new_thread(int fd)
{
	int err;
	char c;

	os_stop_process(os_getpid());
	err = os_read_file(fd, &c, sizeof(c));
	if(err != sizeof(c))
		panic("read failed in suspend_new_thread, err = %d", -err);
}
コード例 #7
0
ファイル: net_user.c プロジェクト: FatSunHYS/OSCourseDesign
int net_read(int fd, void *buf, int len)
{
	int n;

	n = os_read_file(fd,  buf,  len);

	if(n == -EAGAIN)
		return 0;
	else if(n == 0)
		return -ENOTCONN;
	return n;
}
コード例 #8
0
ファイル: chan_kern.c プロジェクト: cilynx/dd-wrt
int generic_read(int fd, char *c_out, void *unused)
{
	int n;

	n = os_read_file(fd, c_out, sizeof(*c_out));

	if(n == -EAGAIN)
		return 0;
	else if(n == 0)
		return -EIO;
	return n;
}
コード例 #9
0
ファイル: net_user.c プロジェクト: OpenHMR/Open-HMR600
int net_read(int fd, void *buf, int len)
{
	int n;

	n = os_read_file(fd,  buf,  len);

	if(n == -EAGAIN)
		return(0);
	else if(n == 0)
		return(-ENOTCONN);
	return(n);
}
コード例 #10
0
ファイル: net_user.c プロジェクト: FatSunHYS/OSCourseDesign
/* Do reliable error handling as this fails frequently enough. */
void read_output(int fd, char *output, int len)
{
	int remain, ret, expected;
	char c;
	char *str;

	if(output == NULL){
		output = &c;
		len = sizeof(c);
	}
		
	*output = '\0';
	ret = os_read_file(fd, &remain, sizeof(remain));

	if (ret != sizeof(remain)) {
		expected = sizeof(remain);
		str = "length";
		goto err;
	}

	while(remain != 0){
		expected = (remain < len) ? remain : len;
		ret = os_read_file(fd, output, expected);
		if (ret != expected) {
			str = "data";
			goto err;
		}
		remain -= ret;
	}

	return;

err:
	if (ret < 0)
		printk("read_output - read of %s failed, errno = %d\n", str, -ret);
	else
		printk("read_output - read of %s failed, read only %d of %d bytes\n", str, ret, expected);
}
コード例 #11
0
static irqreturn_t test_interrupt(int irq, void *data)
{
    char buff[1024];
    printk("Test Interrupt occurred!!!\n");

    memset(buff, 0, 1024);

    os_read_file(fd, buff, 1023);

    printk("Test: read %s\n", buff);

    reactivate_fd(fd, MAPPER_IRQ);

    return IRQ_HANDLED;
}
コード例 #12
0
static int etap_tramp(char *dev, char *gate, int control_me, 
		      int control_remote, int data_me, int data_remote)
{
	struct etap_pre_exec_data pe_data;
	int pid, status, err, n;
	char version_buf[sizeof("nnnnn\0")];
	char data_fd_buf[sizeof("nnnnnn\0")];
	char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")];
	char *setup_args[] = { "uml_net", version_buf, "ethertap", dev,
			       data_fd_buf, gate_buf, NULL };
	char *nosetup_args[] = { "uml_net", version_buf, "ethertap", 
				 dev, data_fd_buf, NULL };
	char **args, c;

	sprintf(data_fd_buf, "%d", data_remote);
	sprintf(version_buf, "%d", UML_NET_VERSION);
	if(gate != NULL){
		strcpy(gate_buf, gate);
		args = setup_args;
	}
	else args = nosetup_args;

	err = 0;
	pe_data.control_remote = control_remote;
	pe_data.control_me = control_me;
	pe_data.data_me = data_me;
	pid = run_helper(etap_pre_exec, &pe_data, args, NULL);

	if(pid < 0) err = pid;
	os_close_file(data_remote);
	os_close_file(control_remote);
	n = os_read_file(control_me, &c, sizeof(c));
	if(n != sizeof(c)){
		printk("etap_tramp : read of status failed, err = %d\n", -n);
		return(-EINVAL);
	}
	if(c != 1){
		printk("etap_tramp : uml_net failed\n");
		err = -EINVAL;
		CATCH_EINTR(n = waitpid(pid, &status, 0));
		if(n < 0)
			err = -errno;
		else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1))
			printk("uml_net didn't exit with status 1\n");
	}
	return(err);
}
コード例 #13
0
int os_read_file_line(file_desc_t file, void *buff, int len)
{
	int nLen = 0;
	char *p = (char*)buff;

	while (nLen < len)
	{
		if (1 == os_read_file(file, p, 1))
		{
			nLen ++;
			if ((*p) == '\n')
				return nLen;
		}
		else
			return -1;
		p ++;
	}
	return nLen;
}
コード例 #14
0
ファイル: random.c プロジェクト: johnny/CobraDroidBeta
static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
			     loff_t *offp)
{
	u32 data;
	int n, ret = 0, have_data;

	while (size) {
		n = os_read_file(random_fd, &data, sizeof(data));
		if (n > 0) {
			have_data = n;
			while (have_data && size) {
				if (put_user((u8) data, buf++)) {
					ret = ret ? : -EFAULT;
					break;
				}
				size--;
				ret++;
				have_data--;
				data >>= 8;
			}
		}
コード例 #15
0
ファイル: initrd.c プロジェクト: 08opt/linux
static int load_initrd(char *filename, void *buf, int size)
{
	int fd, n;

	fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
	if (fd < 0) {
		printk(KERN_ERR "Opening '%s' failed - err = %d\n", filename,
		       -fd);
		return -1;
	}
	n = os_read_file(fd, buf, size);
	if (n != size) {
		printk(KERN_ERR "Read of %d bytes from '%s' failed, "
		       "err = %d\n", size,
		       filename, -n);
		return -1;
	}

	os_close_file(fd);
	return 0;
}
コード例 #16
0
ファイル: umid.c プロジェクト: Antonio-Zhou/Linux-2.6.11
int not_dead_yet(char *dir)
{
	char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
	char pid[sizeof("nnnnn\0")], *end;
	int dead, fd, p, n;

	sprintf(file, "%s/pid", dir);
	dead = 0;
	fd = os_open_file(file, of_read(OPENFLAGS()), 0);
	if(fd < 0){
		if(fd != -ENOENT){
			printk("not_dead_yet : couldn't open pid file '%s', "
			       "err = %d\n", file, -fd);
			return(1);
		}
		dead = 1;
	}
	if(fd > 0){
		n = os_read_file(fd, pid, sizeof(pid));
		if(n < 0){
			printk("not_dead_yet : couldn't read pid file '%s', "
			       "err = %d\n", file, -n);
			return(1);
		}
		p = strtoul(pid, &end, 0);
		if(end == pid){
			printk("not_dead_yet : couldn't parse pid file '%s', "
			       "errno = %d\n", file, errno);
			dead = 1;
		}
		if(((kill(p, 0) < 0) && (errno == ESRCH)) ||
		   (p == CHOOSE_MODE(tracing_pid, os_getpid())))
			dead = 1;
	}
	if(!dead) return(1);
	return(actually_do_remove(dir));
}
コード例 #17
0
ファイル: hppfs_kern.c プロジェクト: romanalexander/Trickles
static ssize_t hppfs_read_file(int fd, char *buf, ssize_t count)
{
	ssize_t n;
	int cur, err;
	char *new_buf;

	n = -ENOMEM;
	new_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
	if(new_buf == NULL){
		printk("hppfs_read_file : kmalloc failed\n");
		goto out;
	}
	n = 0;
	while(count > 0){
		cur = min_t(ssize_t, count, PAGE_SIZE);
		err = os_read_file(fd, new_buf, cur);
		if(err < 0){
			printk("hppfs_read : read failed, err = %d\n", -err);
			n = err;
			goto out_free;
		}
		else if(err == 0)
			break;

		if(copy_to_user(buf, new_buf, err)){
			n = -EFAULT;
			goto out_free;
		}
		n += err;
		count -= err;
	}
 out_free:
	kfree(new_buf);
 out:
	return(n);
}
コード例 #18
0
static int connect_to_switch(struct daemon_data *pri)
{
	struct sockaddr_un *ctl_addr = pri->ctl_addr;
	struct sockaddr_un *local_addr = pri->local_addr;
	struct sockaddr_un *sun;
	struct request_v3 req;
	int fd, n, err;

	pri->control = socket(AF_UNIX, SOCK_STREAM, 0);
	if(pri->control < 0){
		printk("daemon_open : control socket failed, errno = %d\n", 
		       errno);		
		return(-errno);
	}

	if(connect(pri->control, (struct sockaddr *) ctl_addr, 
		   sizeof(*ctl_addr)) < 0){
		printk("daemon_open : control connect failed, errno = %d\n",
		       errno);
		err = -errno;
		goto out;
	}

	fd = socket(AF_UNIX, SOCK_DGRAM, 0);
	if(fd < 0){
		printk("daemon_open : data socket failed, errno = %d\n", 
		       errno);
		err = -errno;
		goto out;
	}
	if(bind(fd, (struct sockaddr *) local_addr, sizeof(*local_addr)) < 0){
		printk("daemon_open : data bind failed, errno = %d\n", 
		       errno);
		err = -errno;
		goto out_close;
	}

	sun = um_kmalloc(sizeof(struct sockaddr_un));
	if(sun == NULL){
		printk("new_addr: allocation of sockaddr_un failed\n");
		err = -ENOMEM;
		goto out_close;
	}

	req.magic = SWITCH_MAGIC;
	req.version = SWITCH_VERSION;
	req.type = REQ_NEW_CONTROL;
	req.sock = *local_addr;
	n = os_write_file(pri->control, &req, sizeof(req));
	if(n != sizeof(req)){
		printk("daemon_open : control setup request failed, err = %d\n",
		       -n);
		err = -ENOTCONN;
		goto out_free;
	}

	n = os_read_file(pri->control, sun, sizeof(*sun));
	if(n != sizeof(*sun)){
		printk("daemon_open : read of data socket failed, err = %d\n",
		       -n);
		err = -ENOTCONN;
		goto out_free;
	}

	pri->data_addr = sun;
	return(fd);

 out_free:
	kfree(sun);
 out_close:
	os_close_file(fd);
 out:
	os_close_file(pri->control);
	return(err);
}
コード例 #19
0
void switch_to_tt(void *prev, void *next)
{
	struct task_struct *from, *to, *prev_sched;
	unsigned long flags;
	int err, vtalrm, alrm, prof, cpu;
	char c;

	from = prev;
	to = next;

	cpu = task_thread_info(from)->cpu;
	if(cpu == 0)
		forward_interrupts(to->thread.mode.tt.extern_pid);
#ifdef CONFIG_SMP
	forward_ipi(cpu_data[cpu].ipi_pipe[0], to->thread.mode.tt.extern_pid);
#endif
	local_irq_save(flags);

	vtalrm = change_sig(SIGVTALRM, 0);
	alrm = change_sig(SIGALRM, 0);
	prof = change_sig(SIGPROF, 0);

	forward_pending_sigio(to->thread.mode.tt.extern_pid);

	c = 0;

	/* Notice that here we "up" the semaphore on which "to" is waiting, and
	 * below (the read) we wait on this semaphore (which is implemented by
	 * switch_pipe) and go sleeping. Thus, after that, we have resumed in
	 * "to", and can't use any more the value of "from" (which is outdated),
	 * nor the value in "to" (since it was the task which stole us the CPU,
	 * which we don't care about). */

	err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c));
	if(err != sizeof(c))
		panic("write of switch_pipe failed, err = %d", -err);

	if(from->thread.mode.tt.switch_pipe[0] == -1)
		os_kill_process(os_getpid(), 0);

	err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, sizeof(c));
	if(err != sizeof(c))
		panic("read of switch_pipe failed, errno = %d", -err);

	/* If the process that we have just scheduled away from has exited,
	 * then it needs to be killed here.  The reason is that, even though
	 * it will kill itself when it next runs, that may be too late.  Its
	 * stack will be freed, possibly before then, and if that happens,
	 * we have a use-after-free situation.  So, it gets killed here
	 * in case it has not already killed itself.
	 */
	prev_sched = current->thread.prev_sched;
        if(prev_sched->thread.mode.tt.switch_pipe[0] == -1)
		os_kill_process(prev_sched->thread.mode.tt.extern_pid, 1);

	change_sig(SIGVTALRM, vtalrm);
	change_sig(SIGALRM, alrm);
	change_sig(SIGPROF, prof);

	arch_switch_to_tt(prev_sched, current);

	flush_tlb_all();
	local_irq_restore(flags);
}
コード例 #20
0
void *switch_to_tt(void *prev, void *next, void *last)
{
	struct task_struct *from, *to, *prev_sched;
	unsigned long flags;
	int err, vtalrm, alrm, prof, cpu;
	char c;
	/* jailing and SMP are incompatible, so this doesn't need to be 
	 * made per-cpu 
	 */
	static int reading;

	from = prev;
	to = next;

	to->thread.prev_sched = from;

	cpu = from->thread_info->cpu;
	if(cpu == 0)
		forward_interrupts(to->thread.mode.tt.extern_pid);
#ifdef CONFIG_SMP
	forward_ipi(cpu_data[cpu].ipi_pipe[0], to->thread.mode.tt.extern_pid);
#endif
	local_irq_save(flags);

	vtalrm = change_sig(SIGVTALRM, 0);
	alrm = change_sig(SIGALRM, 0);
	prof = change_sig(SIGPROF, 0);

	forward_pending_sigio(to->thread.mode.tt.extern_pid);

	c = 0;
	set_current(to);

	reading = 0;
	err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c));
	if(err != sizeof(c))
		panic("write of switch_pipe failed, err = %d", -err);

	reading = 1;
	if((from->exit_state == EXIT_ZOMBIE) || (from->exit_state == EXIT_DEAD))
		os_kill_process(os_getpid(), 0);

	err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, sizeof(c));
	if(err != sizeof(c))
		panic("read of switch_pipe failed, errno = %d", -err);

	/* If the process that we have just scheduled away from has exited,
	 * then it needs to be killed here.  The reason is that, even though
	 * it will kill itself when it next runs, that may be too late.  Its
	 * stack will be freed, possibly before then, and if that happens,
	 * we have a use-after-free situation.  So, it gets killed here
	 * in case it has not already killed itself.
	 */
	prev_sched = current->thread.prev_sched;
	if((prev_sched->exit_state == EXIT_ZOMBIE) ||
	   (prev_sched->exit_state == EXIT_DEAD))
		os_kill_ptraced_process(prev_sched->thread.mode.tt.extern_pid, 1);

	/* This works around a nasty race with 'jail'.  If we are switching
	 * between two threads of a threaded app and the incoming process 
	 * runs before the outgoing process reaches the read, and it makes
	 * it all the way out to userspace, then it will have write-protected 
	 * the outgoing process stack.  Then, when the outgoing process 
	 * returns from the write, it will segfault because it can no longer
	 * write its own stack.  So, in order to avoid that, the incoming 
	 * thread sits in a loop yielding until 'reading' is set.  This 
	 * isn't entirely safe, since there may be a reschedule from a timer
	 * happening between setting 'reading' and sleeping in read.  But,
	 * it should get a whole quantum in which to reach the read and sleep,
	 * which should be enough.
	 */

	if(jail){
		while(!reading) sched_yield();
	}

	change_sig(SIGVTALRM, vtalrm);
	change_sig(SIGALRM, alrm);
	change_sig(SIGPROF, prof);

	arch_switch();

	flush_tlb_all();
	local_irq_restore(flags);

	return(current->thread.prev_sched);
}
コード例 #21
0
ファイル: helper.c プロジェクト: GodFox/magx_kernel_xpixl
int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
	       unsigned long *stack_out)
{
	struct helper_data data;
	unsigned long stack, sp;
	int pid, fds[2], err, n;

	if((stack_out != NULL) && (*stack_out != 0))
		stack = *stack_out;
	else stack = alloc_stack(0, um_in_interrupt());
	if(stack == 0)
		return(-ENOMEM);

	err = os_pipe(fds, 1, 0);
	if(err < 0){
		printk("run_helper : pipe failed, err = %d\n", -err);
		goto out_free;
	}

	err = os_set_exec_close(fds[1], 1);
	if(err < 0){
		printk("run_helper : setting FD_CLOEXEC failed, err = %d\n",
		       -err);
		goto out_close;
	}

	sp = stack + page_size() - sizeof(void *);
	data.pre_exec = pre_exec;
	data.pre_data = pre_data;
	data.argv = argv;
	data.fd = fds[1];
	pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data);
	if(pid < 0){
		printk("run_helper : clone failed, errno = %d\n", errno);
		err = -errno;
		goto out_close;
	}

	os_close_file(fds[1]);
	n = os_read_file(fds[0], &err, sizeof(err));
	if(n < 0){
		printk("run_helper : read on pipe failed, err = %d\n", -n);
		err = n;
		goto out_kill;
	}
	else if(n != 0){
		CATCH_EINTR(n = waitpid(pid, NULL, 0));
		pid = -errno;
	}

	if(stack_out == NULL) free_stack(stack, 0);
        else *stack_out = stack;
	return(pid);

 out_kill:
	os_kill_process(pid, 1);
 out_close:
	os_close_file(fds[0]);
	os_close_file(fds[1]);
 out_free:
	free_stack(stack, 0);
	return(err);
}
コード例 #22
0
ファイル: harddog_user.c プロジェクト: 3sOx/asuswrt-merlin
int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
{
	struct dog_data data;
	int in_fds[2], out_fds[2], pid, n, err;
	char pid_buf[sizeof("nnnnn\0")], c;
	char *pid_args[] = { "/usr/bin/uml_watchdog", "-pid", pid_buf, NULL };
	char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL,
				  NULL };
	char **args = NULL;

	err = os_pipe(in_fds, 1, 0);
	if(err < 0){
		printk("harddog_open - os_pipe failed, err = %d\n", -err);
		goto out;
	}

	err = os_pipe(out_fds, 1, 0);
	if(err < 0){
		printk("harddog_open - os_pipe failed, err = %d\n", -err);
		goto out_close_in;
	}

	data.stdin = out_fds[0];
	data.stdout = in_fds[1];
	data.close_me[0] = out_fds[1];
	data.close_me[1] = in_fds[0];

	if(sock != NULL){
		mconsole_args[2] = sock;
		args = mconsole_args;
	}
	else {
		/* XXX The os_getpid() is not SMP correct */
		sprintf(pid_buf, "%d", CHOOSE_MODE(tracing_pid, os_getpid()));
		args = pid_args;
	}

	pid = run_helper(pre_exec, &data, args, NULL);

	os_close_file(out_fds[0]);
	os_close_file(in_fds[1]);

	if(pid < 0){
		err = -pid;
		printk("harddog_open - run_helper failed, errno = %d\n", -err);
		goto out_close_out;
	}

	n = os_read_file(in_fds[0], &c, sizeof(c));
	if(n == 0){
		printk("harddog_open - EOF on watchdog pipe\n");
		helper_wait(pid);
		err = -EIO;
		goto out_close_out;
	}
	else if(n < 0){
		printk("harddog_open - read of watchdog pipe failed, "
		       "err = %d\n", -n);
		helper_wait(pid);
		err = n;
		goto out_close_out;
	}
	*in_fd_ret = in_fds[0];
	*out_fd_ret = out_fds[1];
	return 0;

 out_close_in:
	os_close_file(in_fds[0]);
	os_close_file(in_fds[1]);
 out_close_out:
	os_close_file(out_fds[0]);
	os_close_file(out_fds[1]);
 out:
	return err;
}