Example #1
0
int process_test_str(struct config *config, char *value, int value_sz, char *keyprefix) {
	int r;
	char c_file[1024];
	char elf_file[1024];
	snprintf(c_file, sizeof(c_file), "%s/plugin-%s.c", config->tmpdir, keyprefix);
	snprintf(elf_file, sizeof(elf_file), "%s/plugin-%s.elf", config->tmpdir, keyprefix);

	if(0 != write_file(c_file, value, value_sz)) {
		log_perror("write()");
		return(-1);
	}
	char warn_buf[1024];
	int warn_buf_sz = 0;
	if(0 != process_compile(config, c_file, elf_file, warn_buf, sizeof(warn_buf), &warn_buf_sz)) {
		warn_buf[MAX(1, warn_buf_sz)-1] = '\0';
		log_error("compilation failed:\n%s", warn_buf);
		return(-1);
	}
	struct process *process = process_new(NULL, keyprefix, strlen(keyprefix));
	log_warn("#%p: loaded code from str", process);
	r = process_load(process, elf_file);
	if(0 != r) {
		process_free(process);
		log_error("unable to load process:\n%s", warn_buf);
		return(-1);
	}
	r = process_run(NULL, process);
	process_free(process);
	if(r <= 0) {
		log_error("error while running process");
		return(-1);
	}
	// ok!
	return(r);
}
Example #2
0
// return 1 to say that a file was processed
static int maybe_process_file(struct asfd *asfd,
	struct sdirs *sdirs, struct sbuf *cb, struct sbuf *p1b,
	struct fzp *ucfp, struct conf **cconfs)
{
	switch(sbuf_pathcmp(cb, p1b))
	{
		case 0:
			return maybe_do_delta_stuff(asfd, sdirs, cb, p1b,
				ucfp, cconfs);
		case 1:
			//logp("ahead: %s\n", p1b->path);
			// ahead - need to get the whole file
			if(process_new(sdirs, cconfs, p1b, ucfp))
				return -1;
			// Do not free.
			return 1;
		case -1:
		default:
			//logp("behind: %s\n", p1b->path);
			// Behind - need to read more from the old manifest.
			// Count a deleted file - it was in the old manifest
			// but not the new.
			cntr_add_deleted(get_cntr(cconfs[OPT_CNTR]),
				cb->path.cmd);
			return 0;
	}
}
Example #3
0
static int process_new_file(struct sbuf *cb, struct sbuf *p1b, FILE *ucfp, const char *currentdata, const char *datadirtmp, const char *deltmppath, struct dpth *dpth, int *resume_partial, struct cntr *cntr, struct config *cconf)
{
	if(process_new(p1b, ucfp, currentdata, datadirtmp, deltmppath,
		dpth, resume_partial, cntr, cconf)) return -1;
	free_sbuf(cb);
	return 1;
}
Example #4
0
void
test_new (void)
{
	Process *process;

	/* Check that we can create a new Process structure; the structure
	 * should be allocated with nih_alloc and have sensible defaults.
	 */
	TEST_FUNCTION ("process_new");
	TEST_ALLOC_FAIL {
		process = process_new (NULL);

		if (test_alloc_failed) {
			TEST_EQ_P (process, NULL);
			continue;
		}

		TEST_ALLOC_SIZE (process, sizeof (Process));

		TEST_EQ (process->script, FALSE);
		TEST_EQ_P (process->command, NULL);

		nih_free (process);
	}
}
Example #5
0
static int process_new_file(struct sdirs *sdirs, struct conf **cconfs,
	struct sbuf *cb, struct sbuf *p1b, struct fzp *ucfp)
{
	if(process_new(sdirs, cconfs, p1b, ucfp))
		return -1;
	sbuf_free_content(cb);
	return 1;
}
Example #6
0
File: proc.c Project: clarkok/CoS
static Process *
_proc_construct_init()
{
    Process *new_proc = process_new("init", NULL);

    new_proc->current_scene->pc = proc_kernel_thread(init_proc);

    return new_proc;
}
Example #7
0
static int process_new_file(struct sdirs *sdirs, struct conf *cconf,
	struct sbuf *cb, struct sbuf *p1b, FILE *ucfp,
	struct dpthl *dpthl)
{
	if(process_new(sdirs, cconf, p1b, ucfp, dpthl))
		return -1;
	sbuf_free_content(cb);
	return 1;
}
Example #8
0
/*
   Request:
      MUST NOT have extras.
      MUST have key.
      MUST have value.
*/
ST_RES *cmd_code_load(CONN *conn, ST_REQ *req, ST_RES *res) {
	if(req->extras_sz || !req->key_sz || !req->value_sz)
		return(set_error_code(res, MEMCACHE_STATUS_INVALID_ARGUMENTS, NULL));
	
	if(CONFIG(conn)->vx32_disabled) {
		return(set_error_code(res, MEMCACHE_STATUS_UNKNOWN_COMMAND, "Command disabled by configuration"));
	}
	
	if(NULL != find_process(req->key, req->key_sz))
		return(set_error_code(res, MEMCACHE_STATUS_KEY_EXISTS, NULL));	

	int r;
	char c_file[1024];
	char elf_file[1024];
	char keyprefix[32];
	key_escape(keyprefix, sizeof(keyprefix), req->key, req->key_sz);
	keyprefix[MIN(req->key_sz, sizeof(keyprefix)-1)] = '\0'; // make it reasonably short
	snprintf(c_file, sizeof(c_file), "%s/plugin-%s.c", CONFIG(conn)->tmpdir, keyprefix);
	snprintf(elf_file, sizeof(elf_file), "%s/plugin-%s.elf", CONFIG(conn)->tmpdir, keyprefix);
	
	res->value = res->buf;
	
	r = write_file(c_file, req->value, req->value_sz);
	if(0 != r) { // never
		res->status = MEMCACHE_STATUS_ITEM_NOT_STORED;
		res->value_sz += snprintf(&res->value[res->value_sz], res->buf_sz - res->value_sz, "Error while saving file: %s", strerror(errno));
		return(res);
	}
	
	if(0 != process_compile(CONFIG(conn), c_file, elf_file, res->value, res->buf_sz, (int*)&res->value_sz)) {
		res->status = MEMCACHE_STATUS_ITEM_NOT_STORED;
		return(res);
	}
	res->value_sz = MIN(res->value_sz, 4096); // no more than 4k logs
	res->value[res->value_sz++] = '\n';
	res->value[res->value_sz++] = '\n';
	
	struct process *process = process_new(conn, req->key, req->key_sz);
	log_warn("#%p: loaded code", process);
	r = process_load(process, elf_file);
	if(0 != r) { // never
		process_free(process);
		res->value_sz += snprintf(&res->value[res->value_sz], res->buf_sz - res->value_sz, "Error while loading the binary");
		res->status = MEMCACHE_STATUS_ITEM_NOT_STORED;
		return(res);
	}
	if(0 != process_run(conn, process)) {
		process_free(process);
		res->value_sz += snprintf(&res->value[res->value_sz], res->buf_sz - res->value_sz, "Error while running the binary");
		res->status = MEMCACHE_STATUS_ITEM_NOT_STORED;
		return(res);
	}
	res->status = MEMCACHE_STATUS_OK;
	return res;
}
Example #9
0
void host_addApplication(Host* host, GQuark pluginID,
		SimulationTime startTime, SimulationTime stopTime, gchar* arguments) {
	MAGIC_ASSERT(host);
	Process* application = process_new(pluginID, startTime, stopTime, arguments);
	g_queue_push_tail(host->applications, application);

	StartApplicationEvent* event = startapplication_new(application);
	worker_scheduleEvent((Event*)event, startTime, host->id);

	if(stopTime > startTime) {
		StopApplicationEvent* event = stopapplication_new(application);
		worker_scheduleEvent((Event*)event, stopTime, host->id);
	}
}
Example #10
0
struct process *
process_spawn(struct closure *k)
{
	struct vm *vm;
	struct process *p;

	vm = vm_new(current_process->vm->program, current_process->vm->prog_size);
	vm_set_pc(vm, k->label);

	vm->current_ar = activation_new_on_heap(
	    k->arity + k->locals, NULL, k->ar);

	p = process_new(vm);
#ifdef DEBUG
	if (trace_scheduling)
		printf("process #%d created\n", p->number);
#endif

	return(p);
}
Example #11
0
		Process::Process() {
			this->obj = process_new();
		}
Example #12
0
File: main.c Project: catseye/Bhuna
int
main(int argc, char **argv)
{
	char **real_argv = argv;
	struct scan_st *sc;
	struct symbol_table *stab;
	struct ast *a;
	char *source = NULL;
	int opt;
	int err_count = 0;
#ifdef DEBUG
	int run_program = 1;
	int dump_symbols = 0;
	int dump_program = 0;
	int dump_icode = 0;
#endif

#ifdef DEBUG
	setvbuf(stdout, NULL, _IOLBF, 0);
#endif

	/*
	 * Get command-line arguments.
	 */
	while ((opt = getopt(argc, argv, OPTS)) != -1) {
		switch(opt) {
#ifdef DEBUG
		case 'c':
			trace_scheduling++;
			break;
#ifdef POOL_VALUES
		case 'd':
			trace_pool++;
			break;
#endif
		case 'g':
			trace_gc++;
			break;
#endif
		case 'G':
			gc_trigger = atoi(optarg);
			break;
#ifdef DEBUG
		case 'i':
			dump_icode++;
			break;
		case 'l':
			trace_gen++;
			break;
		case 'm':
			trace_vm++;
			break;
		case 'n':
			run_program = 0;
			break;
		case 'o':
			trace_valloc++;
			break;
		case 'p':
			dump_program = 1;
			break;
		case 's':
			dump_symbols = 1;
			break;
		case 'v':
			trace_activations++;
			break;
		case 'y':
			trace_type_inference++;
			break;
#endif
		case '?':
		default:
			usage(argv);
		}
	}
	argc -= optind;
	argv += optind;

	if (*argv != NULL)
		source = *argv;
	else
		usage(real_argv);

#ifdef POOL_VALUES
	value_pool_new();
#endif

	gc_target = gc_trigger;
	if ((sc = scan_open(source)) != NULL) {
		stab = symbol_table_new(NULL, 0);
		global_ar = activation_new_on_heap(100, NULL, NULL);
		register_std_builtins(stab);
		report_start();
		a = parse_program(sc, stab);
		scan_close(sc);
#ifdef DEBUG
		if (dump_symbols)
			symbol_table_dump(stab, 1);
		if (dump_program) {
			ast_dump(a, 0);
		}
#endif
#ifndef DEBUG
		symbol_table_free(stab);
		types_free();
#endif
		err_count = report_finish();
		if (err_count == 0) {
			struct iprogram *ip;
			struct vm *vm;
			struct process *p;
			unsigned char *program;

			program = bhuna_malloc(16384);

			ip = ast_gen_iprogram(a);
			iprogram_eliminate_nops(ip);
			iprogram_eliminate_useless_jumps(ip);
			iprogram_optimize_tail_calls(ip);
			iprogram_optimize_push_small_ints(ip);
			iprogram_eliminate_dead_code(ip);
			iprogram_gen(&program, ip);
#ifdef DEBUG
			if (dump_icode > 0)
				iprogram_dump(ip, program);
#endif

			vm = vm_new(program, 16384);
			vm_set_pc(vm, program);
			vm->current_ar = global_ar;
			p = process_new(vm);
			/* ast_dump(a, 0); */
			if (RUN_PROGRAM) {
				process_scheduler();
			}
			vm_free(vm);
			bhuna_free(program);
			/*value_dump_global_table();*/
		}

		ast_free(a);	/* XXX move on up */
		/* gc(); */		/* actually do a full blow out at the end */
		/* activation_free_from_stack(global_ar); */
#ifdef DEBUG
		symbol_table_free(stab);
		types_free();
		if (trace_valloc > 0) {
			/*
			value_dump_global_table();
			*/
			printf("Created:  %8d\n", num_vars_created);
			printf("Cached:   %8d\n", num_vars_cached);
			printf("Freed:    %8d\n", num_vars_freed);
		}
		if (trace_activations > 0) {
			printf("AR's alloc'ed:  %8d\n", activations_allocated);
			printf("AR's freed:     %8d\n", activations_freed);
		}
#ifdef POOL_VALUES
		if (trace_pool > 0) {
			pool_report();
		}
#endif
#endif
		return(0);
	} else {
		fprintf(stderr, "Can't open `%s'\n", source);
		return(1);
	}
}
Example #13
0
int backup_phase2_server_protocol1(struct async *as, struct sdirs *sdirs,
	const char *incexc, int resume, struct conf **cconfs)
{
	int ret=0;
	struct manio *p1manio=NULL;
	struct dpth *dpth=NULL;
	char *deltmppath=NULL;
	char *last_requested=NULL;
	// Where to write changed data.
	// Data is not getting written to a compressed file.
	// This is important for recovery if the power goes.
	struct fzp *chfp=NULL;
	struct fzp *ucfp=NULL; // unchanged data
	struct fzp *cmanfp=NULL; // previous (current) manifest.
	struct sbuf *cb=NULL; // file list in current manifest
	struct sbuf *p1b=NULL; // file list from client
	struct sbuf *rb=NULL; // receiving file from client
	struct asfd *asfd=as->asfd;
	int breaking=0;
	int breakcount=0;
	if(get_int(cconfs[OPT_BREAKPOINT])>=2000
	  && get_int(cconfs[OPT_BREAKPOINT])<3000)
	{
		breaking=get_int(cconfs[OPT_BREAKPOINT]);
		breakcount=breaking-2000;
	}

	logp("Begin phase2 (receive file data)\n");

	if(!(dpth=dpth_alloc())
	  || dpth_protocol1_init(dpth, sdirs->currentdata,
		get_int(cconfs[OPT_MAX_STORAGE_SUBDIRS])))
			goto error;

	if(open_previous_manifest(&cmanfp, sdirs, incexc, cconfs))
		goto error;

	if(get_int(cconfs[OPT_DIRECTORY_TREE]))
	{
		// Need to make sure we do not try to create a path that is
		// too long.
		if(build_path_w(sdirs->treepath)) goto error;
		treepathlen=strlen(sdirs->treepath);
		init_fs_max(sdirs->treepath);
	}

	if(!(p1manio=manio_alloc())
	  || manio_init_read(p1manio, sdirs->phase1data)
	  || !(cb=sbuf_alloc(cconfs))
	  || !(p1b=sbuf_alloc(cconfs))
	  || !(rb=sbuf_alloc(cconfs)))
		goto error;

	manio_set_protocol(p1manio, PROTO_1);

	if(resume && do_resume(p1manio, sdirs, dpth, cconfs))
		goto error;

	// Unchanged and changed should now be truncated correctly, we just
	// have to open them for appending.
	if(!(ucfp=fzp_open(sdirs->unchanged, "a+b"))
	  || !(chfp=fzp_open(sdirs->changed, "a+b")))
		goto error;

	if(manio_closed(p1manio)
	  && manio_open_next_fpath(p1manio))
		goto error;

	while(1)
	{
		if(breaking)
		{
			if(breakcount--==0) return breakpoint(cconfs, __func__);
		}

		//printf("in loop, %s %s %c\n",
		//	cmanfp?"got cmanfp":"no cmanfp",
		//	rb->path.buf?:"no rb->path",
	 	//	rb->path.buf?'X':rb->path.cmd);
		if(write_status(CNTR_STATUS_BACKUP,
			rb->path.buf?rb->path.buf:p1b->path.buf, cconfs))
				goto error;
		if(last_requested
		  || manio_closed(p1manio)
		  || asfd->writebuflen)
		{
			switch(do_stuff_to_receive(asfd, sdirs,
				cconfs, rb, chfp, dpth, &last_requested))
			{
				case 0: break;
				case 1: goto end; // Finished ok.
				case -1: goto error;
			}
		}

		switch(do_stuff_to_send(asfd, p1b, &last_requested))
		{
			case 0: break;
			case 1: continue;
			case -1: goto error;
		}

		if(manio_closed(p1manio)) continue;

		sbuf_free_content(p1b);

		switch(manio_sbuf_fill_phase1(p1manio, asfd,
			p1b, NULL, sdirs, cconfs))
		{
			case 0: break;
			case 1: manio_close(p1manio);
				if(asfd->write_str(asfd,
				  CMD_GEN, "backupphase2end")) goto error;
				break;
			case -1: goto error;
		}

		if(!cmanfp)
		{
			// No old manifest, need to ask for a new file.
			if(process_new(sdirs, cconfs, p1b, ucfp))
				goto error;
			continue;
		}

		// Have an old manifest, look for it there.

		// Might already have it, or be ahead in the old
		// manifest.
		if(cb->path.buf) switch(maybe_process_file(asfd,
			sdirs, cb, p1b, ucfp, cconfs))
		{
			case 0: break;
			case 1: continue;
			case -1: goto error;
		}

		while(cmanfp)
		{
			sbuf_free_content(cb);
			switch(sbufl_fill(cb, asfd, cmanfp, cconfs))
			{
				case 0: break;
				case 1: fzp_close(&cmanfp);
					if(process_new(sdirs, cconfs, p1b,
						ucfp)) goto error;
					continue;
				case -1: goto error;
			}
			switch(maybe_process_file(asfd, sdirs,
				cb, p1b, ucfp, cconfs))
			{
				case 0: continue;
				case 1: break;
				case -1: goto error;
			}
			break;
		}
	}

error:
	ret=-1;
end:
	if(fzp_close(&chfp))
	{
		logp("error closing %s in %s\n", sdirs->changed, __func__);
		ret=-1;
	}
	if(fzp_close(&ucfp))
	{
		logp("error closing %s in %s\n", sdirs->unchanged, __func__);
		ret=-1;
	}
	free_w(&deltmppath);
	sbuf_free(&cb);
	sbuf_free(&p1b);
	sbuf_free(&rb);
	manio_free(&p1manio);
	fzp_close(&cmanfp);
	dpth_free(&dpth);
	if(!ret) unlink(sdirs->phase1data);

	logp("End phase2 (receive file data)\n");

	return ret;
}
Example #14
0
int backup_phase2_server(struct asfd *asfd,
	struct sdirs *sdirs, struct conf *cconf,
	gzFile *cmanfp, struct dpthl *dpthl, int resume)
{
	int ars=0;
	int ret=0;
	gzFile p1zp=NULL;
	char *deltmppath=NULL;
	char *last_requested=NULL;
	// Where to write phase2data.
	// Data is not getting written to a compressed file.
	// This is important for recovery if the power goes.
	FILE *p2fp=NULL;
	// unchanged data
	FILE *ucfp=NULL;

	struct sbuf *cb=NULL; // file list in current manifest
	struct sbuf *p1b=NULL; // file list from client

	struct sbuf *rb=NULL; // receiving file from client

	if(!(cb=sbuf_alloc(cconf))
	  || !(p1b=sbuf_alloc(cconf))
	  || !(rb=sbuf_alloc(cconf)))
		goto error;

	if(!(p1zp=gzopen_file(sdirs->phase1data, "rb")))
		goto error;

	// Open in read+write mode, so that they can be read through if
	// we need to resume.
	// First, open them in a+ mode, so that they will be created if they
	// do not exist.
	if(!(ucfp=open_file(sdirs->unchangeddata, "a+b"))
	  || !(p2fp=open_file(sdirs->phase2data, "a+b")))
		goto error;
	close_fp(&ucfp);
	close_fp(&p2fp);
	if(!(ucfp=open_file(sdirs->unchangeddata, "r+b"))
	  || !(p2fp=open_file(sdirs->phase2data, "r+b")))
		goto error;

	if(resume && do_resume(p1zp, p2fp, ucfp, dpthl, cconf))
		goto error;

	logp("Begin phase2 (receive file data)\n");

	while(1)
	{
		int sts=0;
		//printf("in loop, %s %s %c\n",
		//	*cmanfp?"got cmanfp":"no cmanfp",
		//	rb->path.buf?:"no rb->path",
	 	//	rb->path.buf?'X':rb->path.cmd);
		if(write_status(STATUS_BACKUP,
			rb->path.buf?rb->path.buf:p1b->path.buf, cconf))
				goto error;
		if((last_requested || !p1zp || asfd->writebuflen)
		  && (ars=do_stuff_to_receive(asfd, sdirs,
			cconf, rb, p2fp, dpthl, &last_requested)))
		{
			if(ars<0) goto error;
			// 1 means ok.
			break;
		}

		if((sts=do_stuff_to_send(asfd, p1b, &last_requested))<0)
			goto error;

		if(!sts && p1zp)
		{
		   sbuf_free_content(p1b);

		   if((ars=sbufl_fill_phase1(p1b, NULL, p1zp, cconf->cntr)))
		   {
			if(ars<0) goto error;
			// ars==1 means it ended ok.
			gzclose_fp(&p1zp);
			//logp("ended OK - write phase2end");
			if(asfd->write_str(asfd, CMD_GEN, "backupphase2end"))
				goto error;
		   }

		   //logp("check: %s\n", p1b.path);

		   if(!*cmanfp)
		   {
			// No old manifest, need to ask for a new file.
			//logp("no cmanfp\n");
			if(process_new(sdirs, cconf, p1b, ucfp, dpthl))
				goto error;
		   }
		   else
		   {
			// Have an old manifest, look for it there.

			// Might already have it, or be ahead in the old
			// manifest.
			if(cb->path.buf)
			{
				if((ars=maybe_process_file(asfd, sdirs, cconf,
					cb, p1b, ucfp, dpthl)))
				{
					if(ars<0) goto error;
					// Do not free it - need to send stuff.
					continue;
				}
				//free_sbufl(&p1b);
			}

			while(*cmanfp)
			{
				sbuf_free_content(cb);
				if((ars=sbufl_fill(cb, asfd, NULL,
					*cmanfp, cconf->cntr)))
				{
					// ars==1 means it ended ok.
					if(ars<0) goto error;
					gzclose_fp(cmanfp);
		//logp("ran out of current manifest\n");
					if(process_new(sdirs, cconf,
						p1b, ucfp, dpthl))
							goto error;
					break;
				}
		//logp("against: %s\n", cb.path);
				if((ars=maybe_process_file(asfd, sdirs, cconf,
					cb, p1b, ucfp, dpthl)))
				{
					if(ars<0) goto error;
					// Do not free it - need to send stuff.
					break;
				}
			}
		   }
		}
	}

	goto end;

error:
	ret=-1;
end:
	if(close_fp(&p2fp))
	{
		logp("error closing %s in backup_phase2_server\n",
			sdirs->phase2data);
		ret=-1;
	}
	if(close_fp(&ucfp))
	{
		logp("error closing %s in backup_phase2_server\n",
			sdirs->unchangeddata);
		ret=-1;
	}
	free(deltmppath);
	sbuf_free(cb);
	sbuf_free(p1b);
	sbuf_free(rb);
	gzclose_fp(&p1zp);
	if(!ret) unlink(sdirs->phase1data);

	logp("End phase2 (receive file data)\n");

	return ret;
}
Example #15
0
File: proc.c Project: clarkok/CoS
int
proc_do_fork()
{ return process_new(current_process->name, current_process)->id; }
Example #16
0
proc *process_run(char executable[], char *args[], int timeout)
{
	proc *retval = NULL;
	char *text;
	int status;
	tl_stream stdout_p;
	tl_stream stdin_p;
	SECURITY_ATTRIBUTES saAttr; 
	PROCESS_INFORMATION pi;
	STARTUPINFO si;
	BOOL createproc_success = FALSE; 
	BOOL timedout = FALSE; 
	TCHAR *commandline = NULL;

	proc *p = process_new();

	if (p == NULL)
		return NULL;

	/* Make sure pipe handles are inherited */
	saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
	saAttr.bInheritHandle = TRUE; 
	saAttr.lpSecurityDescriptor = NULL; 
	
	p->causeofdeath = PROC_PIPECREATE;

	DEBUG(("making pipes \n"));
	/* Child's Stdout */
	if ( ! CreatePipe(&stdout_p.read, &stdout_p.write, &saAttr, 1) ) 
	{
		printlasterror();
		RETURN(p);
	}
	DEBUG(("stdout done \n"));
	
	/* read handle to the pipe for STDOUT is not inherited */
	if ( ! SetHandleInformation(stdout_p.read, HANDLE_FLAG_INHERIT, 0) )
	{
		printlasterror();
		RETURN(p); 
	}
	DEBUG(("stdout noinherit \n"));
	
	/* a pipe for the child process's STDIN */
	if ( ! CreatePipe(&stdin_p.read, &stdin_p.write, &saAttr, 0) ) 
	{
		printlasterror();
		RETURN(p); 
	}
	DEBUG(("stdin done \n"));
	
	/*  write handle to the pipe for STDIN not inherited */
	if ( ! SetHandleInformation(stdin_p.read, HANDLE_FLAG_INHERIT, 0) )
	{
		printlasterror();
		RETURN(p); 
	}
	DEBUG(("pipes done \n"));
	
	
	p->causeofdeath = PROC_START;

	ZeroMemory( &si, sizeof(STARTUPINFO) );
	ZeroMemory( &pi, sizeof(PROCESS_INFORMATION) );
	
	si.cb = sizeof(STARTUPINFO); 
	si.hStdError = stdout_p.write;
	si.hStdOutput = stdout_p.write;
	/*
	  Rather than use the stdin pipe, which would be
       		  si.hStdInput = stdin_p.read;
	  Pass on talon's own standard input to the child process
	  This helps with programs like xcopy which demand that
	  they are attached to a console and not just any type of
	  input file.
	 */
	si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
	si.dwFlags |= STARTF_USESTDHANDLES;

	
	DEBUG(("pre commandline \n"));
	/* create the commandline string */
	int len = 0;
	int i = 0;
	while (args[i] != NULL)
	{
		len += strlen(args[i++]) + 1;
	}
	len+=2;

	commandline = malloc(len*2);
	if (! commandline) 
		RETURN(p);
	commandline[0] = '\0';

	i = 0;
	while (args[i] != NULL)
	{
		strcat(commandline, args[i]);
		strcat(commandline, " ");
		i++;
	}


	/* Get the read thread ready to go before creating
	 * the process.
	 */
	ReadOpQ *ropq  = malloc(sizeof(ReadOpQ));

	ropq->first=NULL;
	ropq->last=NULL;
	ropq->semaphore = CreateSemaphore(NULL, 0, 1, NULL);
	DEBUG(("Creating read thread. \n"));

	DWORD readpipe_threadid;
	HANDLE h_readpipe_thread = CreateThread(NULL, 8192, (LPTHREAD_START_ROUTINE) readpipe_thread, (void*)ropq, 0, &readpipe_threadid);

	/* ready to run the process */
 
	DEBUG(("process commandline:\n%s \n", commandline));
	DEBUG(("\n"));
	createproc_success = CreateProcess(executable, 
	   commandline,     // command line 
	   NULL,          // process security attributes 
	   NULL,          // primary thread security attributes 
	   TRUE,          // handles are inherited 
	   0,             // creation flags 
	   NULL,          // use parent's environment 
	   NULL,          // use parent's current directory 
	   &si,  // STARTUPINFO pointer 
	   &pi);  // receives PROCESS_INFORMATION 

	if (! createproc_success)
	{
		DEBUG(("Createprocess failed. \n"));
		p->causeofdeath = PROC_SOMEODDDEATH;
		RETURN(p);
	}

	int have_status = 0;


	DEBUG(("Closing Handles. \n"));
	if (!CloseHandle(stdout_p.write)) 
		RETURN(p);
	if (!CloseHandle(stdin_p.read)) 
		RETURN(p);

	DEBUG(("Closed Handles. \n"));


	static int id=0;
	do
	{
		char *space = buffer_makespace(p->output, READSIZE);

		DWORD waitres;
		ReadOp *iopipe_op = malloc(sizeof(ReadOp));
		iopipe_op->semaphore = CreateSemaphore(NULL, 0, 1, NULL);
		iopipe_op->thread =  h_readpipe_thread;
		iopipe_op->timeout = timeout;
		iopipe_op->file = stdout_p.read;
		iopipe_op->space = malloc(READSIZE);
		iopipe_op->id = id++;
		iopipe_op->nbytes = READSIZE;
		iopipe_op->next = NULL;

		if (!ropq->first)
		{
			ropq->first = iopipe_op;
			ropq->last = iopipe_op;
		} else {
			ropq->last->next = iopipe_op;
			ropq->last = iopipe_op;
		}

		ReleaseSemaphore(ropq->semaphore, 1, NULL);

		DEBUG(("waiting for read %d\n", timeout));
		waitres = WaitForSingleObject(iopipe_op->semaphore, timeout);
		DEBUG(("read wait finished result= %d\n", waitres));

		if (waitres != WAIT_OBJECT_0)
		{
			DEBUG(("timeout \n"));
			timedout = TRUE;
			break;
		}
		else
		{
			DEBUG(("read signalled: nbytes: %d \n", iopipe_op->nbytes));
			if (iopipe_op->nbytes <= 0)
			{
				break;
			}
			memcpy(space, iopipe_op->space, iopipe_op->nbytes);	
			buffer_usespace(p->output, iopipe_op->nbytes);	
			DEBUG(("buffer took on nbytes: %d \n", iopipe_op->nbytes));
		}
	}
	while (1);

	if (timedout == FALSE) 
	{
		DEBUG(("Wait for process exit\n"));
		// Wait until child process exits.
		WaitForSingleObject(pi.hProcess, INFINITE);
		DEBUG(("Process exited\n"));

		DWORD exitcode;

		if (GetExitCodeProcess(pi.hProcess, &exitcode))
		{
			p->causeofdeath = PROC_NORMALDEATH;
			p->returncode = exitcode;
			DEBUG(("process exited normally = %d:\n", p->returncode));
			RETURN(p);	
		} else {
			p->causeofdeath = PROC_SOMEODDDEATH;
			p->returncode = 128;
			DEBUG(("process terminated \n"));
			RETURN(p);	
		}
	} else {
		TerminateProcess(pi.hProcess,1);
		p->causeofdeath = PROC_TIMEOUTDEATH;
		p->returncode = 128;
		DEBUG(("process timedout \n"));
		RETURN(p);	
	}

	/* Clean up the read operation queue 
	ReadOp *r = ropq.first;
	do
	{
		CloseHandle(r->semaphore);
		free(r->space);
		free(r);
		r = r->next;
	} while (r != NULL); */

	CLEANUP();
	if (retval == NULL)
	{
		if (p)
			process_free(&p);
	}
	if (commandline)
		free(commandline);
	
	return retval;
}
Example #17
0
/* Test the configure_proxy() function. */
static void
test_pt_configure_proxy(void *arg)
{
  int i, retval;
  managed_proxy_t *mp = NULL;
  (void) arg;

  dummy_state = tor_malloc_zero(sizeof(or_state_t));

  MOCK(process_read_stdout, process_read_stdout_replacement);
  MOCK(get_or_state,
       get_or_state_replacement);
  MOCK(queue_control_event_string,
       queue_control_event_string_replacement);

  control_testing_set_global_event_mask(EVENT_TRANSPORT_LAUNCHED);

  mp = tor_malloc_zero(sizeof(managed_proxy_t));
  mp->conf_state = PT_PROTO_ACCEPTING_METHODS;
  mp->transports = smartlist_new();
  mp->transports_to_launch = smartlist_new();
  mp->argv = tor_malloc_zero(sizeof(char*)*2);
  mp->argv[0] = tor_strdup("<testcase>");
  mp->is_server = 1;

  /* Configure the process. */
  mp->process = process_new("");
  process_set_stdout_read_callback(mp->process, managed_proxy_stdout_callback);
  process_set_data(mp->process, mp);

  /* Test the return value of configure_proxy() by calling it some
     times while it is uninitialized and then finally finalizing its
     configuration. */
  for (i = 0 ; i < 5 ; i++) {
    /* force a read from our mocked stdout reader. */
    process_notify_event_stdout(mp->process);
    /* try to configure our proxy. */
    retval = configure_proxy(mp);
    /* retval should be zero because proxy hasn't finished configuring yet */
    tt_int_op(retval, OP_EQ, 0);
    /* check the number of registered transports */
    tt_int_op(smartlist_len(mp->transports), OP_EQ, i+1);
    /* check that the mp is still waiting for transports */
    tt_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);
  }

  /* Get the SMETHOD DONE written to the process. */
  process_notify_event_stdout(mp->process);

  /* this last configure_proxy() should finalize the proxy configuration. */
  retval = configure_proxy(mp);
  /* retval should be 1 since the proxy finished configuring */
  tt_int_op(retval, OP_EQ, 1);
  /* check the mp state */
  tt_assert(mp->conf_state == PT_PROTO_COMPLETED);

  tt_int_op(controlevent_n, OP_EQ, 5);
  tt_int_op(controlevent_event, OP_EQ, EVENT_TRANSPORT_LAUNCHED);
  tt_int_op(smartlist_len(controlevent_msgs), OP_EQ, 5);
  smartlist_sort_strings(controlevent_msgs);
  tt_str_op(smartlist_get(controlevent_msgs, 0), OP_EQ,
            "650 TRANSPORT_LAUNCHED server mock1 127.0.0.1 5551\r\n");
  tt_str_op(smartlist_get(controlevent_msgs, 1), OP_EQ,
            "650 TRANSPORT_LAUNCHED server mock2 127.0.0.1 5552\r\n");
  tt_str_op(smartlist_get(controlevent_msgs, 2), OP_EQ,
            "650 TRANSPORT_LAUNCHED server mock3 127.0.0.1 5553\r\n");
  tt_str_op(smartlist_get(controlevent_msgs, 3), OP_EQ,
            "650 TRANSPORT_LAUNCHED server mock4 127.0.0.1 5554\r\n");
  tt_str_op(smartlist_get(controlevent_msgs, 4), OP_EQ,
            "650 TRANSPORT_LAUNCHED server mock5 127.0.0.1 5555\r\n");

  /* Get the log message out. */
  process_notify_event_stdout(mp->process);

  tt_int_op(controlevent_n, OP_EQ, 10);
  tt_int_op(controlevent_event, OP_EQ, EVENT_PT_LOG);
  tt_int_op(smartlist_len(controlevent_msgs), OP_EQ, 10);
  tt_str_op(smartlist_get(controlevent_msgs, 5), OP_EQ,
            "650 PT_LOG PT=<testcase> SEVERITY=error "
            "MESSAGE=\"Oh noes, "
            "something bad happened. What do we do!?\"\r\n");
  tt_str_op(smartlist_get(controlevent_msgs, 6), OP_EQ,
            "650 PT_LOG PT=<testcase> SEVERITY=warning "
            "MESSAGE=\"warning msg\"\r\n");
  tt_str_op(smartlist_get(controlevent_msgs, 7), OP_EQ,
            "650 PT_LOG PT=<testcase> SEVERITY=notice "
            "MESSAGE=\"notice msg\"\r\n");
  tt_str_op(smartlist_get(controlevent_msgs, 8), OP_EQ,
            "650 PT_LOG PT=<testcase> SEVERITY=info "
            "MESSAGE=\"info msg\"\r\n");
  tt_str_op(smartlist_get(controlevent_msgs, 9), OP_EQ,
            "650 PT_LOG PT=<testcase> SEVERITY=debug "
            "MESSAGE=\"debug msg\"\r\n");

  /* Get the STATUS messages out. */
  process_notify_event_stdout(mp->process);

  tt_int_op(controlevent_n, OP_EQ, 13);
  tt_int_op(controlevent_event, OP_EQ, EVENT_PT_STATUS);
  tt_int_op(smartlist_len(controlevent_msgs), OP_EQ, 13);

  tt_str_op(smartlist_get(controlevent_msgs, 10), OP_EQ,
            "650 PT_STATUS "
            "PT=<testcase> TRANSPORT=a K_1=a K_2=b K_3=\"foo bar\"\r\n");
  tt_str_op(smartlist_get(controlevent_msgs, 11), OP_EQ,
            "650 PT_STATUS "
            "PT=<testcase> TRANSPORT=b K_1=a K_2=b K_3=\"foo bar\"\r\n");
  tt_str_op(smartlist_get(controlevent_msgs, 12), OP_EQ,
            "650 PT_STATUS "
            "PT=<testcase> TRANSPORT=c K_1=a K_2=b K_3=\"foo bar\"\r\n");

  { /* check that the transport info were saved properly in the tor state */
    config_line_t *transport_in_state = NULL;
    smartlist_t *transport_info_sl = smartlist_new();
    char *name_of_transport = NULL;
    char *bindaddr = NULL;

    /* Get the bindaddr for "mock1" and check it against the bindaddr
       that the mocked tor_get_lines_from_handle() generated. */
    transport_in_state = get_transport_in_state_by_name("mock1");
    tt_assert(transport_in_state);
    smartlist_split_string(transport_info_sl, transport_in_state->value,
                           NULL, 0, 0);
    name_of_transport = smartlist_get(transport_info_sl, 0);
    bindaddr = smartlist_get(transport_info_sl, 1);
    tt_str_op(name_of_transport, OP_EQ, "mock1");
    tt_str_op(bindaddr, OP_EQ, "127.0.0.1:5551");

    SMARTLIST_FOREACH(transport_info_sl, char *, cp, tor_free(cp));
    smartlist_free(transport_info_sl);
  }

 done:
  or_state_free(dummy_state);
  UNMOCK(process_read_stdout);
  UNMOCK(get_or_state);
  UNMOCK(queue_control_event_string);
  if (controlevent_msgs) {
    SMARTLIST_FOREACH(controlevent_msgs, char *, cp, tor_free(cp));
    smartlist_free(controlevent_msgs);
    controlevent_msgs = NULL;
  }
  if (mp->transports) {
    SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
    smartlist_free(mp->transports);
  }
Example #18
0
static int nl_handle_msg(struct cn_msg *cn_hdr)
{
	/* The event to consider */
	struct proc_event *ev;

	/* Return codes */
	int ret = 0;


	/* Get the event data.  We only care about two event types. */
	ev = (struct proc_event*)cn_hdr->data;
	switch (ev->what) {
	case PROC_EVENT_NONE:
		g_debug("netlink: successfully subscribed for listening to proc events");
		netlink_proc_listening = TRUE;
		break;
	// quite seldom events on old processes changing important parameters
	case PROC_EVENT_UID:
	  // skip threads
	  if(ev->event_data.id.process_tgid != ev->event_data.id.process_pid)
      break;
		u_trace("UID Event: PID = %d, tGID = %d, rUID = %d,"
				" eUID = %d", ev->event_data.id.process_pid,
				ev->event_data.id.process_tgid,
				ev->event_data.id.r.ruid,
				ev->event_data.id.e.euid);
    process_new(ev->event_data.id.process_pid, FALSE);
		break;
	case PROC_EVENT_GID:
	  // skip threads
	  if(ev->event_data.id.process_tgid != ev->event_data.id.process_pid)
      break;
		u_trace("GID Event: PID = %d, tGID = %d, rGID = %d,"
				" eGID = %d", ev->event_data.id.process_pid,
				ev->event_data.id.process_tgid,
				ev->event_data.id.r.rgid,
				ev->event_data.id.e.egid);
    process_new(ev->event_data.id.process_pid, FALSE);
		break;
	case PROC_EVENT_EXIT:
    /*
     * Skip threads,
     * We could remove thread from the thread leader tasks, but this is
     * currently useless, as we don't schedule tasks and we can wait for
     * the next iteration; tasks will be updated automatically.
     */
    if(ev->event_data.exit.process_tgid != ev->event_data.exit.process_pid)
      break;
		u_trace("EXIT Event: PID = %d", ev->event_data.exit.process_pid);
		//g_ptr_array_foreach(stack, remove_pid_from_stack, &pid);
		// if the pid was found in the new stack, pid is set to 0 to indicate
		// the removal
		process_remove_by_pid(ev->event_data.exit.process_pid);
		break;
	case PROC_EVENT_EXEC:
	  // skip threads, see above note
	  if(ev->event_data.exec.process_tgid != ev->event_data.exec.process_pid)
      break;
		u_trace("EXEC Event: PID = %d, tGID = %d",
				ev->event_data.exec.process_pid,
				ev->event_data.exec.process_tgid);
    process_new_delay(ev->event_data.exec.process_tgid, 0);
		break;
	case PROC_EVENT_FORK:
    // skip threads, see above note
    if(ev->event_data.fork.child_tgid != ev->event_data.fork.child_pid)
      break;
		u_trace("FORK Event: PARENT = <PID: %d, TGID: %d>, CHILD = <PID: %d, TGID = %d>",
		        ev->event_data.fork.parent_pid, ev->event_data.fork.parent_tgid,
		        ev->event_data.fork.child_pid, ev->event_data.fork.child_tgid);
		process_new_delay(ev->event_data.fork.child_tgid, ev->event_data.fork.parent_tgid);
		break;
	default:
		return 0;
	}

	return ret;
}
Example #19
0
// return 1 to say that a file was processed
static int maybe_process_file(struct asfd *asfd,
	struct sdirs *sdirs, struct conf *cconf,
	struct sbuf *cb, struct sbuf *p1b, FILE *ucfp,
	struct dpthl *dpthl)
{
	int pcmp;
	if(!(pcmp=sbuf_pathcmp(cb, p1b)))
	{
		int oldcompressed=0;

		// If the file type changed, I think it is time to back it
		// up again (for example, EFS changing to normal file, or
		// back again).
		if(cb->path.cmd!=p1b->path.cmd)
			return process_new_file(sdirs, cconf, cb, p1b, ucfp,
				dpthl);

		// mtime is the actual file data.
		// ctime is the attributes or meta data.
		if(cb->statp.st_mtime==p1b->statp.st_mtime
		  && cb->statp.st_ctime==p1b->statp.st_ctime)
		{
			// got an unchanged file
			//logp("got unchanged file: %s %c %c\n", cb->path, cb->cmd, p1b->cmd);
			return process_unchanged_file(cb, ucfp, cconf);
		}

		if(cb->statp.st_mtime==p1b->statp.st_mtime
		  && cb->statp.st_ctime!=p1b->statp.st_ctime)
		{
			// File data stayed the same, but attributes or meta
			// data changed. We already have the attributes, but
			// may need to get extra meta data.
			if(cb->path.cmd==CMD_ENC_METADATA
			  || p1b->path.cmd==CMD_ENC_METADATA
			// TODO: make unencrypted metadata use the librsync
			  || cb->path.cmd==CMD_METADATA
			  || p1b->path.cmd==CMD_METADATA
			  || cb->path.cmd==CMD_VSS
			  || p1b->path.cmd==CMD_VSS
			  || cb->path.cmd==CMD_ENC_VSS
			  || p1b->path.cmd==CMD_ENC_VSS
			  || cb->path.cmd==CMD_VSS_T
			  || p1b->path.cmd==CMD_VSS_T
			  || cb->path.cmd==CMD_ENC_VSS_T
			  || p1b->path.cmd==CMD_ENC_VSS_T
			  || cb->path.cmd==CMD_EFS_FILE
			  || p1b->path.cmd==CMD_EFS_FILE)
				return process_new_file(sdirs, cconf, cb,
					p1b, ucfp, dpthl);
			// On Windows, we have to back up the whole file if
			// ctime changed, otherwise things like permission
			// changes do not get noticed. So, in that case, fall
			// through to the changed stuff below.
			// Non-Windows clients finish here.
			else if(!cconf->client_is_windows)
				return process_unchanged_file(cb, ucfp, cconf);
		}

		// Got a changed file.
		//logp("got changed file: %s\n", p1b->path);

		// If either old or new is encrypted, or librsync is off,
		// we need to get a new file.
		if(!cconf->librsync
		  || cb->path.cmd==CMD_ENC_FILE
		  || p1b->path.cmd==CMD_ENC_FILE
		  || cb->path.cmd==CMD_ENC_METADATA
		  || p1b->path.cmd==CMD_ENC_METADATA
		  || cb->path.cmd==CMD_EFS_FILE
		  || p1b->path.cmd==CMD_EFS_FILE
		// TODO: make unencrypted metadata use the librsync
		  || cb->path.cmd==CMD_METADATA
		  || p1b->path.cmd==CMD_METADATA
		  || cb->path.cmd==CMD_VSS
		  || p1b->path.cmd==CMD_VSS
		  || cb->path.cmd==CMD_ENC_VSS
		  || p1b->path.cmd==CMD_ENC_VSS
		  || cb->path.cmd==CMD_VSS_T
		  || p1b->path.cmd==CMD_VSS_T
		  || cb->path.cmd==CMD_ENC_VSS_T
		  || p1b->path.cmd==CMD_ENC_VSS_T)
			return process_new_file(sdirs, cconf, cb, p1b, ucfp,
				dpthl);

		// Get new files if they have switched between compression on
		// or off.
		if(cb->burp1->datapth.buf
		  && dpthl_is_compressed(cb->compression, cb->burp1->datapth.buf))
			oldcompressed=1;
		if( ( oldcompressed && !cconf->compression)
		 || (!oldcompressed &&  cconf->compression))
			return process_new_file(sdirs, cconf, cb, p1b, ucfp,
				dpthl);

		// Otherwise, do the delta stuff (if possible).
		if(filedata(p1b->path.cmd))
		{
			if(process_changed_file(asfd, sdirs, cconf, cb, p1b,
				sdirs->currentdata)) return -1;
		}
		else
		{
			if(changed_non_file(p1b, ucfp, p1b->path.cmd, cconf))
				return -1;
		}
		sbuf_free_content(cb);
		return 1;
	}
	else if(pcmp>0)
	{
		//logp("ahead: %s\n", p1b->path);
		// ahead - need to get the whole file
		if(process_new(sdirs, cconf, p1b, ucfp, dpthl)) return -1;
		// do not free
		return 1;
	}
	else
	{
		//logp("behind: %s\n", p1b->path);
		// behind - need to read more from the old
		// manifest
		// Count a deleted file - it was in the old manifest but not
		// the new.
		cntr_add_deleted(cconf->cntr, cb->path.cmd);
	}
	return 0;
}
Example #20
0
static int nl_handle_msg(struct cn_msg *cn_hdr)
{
	/* The event to consider */
	struct proc_event *ev;

	/* Return codes */
	int ret = 0;


	/* Get the event data.  We only care about two event types. */
	ev = (struct proc_event*)cn_hdr->data;
	switch (ev->what) {
	case PROC_EVENT_NONE:
		g_debug("netlink: successfully subscribed for listening to proc events");
		netlink_proc_listening = TRUE;
		break;
	// quite seldom events on old processes changing important parameters
	case PROC_EVENT_UID:
	  // skip threads
	  if(ev->event_data.id.process_tgid != ev->event_data.id.process_pid)
      break;
		u_trace("UID Event: PID = %d, tGID = %d, rUID = %d,"
				" eUID = %d", ev->event_data.id.process_pid,
				ev->event_data.id.process_tgid,
				ev->event_data.id.r.ruid,
				ev->event_data.id.e.euid);
    process_new(ev->event_data.id.process_pid, FALSE);
		break;
	case PROC_EVENT_GID:
	  // skip threads
	  if(ev->event_data.id.process_tgid != ev->event_data.id.process_pid)
      break;
		u_trace("GID Event: PID = %d, tGID = %d, rGID = %d,"
				" eGID = %d", ev->event_data.id.process_pid,
				ev->event_data.id.process_tgid,
				ev->event_data.id.r.rgid,
				ev->event_data.id.e.egid);
    process_new(ev->event_data.id.process_pid, FALSE);
		break;
	case PROC_EVENT_EXIT:
    // skip threads
    if(ev->event_data.exit.process_tgid != ev->event_data.exit.process_pid)
      break;
		u_trace("EXIT Event: PID = %d", ev->event_data.exit.process_pid);
		//g_ptr_array_foreach(stack, remove_pid_from_stack, &pid);
		// if the pid was found in the new stack, pid is set to 0 to indicate
		// the removal
		process_remove_by_pid(ev->event_data.exit.process_pid);
		break;
	case PROC_EVENT_EXEC:
	  // skip threads
	  if(ev->event_data.exec.process_tgid != ev->event_data.exec.process_pid)
      break;
		u_trace("EXEC Event: PID = %d, tGID = %d",
				ev->event_data.exec.process_pid,
				ev->event_data.exec.process_tgid);
    process_new_delay(ev->event_data.exec.process_tgid, 0);
		break;
	case PROC_EVENT_FORK:
    // we skip new threads for now
    // FIXME need filter block to get those events
    if(ev->event_data.fork.parent_tgid != ev->event_data.fork.child_pid)
      break;
		u_trace("FORK Event: PARENT = %d PID = %d tGID = %d",
			ev->event_data.fork.parent_tgid, ev->event_data.fork.child_pid, ev->event_data.fork.child_tgid);

		// parent does not mean the parent of the new proc, but the parent of
		// the forking process. so we lookup the parent of the forking process
		// first

		u_proc *rparent = proc_by_pid(ev->event_data.fork.parent_tgid);
		if(rparent) {
			u_proc_ensure(rparent, BASIC, NOUPDATE);
			process_new_delay(ev->event_data.fork.child_tgid, rparent->proc->ppid); //ev->event_data.fork.parent_pid);
		} else
			process_new_delay(ev->event_data.fork.child_tgid, 0);
		break;
	default:
		return 0;
	}

	return ret;
}
Example #21
0
// return 1 to say that a file was processed
static int maybe_process_file(struct sbuf *cb, struct sbuf *p1b, FILE *ucfp, const char *currentdata, const char *datadirtmp, const char *deltmppath, struct dpth *dpth, int *resume_partial, struct cntr *cntr, struct config *cconf)
{
	int pcmp;
//	logp("in maybe_proc %s\n", p1b->path);
	if(!(pcmp=sbuf_pathcmp(cb, p1b)))
	{
		int oldcompressed=0;

		// If the file type changed, I think it is time to back it
		// up again (for example, EFS changing to normal file, or
		// back again).
		if(cb->cmd!=p1b->cmd)
			return process_new_file(cb, p1b, ucfp, currentdata,
				datadirtmp, deltmppath,
				dpth, resume_partial,
				cntr, cconf);

		// mtime is the actual file data.
		// ctime is the attributes or meta data.
		if(cb->statp.st_mtime==p1b->statp.st_mtime
		  && cb->statp.st_ctime==p1b->statp.st_ctime)
		{
			// got an unchanged file
			//logp("got unchanged file: %s %c %c\n", cb->path, cb->cmd, p1b->cmd);
			return process_unchanged_file(cb, ucfp, cntr);
		}

		if(cb->statp.st_mtime==p1b->statp.st_mtime
		  && cb->statp.st_ctime!=p1b->statp.st_ctime)
		{
			// File data stayed the same, but attributes or meta
			// data changed. We already have the attributes, but
			// may need to get extra meta data.
			if(cb->cmd==CMD_ENC_METADATA
			  || p1b->cmd==CMD_ENC_METADATA
			// TODO: make unencrypted metadata use the librsync
			  || cb->cmd==CMD_METADATA
			  || p1b->cmd==CMD_METADATA
			  || cb->cmd==CMD_VSS
			  || p1b->cmd==CMD_VSS
			  || cb->cmd==CMD_ENC_VSS
			  || p1b->cmd==CMD_ENC_VSS
			  || cb->cmd==CMD_VSS_T
			  || p1b->cmd==CMD_VSS_T
			  || cb->cmd==CMD_ENC_VSS_T
			  || p1b->cmd==CMD_ENC_VSS_T
			  || cb->cmd==CMD_EFS_FILE
			  || p1b->cmd==CMD_EFS_FILE)
				return process_new_file(cb,
					p1b, ucfp, currentdata,
					datadirtmp, deltmppath,
					dpth, resume_partial,
					cntr, cconf);
			else
				return process_unchanged_file(cb, ucfp, cntr);
		}

		// Got a changed file.
		//logp("got changed file: %s\n", p1b->path);

		// If either old or new is encrypted, or librsync is off,
		// we need to get a new file.
		if(!cconf->librsync
		  || cb->cmd==CMD_ENC_FILE
		  || p1b->cmd==CMD_ENC_FILE
		  || cb->cmd==CMD_ENC_METADATA
		  || p1b->cmd==CMD_ENC_METADATA
		  || cb->cmd==CMD_EFS_FILE
		  || p1b->cmd==CMD_EFS_FILE
		// TODO: make unencrypted metadata use the librsync
		  || cb->cmd==CMD_METADATA
		  || p1b->cmd==CMD_METADATA
		  || cb->cmd==CMD_VSS
		  || p1b->cmd==CMD_VSS
		  || cb->cmd==CMD_ENC_VSS
		  || p1b->cmd==CMD_ENC_VSS
		  || cb->cmd==CMD_VSS_T
		  || p1b->cmd==CMD_VSS_T
		  || cb->cmd==CMD_ENC_VSS_T
		  || p1b->cmd==CMD_ENC_VSS_T)
			return process_new_file(cb, p1b, ucfp, currentdata,
				datadirtmp, deltmppath,
				dpth, resume_partial,
				cntr, cconf);

		// Get new files if they have switched between compression on
		// or off.
		if(cb->datapth && dpth_is_compressed(cb->compression, cb->datapth))
			oldcompressed=1;
		if( ( oldcompressed && !cconf->compression)
		 || (!oldcompressed &&  cconf->compression))
			return process_new_file(cb, p1b, ucfp, currentdata,
				datadirtmp, deltmppath,
				dpth, resume_partial,
				cntr, cconf);

		// Otherwise, do the delta stuff (if possible).
		if(filedata(p1b->cmd))
		{
			if(process_changed_file(cb, p1b, currentdata,
				datadirtmp, deltmppath, resume_partial,
				cntr, cconf)) return -1;
		}
		else
		{
			if(changed_non_file(p1b, ucfp, p1b->cmd, cntr))
				return -1;
		}
		free_sbuf(cb);
		return 1;
	}
	else if(pcmp>0)
	{
		//logp("ahead: %s\n", p1b->path);
		// ahead - need to get the whole file
		if(process_new(p1b, ucfp, currentdata, datadirtmp, deltmppath,
			dpth, resume_partial, cntr, cconf)) return -1;
		// do not free
		return 1;
	}
	else
	{
		//logp("behind: %s\n", p1b->path);
		// behind - need to read more from the old
		// manifest
		// Count a deleted file - it was in the old manifest but not
		// the new.
		do_filecounter_deleted(cntr, cb->cmd);
	}
	return 0;
}
Example #22
0
int
fork1(struct proc *p1, int exitsig, int flags, void *stack, size_t stacksize,
    void (*func)(void *), void *arg, register_t *retval,
    struct proc **rnewprocp)
{
	struct proc *p2;
	uid_t uid;
	struct vmspace *vm;
	int count;
	vaddr_t uaddr;
	int s;
	extern void endtsleep(void *);
	extern void realitexpire(void *);

	/*
	 * Although process entries are dynamically created, we still keep
	 * a global limit on the maximum number we will create. We reserve
	 * the last 5 processes to root. The variable nprocs is the current
	 * number of processes, maxproc is the limit.
	 */
	uid = p1->p_cred->p_ruid;
	if ((nprocs >= maxproc - 5 && uid != 0) || nprocs >= maxproc) {
		static struct timeval lasttfm;

		if (ratecheck(&lasttfm, &fork_tfmrate))
			tablefull("proc");
		return (EAGAIN);
	}
	nprocs++;

	/*
	 * Increment the count of procs running with this uid. Don't allow
	 * a nonprivileged user to exceed their current limit.
	 */
	count = chgproccnt(uid, 1);
	if (uid != 0 && count > p1->p_rlimit[RLIMIT_NPROC].rlim_cur) {
		(void)chgproccnt(uid, -1);
		nprocs--;
		return (EAGAIN);
	}

	uaddr = uvm_km_alloc1(kernel_map, USPACE, USPACE_ALIGN, 1);
	if (uaddr == 0) {
		chgproccnt(uid, -1);
		nprocs--;
		return (ENOMEM);
	}

	/*
	 * From now on, we're committed to the fork and cannot fail.
	 */

	/* Allocate new proc. */
	p2 = pool_get(&proc_pool, PR_WAITOK);

	p2->p_stat = SIDL;			/* protect against others */
	p2->p_exitsig = exitsig;
	p2->p_forw = p2->p_back = NULL;

#ifdef RTHREADS
	if (flags & FORK_THREAD) {
		atomic_setbits_int(&p2->p_flag, P_THREAD);
		p2->p_p = p1->p_p;
		TAILQ_INSERT_TAIL(&p2->p_p->ps_threads, p2, p_thr_link);
	} else {
		process_new(p2, p1);
	}
#else
	process_new(p2, p1);
#endif

	/*
	 * Make a proc table entry for the new process.
	 * Start by zeroing the section of proc that is zero-initialized,
	 * then copy the section that is copied directly from the parent.
	 */
	bzero(&p2->p_startzero,
	    (unsigned) ((caddr_t)&p2->p_endzero - (caddr_t)&p2->p_startzero));
	bcopy(&p1->p_startcopy, &p2->p_startcopy,
	    (unsigned) ((caddr_t)&p2->p_endcopy - (caddr_t)&p2->p_startcopy));

	/*
	 * Initialize the timeouts.
	 */
	timeout_set(&p2->p_sleep_to, endtsleep, p2);
	timeout_set(&p2->p_realit_to, realitexpire, p2);

#if defined(__HAVE_CPUINFO)
	p2->p_cpu = p1->p_cpu;
#endif

	/*
	 * Duplicate sub-structures as needed.
	 * Increase reference counts on shared objects.
	 * The p_stats and p_sigacts substructs are set in vm_fork.
	 */
	p2->p_flag = 0;
	p2->p_emul = p1->p_emul;
	if (p1->p_flag & P_PROFIL)
		startprofclock(p2);
	atomic_setbits_int(&p2->p_flag, p1->p_flag & (P_SUGID | P_SUGIDEXEC));
	if (flags & FORK_PTRACE)
		atomic_setbits_int(&p2->p_flag, p1->p_flag & P_TRACED);
#ifdef RTHREADS
	if (flags & FORK_THREAD) {
		/* nothing */
	} else
#endif
	{
		p2->p_p->ps_cred = pool_get(&pcred_pool, PR_WAITOK);
		bcopy(p1->p_p->ps_cred, p2->p_p->ps_cred, sizeof(*p2->p_p->ps_cred));
		p2->p_p->ps_cred->p_refcnt = 1;
		crhold(p1->p_ucred);
	}

	TAILQ_INIT(&p2->p_selects);

	/* bump references to the text vnode (for procfs) */
	p2->p_textvp = p1->p_textvp;
	if (p2->p_textvp)
		VREF(p2->p_textvp);

	if (flags & FORK_CLEANFILES)
		p2->p_fd = fdinit(p1);
	else if (flags & FORK_SHAREFILES)
		p2->p_fd = fdshare(p1);
	else
		p2->p_fd = fdcopy(p1);

	/*
	 * If ps_limit is still copy-on-write, bump refcnt,
	 * otherwise get a copy that won't be modified.
	 * (If PL_SHAREMOD is clear, the structure is shared
	 * copy-on-write.)
	 */
#ifdef RTHREADS
	if (flags & FORK_THREAD) {
		/* nothing */
	} else
#endif
	{
		if (p1->p_p->ps_limit->p_lflags & PL_SHAREMOD)
			p2->p_p->ps_limit = limcopy(p1->p_p->ps_limit);
		else {
			p2->p_p->ps_limit = p1->p_p->ps_limit;
			p2->p_p->ps_limit->p_refcnt++;
		}
	}

	if (p1->p_session->s_ttyvp != NULL && p1->p_flag & P_CONTROLT)
		atomic_setbits_int(&p2->p_flag, P_CONTROLT);
	if (flags & FORK_PPWAIT)
		atomic_setbits_int(&p2->p_flag, P_PPWAIT);
	p2->p_pptr = p1;
	if (flags & FORK_NOZOMBIE)
		atomic_setbits_int(&p2->p_flag, P_NOZOMBIE);
	LIST_INIT(&p2->p_children);

#ifdef KTRACE
	/*
	 * Copy traceflag and tracefile if enabled.
	 * If not inherited, these were zeroed above.
	 */
	if (p1->p_traceflag & KTRFAC_INHERIT) {
		p2->p_traceflag = p1->p_traceflag;
		if ((p2->p_tracep = p1->p_tracep) != NULL)
			VREF(p2->p_tracep);
	}
#endif

	/*
	 * set priority of child to be that of parent
	 * XXX should move p_estcpu into the region of struct proc which gets
	 * copied.
	 */
	scheduler_fork_hook(p1, p2);

	/*
	 * Create signal actions for the child process.
	 */
	if (flags & FORK_SIGHAND)
		sigactsshare(p1, p2);
	else
		p2->p_sigacts = sigactsinit(p1);

	/*
	 * If emulation has process fork hook, call it now.
	 */
	if (p2->p_emul->e_proc_fork)
		(*p2->p_emul->e_proc_fork)(p2, p1);

	p2->p_addr = (struct user *)uaddr;

	/*
	 * Finish creating the child process.  It will return through a
	 * different path later.
	 */
	uvm_fork(p1, p2, ((flags & FORK_SHAREVM) ? TRUE : FALSE), stack,
	    stacksize, func ? func : child_return, arg ? arg : p2);

	timeout_set(&p2->p_stats->p_virt_to, virttimer_trampoline, p2);
	timeout_set(&p2->p_stats->p_prof_to, proftimer_trampoline, p2);

	vm = p2->p_vmspace;

	if (flags & FORK_FORK) {
		forkstat.cntfork++;
		forkstat.sizfork += vm->vm_dsize + vm->vm_ssize;
	} else if (flags & FORK_VFORK) {
		forkstat.cntvfork++;
		forkstat.sizvfork += vm->vm_dsize + vm->vm_ssize;
	} else if (flags & FORK_RFORK) {
		forkstat.cntrfork++;
		forkstat.sizrfork += vm->vm_dsize + vm->vm_ssize;
	} else {
		forkstat.cntkthread++;
		forkstat.sizkthread += vm->vm_dsize + vm->vm_ssize;
	}

	/* Find an unused pid satisfying 1 <= lastpid <= PID_MAX */
	do {
		lastpid = 1 + (randompid ? arc4random() : lastpid) % PID_MAX;
	} while (pidtaken(lastpid));
	p2->p_pid = lastpid;

	LIST_INSERT_HEAD(&allproc, p2, p_list);
	LIST_INSERT_HEAD(PIDHASH(p2->p_pid), p2, p_hash);
	LIST_INSERT_HEAD(&p1->p_children, p2, p_sibling);
	LIST_INSERT_AFTER(p1, p2, p_pglist);
	if (p2->p_flag & P_TRACED) {
		p2->p_oppid = p1->p_pid;
		if (p2->p_pptr != p1->p_pptr)
			proc_reparent(p2, p1->p_pptr);

		/*
		 * Set ptrace status.
		 */
		if (flags & FORK_FORK) {
			p2->p_ptstat = malloc(sizeof(*p2->p_ptstat),
			    M_SUBPROC, M_WAITOK);
			p1->p_ptstat->pe_report_event = PTRACE_FORK;
			p2->p_ptstat->pe_report_event = PTRACE_FORK;
			p1->p_ptstat->pe_other_pid = p2->p_pid;
			p2->p_ptstat->pe_other_pid = p1->p_pid;
		}
	}

#if NSYSTRACE > 0
	if (ISSET(p1->p_flag, P_SYSTRACE))
		systrace_fork(p1, p2);
#endif

	/*
	 * Make child runnable, set start time, and add to run queue.
	 */
	SCHED_LOCK(s);
 	getmicrotime(&p2->p_stats->p_start);
	p2->p_acflag = AFORK;
	p2->p_stat = SRUN;
	setrunqueue(p2);
	SCHED_UNLOCK(s);

	/*
	 * Notify any interested parties about the new process.
	 */
	KNOTE(&p1->p_klist, NOTE_FORK | p2->p_pid);

	/*
	 * Update stats now that we know the fork was successfull.
	 */
	uvmexp.forks++;
	if (flags & FORK_PPWAIT)
		uvmexp.forks_ppwait++;
	if (flags & FORK_SHAREVM)
		uvmexp.forks_sharevm++;

	/*
	 * Pass a pointer to the new process to the caller.
	 */
	if (rnewprocp != NULL)
		*rnewprocp = p2;

	/*
	 * Preserve synchronization semantics of vfork.  If waiting for
	 * child to exec or exit, set P_PPWAIT on child, and sleep on our
	 * proc (in case of exit).
	 */
	if (flags & FORK_PPWAIT)
		while (p2->p_flag & P_PPWAIT)
			tsleep(p1, PWAIT, "ppwait", 0);

	/*
	 * If we're tracing the child, alert the parent too.
	 */
	if ((flags & FORK_PTRACE) && (p1->p_flag & P_TRACED))
		psignal(p1, SIGTRAP);

	/*
	 * Return child pid to parent process,
	 * marking us as parent via retval[1].
	 */
	if (retval != NULL) {
		retval[0] = p2->p_pid;
		retval[1] = 0;
	}
	return (0);
}
Example #23
0
int backup_phase2_server(gzFile *cmanfp, const char *phase1data, const char *phase2data, const char *unchangeddata, const char *datadirtmp, struct dpth *dpth, const char *currentdata, const char *working, const char *client, struct cntr *p1cntr, int resume, struct cntr *cntr, struct config *cconf)
{
	int ars=0;
	int ret=0;
	gzFile p1zp=NULL;
	char *deltmppath=NULL;
	char *last_requested=NULL;
	// Where to write phase2data.
	// Data is not getting written to a compressed file.
	// This is important for recovery if the power goes.
	FILE *p2fp=NULL;
	// unchanged data
	FILE *ucfp=NULL;
	int resume_partial=resume;

	struct sbuf cb;		// file list in current manifest
	struct sbuf p1b;	// file list from client

	struct sbuf rb;		// receiving file from client

	init_sbuf(&cb);
	init_sbuf(&p1b);
	init_sbuf(&rb);

	if(!(p1zp=gzopen_file(phase1data, "rb")))
		goto error;

	// Open in read+write mode, so that they can be read through if
	// we need to resume.
	// First, open them in a+ mode, so that they will be created if they
	// do not exist.
	if(!(ucfp=open_file(unchangeddata, "a+b")))
		goto error;
	if(!(p2fp=open_file(phase2data, "a+b")))
		goto error;
	close_fp(&ucfp);
	close_fp(&p2fp);

	if(!(ucfp=open_file(unchangeddata, "r+b")))
		goto error;
	if(!(p2fp=open_file(phase2data, "r+b")))
		goto error;

	if(resume && do_resume(p1zp, p2fp, ucfp, dpth, cconf, client,
		p1cntr, cntr)) goto error;

	logp("Begin phase2 (receive file data)\n");

	if(!(deltmppath=prepend_s(working, "delta.tmp", strlen("delta.tmp"))))
		goto error;

	while(1)
	{
		int sts=0;
	//	logp("in loop, %s %s %c\n",
	//		*cmanfp?"got cmanfp":"no cmanfp",
	//		rb.path?:"no rb.path", rb.path?'X':rb.cmd);
		if(rb.path) write_status(client, STATUS_BACKUP,
			rb.path, p1cntr, cntr);
		else write_status(client, STATUS_BACKUP,
			p1b.path, p1cntr, cntr);
		if((last_requested || !p1zp || writebuflen)
		  && (ars=do_stuff_to_receive(&rb, p2fp, datadirtmp, dpth,
			working, &last_requested, deltmppath, cntr, cconf)))
		{
			if(ars<0) goto error;
			// 1 means ok.
			break;
		}

		if((sts=do_stuff_to_send(&p1b, &last_requested))<0)
			goto error;

		if(!sts && p1zp)
		{
		   free_sbuf(&p1b);

		   if((ars=sbuf_fill_phase1(NULL, p1zp, &p1b, cntr)))
		   {
			if(ars<0) goto error;
			// ars==1 means it ended ok.
			gzclose_fp(&p1zp);
			//logp("ended OK - write phase2end");
			if(async_write_str(CMD_GEN, "backupphase2end"))
				goto error;
		   }

		   //logp("check: %s\n", p1b.path);

		   if(!*cmanfp)
		   {
			// No old manifest, need to ask for a new file.
			//logp("no cmanfp\n");
			if(process_new(&p1b, ucfp, currentdata,
				datadirtmp, deltmppath,
				dpth, &resume_partial,
				cntr, cconf)) goto error;
		   }
		   else
		   {
			// Have an old manifest, look for it there.

			// Might already have it, or be ahead in the old
			// manifest.
			if(cb.path)
			{
				if((ars=maybe_process_file(&cb, &p1b,
					ucfp, currentdata, datadirtmp,
					deltmppath, dpth, &resume_partial,
					cntr, cconf)))
				{
					if(ars<0) goto error;
					// Do not free it - need to send stuff.
					continue;
				}
				//free_sbuf(&p1b);
			}

			while(*cmanfp)
			{
				free_sbuf(&cb);
				if((ars=sbuf_fill(NULL, *cmanfp, &cb, cntr)))
				{
					// ars==1 means it ended ok.
					if(ars<0) goto error;
					gzclose_fp(cmanfp);
		//logp("ran out of current manifest\n");
					if(process_new(&p1b, ucfp,
						currentdata, datadirtmp,
						deltmppath, dpth,
						&resume_partial, cntr, cconf))
							goto error;
					break;
				}
		//logp("against: %s\n", cb.path);
				if((ars=maybe_process_file(&cb, &p1b,
					ucfp, currentdata, datadirtmp,
					deltmppath, dpth, &resume_partial,
					cntr, cconf)))
				{
					if(ars<0) goto error;
					// Do not free it - need to send stuff.
					break;
				}
			}
		   }
		}
	}

	goto end;

error:
	ret=-1;
end:
	if(close_fp(&p2fp))
	{
		logp("error closing %s in backup_phase2_server\n",
			phase2data);
		ret=-1;
	}
	if(close_fp(&ucfp))
	{
		logp("error closing %s in backup_phase2_server\n",
			unchangeddata);
		ret=-1;
	}
	free(deltmppath);
	free_sbuf(&cb);
	free_sbuf(&p1b);
	free_sbuf(&rb);
	gzclose_fp(&p1zp);
	if(!ret) unlink(phase1data);

	logp("End phase2 (receive file data)\n");

	return ret;
}