예제 #1
0
static int update (confuga *C, const char *path, confuga_fid_t fid, confuga_off_t size, int flags)
{
	int rc;
	int fd = -1;
	int n;
	char header[HEADER_LENGTH+1] = "";
	int oflags = O_CREAT|O_WRONLY|O_TRUNC|O_SYNC;

	if (flags & CONFUGA_O_EXCL)
		oflags |= O_EXCL;

	fd = open(path, oflags, S_IRUSR|S_IWUSR);
	CATCHUNIX(fd);
	n = snprintf(header, sizeof(header), "file:" CONFUGA_FID_PRIFMT ":%0*" PRIxCONFUGA_OFF_T "\n", CONFUGA_FID_PRIARGS(fid), (int)sizeof(confuga_off_t)*2, (confuga_off_t)size);
	assert((size_t)n == HEADER_LENGTH);
	rc = full_write(fd, header, HEADER_LENGTH);
	CATCHUNIX(rc);
	if ((size_t)rc < HEADER_LENGTH)
		CATCH(EINVAL); /* FIXME */
	debug(D_DEBUG, "write `%s'", header); /* debug chomps final newline */

	rc = 0;
	goto out;
out:
	close(fd); /* -1 is a NOP */
	return rc;
}
예제 #2
0
CONFUGA_API int confuga_metadata_lookup (confuga *C, const char *path, char **data, size_t *size)
{
	int rc;
	int fd = -1;
	struct stat64 info;
	ssize_t n;
	size_t _size;
	char header[HEADER_LENGTH+1] = "";
	confuga_fid_t fid;
	RESOLVE(path);

	if (size == NULL)
		size = &_size;

	debug(D_CONFUGA, "metadata_lookup(`%s')", unresolved_path);

	fd = open(path, O_RDONLY);
	CATCHUNIX(fd);

	CATCHUNIX(fstat64(fd, &info));
	if (S_ISDIR(info.st_mode))
		CATCH(EISDIR);
	else if (!S_ISREG(info.st_mode))
		CATCH(EINVAL);

	n = read(fd, header, HEADER_LENGTH);
	if (n < (ssize_t)HEADER_LENGTH)
		CATCH(EINVAL);
	debug(D_DEBUG, "read `%s'", header); /* debug chomps final newline */

	const char *current = header;
	if (!(strncmp(current, "meta:", strlen("meta:")) == 0))
		CATCH(EINVAL);
	current += 5;

	/* read hash */
	CATCH(confugaF_extract(C, &fid, current, &current));
	assert(current[0] == ':');
	current += 1;

	/* read size */
	char *endptr;
	*size = strtoull(current, &endptr, 16);
	assert(*endptr == '\n');

	*data = calloc(*size+1, sizeof(char));
	if (*data == NULL)
		CATCH(ENOMEM);
	n = read(fd, *data, *size);
	if (n < (ssize_t)*size)
		CATCH(EINVAL);
	debug(D_DEBUG, "read `%s'", *data); /* debug chomps final newline */

	rc = 0;
	goto out;
out:
	debug(D_CONFUGA, "= %d (%s)", rc, strerror(rc));
	close(fd); /* -1 is a NOP */
	return rc;
}
예제 #3
0
CONFUGA_API int confuga_metadata_update (confuga *C, const char *path, const char *data, size_t size)
{
	static const confuga_fid_t fid = {""};

	int rc;
	int fd = -1;
	int n;
	char header[HEADER_LENGTH+1] = "";
	RESOLVE(path);

	debug(D_CONFUGA, "metadata_update(`%s')", unresolved_path);

	fd = open(path, O_CREAT|O_WRONLY|O_TRUNC|O_SYNC, S_IRUSR|S_IWUSR);
	CATCHUNIX(fd);
	n = snprintf(header, sizeof(header), "meta:" CONFUGA_FID_PRIFMT ":%0*" PRIxCONFUGA_OFF_T "\n", CONFUGA_FID_PRIARGS(fid), (int)sizeof(confuga_off_t)*2, (confuga_off_t)size);
	assert((size_t)n == HEADER_LENGTH);
	rc = full_write(fd, header, HEADER_LENGTH);
	CATCHUNIX(rc);
	if ((size_t)rc < HEADER_LENGTH)
		CATCH(EINVAL); /* FIXME */
	debug(D_DEBUG, "write `%s'", header); /* debug chomps final newline */

	rc = full_write(fd, data, size);
	CATCHUNIX(rc);
	if ((size_t)rc < size)
		CATCH(EINVAL); /* FIXME */
	debug(D_DEBUG, "write `%s'", data); /* debug chomps final newline */

	rc = 0;
	goto out;
out:
	debug(D_CONFUGA, "= %d (%s)", rc, strerror(rc));
	close(fd); /* -1 is a NOP */
	return rc;
}
예제 #4
0
static int lookup (confuga *C, const char *path, confuga_fid_t *fid, confuga_off_t *size, enum CONFUGA_FILE_TYPE *type)
{
	int rc;
	int fd = -1;
	ssize_t n;
	char header[HEADER_LENGTH+1] = "";
	struct stat64 info;

	fd = open(path, O_RDONLY);
	CATCHUNIX(fd);

	CATCHUNIX(fstat64(fd, &info));
	if (S_ISDIR(info.st_mode))
		CATCH(EISDIR);
	else if (!S_ISREG(info.st_mode))
		CATCH(EINVAL);

	n = full_read(fd, header, HEADER_LENGTH);
	if (n < (ssize_t)HEADER_LENGTH)
		CATCH(EINVAL);
	debug(D_DEBUG, "read `%s'", header); /* debug chomps final newline */

	const char *current = header;
	if (strncmp(current, "file:", strlen("file:")) == 0)
		*type = CONFUGA_FILE;
	else if (strncmp(current, "meta:", strlen("meta:")) == 0)
		*type = CONFUGA_FILE;
	else
		CATCH(EINVAL);
	current += 5;

	/* read hash */
	int i;
	for (i = 0; i < (int)sizeof(fid->id); i += 1, current += 2) {
		char byte[3] = {current[0], current[1], '\0'};
		unsigned long value = strtoul(byte, NULL, 16);
		fid->id[i] = value;
	}
	assert(current[0] == ':');
	current += 1;

	/* read size */
	if (size) {
		char *endptr;
		*size = strtoull(current, &endptr, 16);
		assert(*endptr == '\n');
	}

	rc = 0;
	goto out;
out:
	close(fd);
	return rc;
}
예제 #5
0
static int sn_ticket (confuga *C, const struct confuga_host *host)
{
	static const char SQL[] =
		"UPDATE Confuga.StorageNode"
		"	SET ticket = ?2"
		"	WHERE hostport = ?1;"
		;

	int rc;
	sqlite3 *db = C->db;
	sqlite3_stmt *stmt = NULL;
	const char *current = SQL;
	time_t stoptime = STOPTIME_SHORT;

	char ticket[PATH_MAX];
	char path[CHIRP_PATH_MAX];
	struct stat info;
	FILE *stream = NULL;

	CATCHUNIX(snprintf(ticket, sizeof(ticket), "%s/ticket", C->root));
	CATCHUNIX(chirp_reli_ticket_register(host->hostport, ticket, "self", TICKET_DURATION, stoptime));

	/* The list permission is necessary because chirp_fs_local_scheduler.c:geturl does a stat. */
	CATCHUNIX(snprintf(path, sizeof(path), "%s/file", host->root));
	CATCHUNIX(chirp_reli_ticket_modify(host->hostport, ticket, path, "lr", stoptime));

	/* Add write permission because a putfile may need retried. */
	CATCHUNIX(snprintf(path, sizeof(path), "%s/open", host->root));
	CATCHUNIX(chirp_reli_ticket_modify(host->hostport, ticket, path, "pw", stoptime));

	CATCHUNIX(snprintf(path, sizeof(path), "%s/ticket", host->root));
	stream = fopen(ticket, "r");
	CATCHUNIX(stream ? 0 : -1);
	CATCHUNIX(fstat(fileno(stream), &info));
	CATCHUNIX(chirp_reli_putfile(host->hostport, path, stream, S_IRUSR, info.st_size, stoptime));

	sqlcatch(sqlite3_prepare_v2(db, current, -1, &stmt, &current));
	sqlcatch(sqlite3_bind_text(stmt, 1, host->hostport, -1, SQLITE_STATIC));
	sqlcatch(sqlite3_bind_blob(stmt, 2, C->ticket, sizeof(C->ticket), SQLITE_STATIC));
	sqlcatchcode(sqlite3_step(stmt), SQLITE_DONE);
	sqlcatch(sqlite3_finalize(stmt); stmt = NULL);

	rc = 0;
	goto out;
out:
	if (stream)
		fclose(stream);
	sqlite3_finalize(stmt);
	return rc;
}
static int sandbox_create (char sandbox[PATH_MAX], chirp_jobid_t id)
{
	int rc;
	char path[PATH_MAX] = "";

	CATCHUNIX(snprintf(path, PATH_MAX, "/.__job.%" PRICHIRP_JOBID_T ".XXXXXX", id));
	if (rc >= PATH_MAX)
		CATCH(ENAMETOOLONG);
	CATCHUNIX(chirp_fs_local_resolve(path, sandbox));
	CATCHUNIX(mkdtemp(sandbox) ? 0 : -1);
	debug(D_DEBUG, "created new sandbox `%s'", sandbox);

	rc = 0;
	goto out;
out:
	return rc;
}
예제 #7
0
CONFUGA_API int confuga_closedir(confuga_dir *dir)
{
	int rc;
	DIR *ldir = dir->dir;
	debug(D_CONFUGA, "closedir(`%s')", dir->path);
	free(dir);
	CATCHUNIX(closedir(ldir));
	PROLOGUE
}
예제 #8
0
int chirp_sqlite3_row_jsonify(sqlite3_stmt *stmt, buffer_t *B)
{
	int rc;
	int i, first;

	CATCHUNIX(buffer_putliteral(B, "{"));
	for (i = 0, first = 1; i < sqlite3_column_count(stmt); i++, first = 0) {
		if (!first)
			CATCHUNIX(buffer_putliteral(B, ","));
		CATCHUNIX(buffer_putfstring(B, "\"%s\":", sqlite3_column_name(stmt, i)));
		chirp_sqlite3_column_jsonify(stmt, i, B);
	}
	CATCHUNIX(buffer_putliteral(B, "}"));

	rc = 0;
	goto out;
out:
	return rc;
}
static int sandbox_delete (const char *sandbox)
{
	int rc;

	CATCHUNIX(unlink_recursive(sandbox));

	rc = 0;
	goto out;
out:
	return rc;
}
static int kill_kindly (pid_t pid)
{
	int rc;

	/* N.B. There is no point in waiting for `pid' because one of its children
	 * may be ignoring the kinder termination signals. We have to go through
	 * the whole thing. However, if we get ESRCH (or any other error), this is
	 * indication no process matches the group -pid. */
	CATCHUNIX(kill(-pid, SIGTERM));
	usleep(50);
	CATCHUNIX(kill(-pid, SIGQUIT));
	usleep(50);
	CATCHUNIX(kill(-pid, SIGKILL));
	usleep(50);

	rc = 0;
	goto out;
out:
	return rc;
}
예제 #11
0
int chirp_sqlite3_column_jsonify(sqlite3_stmt *stmt, int n, buffer_t *B)
{
	int rc;

	switch (sqlite3_column_type(stmt, n)) {
		case SQLITE_NULL:
			CATCHUNIX(buffer_putliteral(B, "null"));
			break;
		case SQLITE_INTEGER:
			CATCHUNIX(buffer_putfstring(B, "%" PRId64, (int64_t) sqlite3_column_int64(stmt, n)));
			break;
		case SQLITE_FLOAT:
			CATCHUNIX(buffer_putfstring(B, "%.*e", DBL_DIG, sqlite3_column_double(stmt, n)));
			break;
		case SQLITE_TEXT:
			CATCHUNIX(buffer_putliteral(B, "\""));
			CATCHUNIX(jsonA_escapestring(B, (const char *)sqlite3_column_text(stmt, n)));
			CATCHUNIX(buffer_putliteral(B, "\""));
			break;
		default:
			abort();
	}

	rc = 0;
	goto out;
out:
	return rc;
}
예제 #12
0
static INT64_T chirp_fs_confuga_open (const char *path, INT64_T flags, INT64_T mode)
{
	int rc;
	char *data = NULL;
	int fd = getfd();

	strncpy(open_files[fd].path, path, sizeof(open_files[fd].path)-1);
	switch (flags & O_ACCMODE) {
		case O_RDONLY:
			if (strncmp(path_basename(path), ".__", 3) == 0) {
				size_t len;
				buffer_init(&open_files[fd].f.metadata);
				CATCH(confuga_metadata_lookup(C, path, &data, &len));
				CATCHUNIX(buffer_putlstring(&open_files[fd].f.metadata, data, len));
				open_files[fd].type = CHIRP_FS_CONFUGA_META_READ;
			} else {
				confuga_fid_t fid;
				CATCH_CONFUGA(confuga_lookup(C, path, &fid, NULL));
				CATCH_CONFUGA(confuga_replica_open(C, fid, &open_files[fd].f.replica, STOPTIME));
				open_files[fd].type = CHIRP_FS_CONFUGA_REPL_READ;
			}
			break;
		case O_WRONLY:
			if (strncmp(path_basename(path), ".__", 3) == 0) {
				buffer_init(&open_files[fd].f.metadata);
				open_files[fd].type = CHIRP_FS_CONFUGA_META_WRITE;
			} else {
				CATCH_CONFUGA(confuga_file_create(C, &open_files[fd].f.file.file, STOPTIME));
				open_files[fd].f.file.size = 0;
				open_files[fd].f.file.flags = 0;
				if (flags & O_EXCL)
					open_files[fd].f.file.flags |= CONFUGA_O_EXCL;
				open_files[fd].type = CHIRP_FS_CONFUGA_FILE_WRITE;
			}
			break;
		case O_RDWR:
			CATCH(EINVAL);
		default:
			assert(0);
	}

	rc = 0;
	goto out;
out:
	free(data);
	if (rc)
		return (errno = rc, -1);
	else
		return fd; /* N.B. return fd on success */

}
예제 #13
0
static int resolve (confuga *C, const char *path, char resolved[CONFUGA_PATH_MAX])
{
	int rc;
	char collapse[CONFUGA_PATH_MAX];
	char absolute[CONFUGA_PATH_MAX];
	path_collapse(path, collapse, 1);
	CATCHUNIX(snprintf(absolute, sizeof(absolute), "%s/root/%s", C->root, collapse));
	if ((size_t)rc >= CONFUGA_PATH_MAX)
		CATCH(ENAMETOOLONG);
	path_collapse(absolute, resolved, 1);

	rc = 0;
	goto out;
out:
	return rc;
}
예제 #14
0
static int do_stat (confuga *C, const char *path, struct confuga_stat *info, int (*statf) (const char *, struct stat64 *))
{
	int rc;
	struct stat64 linfo;
	enum CONFUGA_FILE_TYPE type;
	RESOLVE(path)
	CATCHUNIX(statf(path, &linfo));
	if (S_ISREG(linfo.st_mode)) {
		CATCH(lookup(C, path, &info->fid, &info->size, &type));
	} else {
		info->size = linfo.st_size;
	}
	info->ino = linfo.st_ino;
	info->mode = linfo.st_mode;
	info->uid = linfo.st_uid;
	info->gid = linfo.st_gid;
	info->nlink = linfo.st_nlink;
	info->atime = linfo.st_atime;
	info->mtime = linfo.st_mtime;
	info->ctime = linfo.st_ctime;
	PROLOGUE
}
예제 #15
0
static INT64_T chirp_fs_confuga_pwrite(int fd, const void *buffer, INT64_T length, INT64_T offset)
{
	int rc;
	size_t n;
	SETUP_FILE

	if (length < 0 || offset < 0)
		CATCH(EINVAL);

	switch (open_files[fd].type) {
		case CHIRP_FS_CONFUGA_FILE_WRITE: {
			if ((confuga_off_t)offset != open_files[fd].f.file.size)
				CATCH(EINVAL); /* do not allow random writes */
			CATCH_CONFUGA(confuga_file_write(open_files[fd].f.file.file, buffer, length, &n, STOPTIME));
			open_files[fd].f.file.size += n;
			break;
		}
		case CHIRP_FS_CONFUGA_META_WRITE:
			if ((size_t)offset != buffer_pos(&open_files[fd].f.metadata))
				CATCH(EINVAL); /* do not allow random writes */
			CATCHUNIX(buffer_putlstring(&open_files[fd].f.metadata, buffer, length));
			n = length;
			break;
		default:
			CATCH(EBADF);
	}

	rc = 0;
	goto out;
out:
	if (rc) {
		return (errno = rc, -1);
	} else {
		return n; /* N.B. return n on success */
	}
}
예제 #16
0
파일: shell.c 프로젝트: Baguage/cctools
static int execute (const char *cmd, const char * const env[], int in[2], int out[2], int err[2])
{
	int rc;
	int i;

	CATCHUNIX(close(in[1]));
	CATCHUNIX(close(out[0]));
	CATCHUNIX(close(err[0]));

	CATCHUNIX(dup2(in[0], STDIN_FILENO));
	CATCHUNIX(dup2(out[1], STDOUT_FILENO));
	CATCHUNIX(dup2(err[1], STDERR_FILENO));

	CATCHUNIX(close(in[0]));
	CATCHUNIX(close(out[1]));
	CATCHUNIX(close(err[1]));

	for(i = 0; env[i]; i++) {
		CATCHUNIX(putenv((char *)env[i]));
	}

	CATCHUNIX(execlp("sh", "sh", "-c", cmd, NULL));

	rc = 0;
	goto out;
out:
	fatal("shellcode execute failure: %s", strerror(errno));
	abort();
}
예제 #17
0
파일: intsort.c 프로젝트: Baguage/cctools
int main (int argc, char *argv[])
{
  int rc;

  (void)testmergesort;

  if (strcmp(argv[1], "assert") == 0) {
	int fd;
	struct stat buf;
	size_t n;
	uint64_t i1, i2;

	CATCHUNIX(fd = open(argv[2], O_RDONLY));
	CATCHUNIX(fstat(fd, &buf));
	assert(buf.st_size % sizeof(uint64_t) == 0);
	FILE *input = fdopen(fd, "r");
	CATCHUNIX(input == NULL ? -1 : 0);
	CATCHUNIX(setvbuf(input, malloc(1LL<<20), _IOFBF, (1LL<<20)));

	i1 = 0;
	while (fread(&i2, sizeof(i2), 1, input) > 0) {
		if (i2 < i1) {
			fprintf(stdout, "for bytes %zu:%zu: not sorted!\n", n, n+1);
			exit(EXIT_FAILURE);
		}
		i1 = i2;
		n += 1;
	}
	assert(feof(input));
	fprintf(stdout, "sorted!\n");
  } else if (strcmp(argv[1], "isort") == 0) {
	int fd;
	struct stat buf;

	/* sort isort <output> <input> */

	CATCHUNIX(fd = open(argv[3], O_RDONLY));
	CATCHUNIX(fstat(fd, &buf));
	void *input = mmap(NULL, (size_t)buf.st_size, PROT_READ, MAP_SHARED, fd, 0);
	CATCHUNIX(input == MAP_FAILED ? -1 : 0);
	CATCHUNIX(close(fd));

	CATCHUNIX(fd = open(argv[2], O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR));
	CATCHUNIX(ftruncate(fd, buf.st_size));
	void *output = mmap(NULL, (size_t)buf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
	CATCHUNIX(output == MAP_FAILED ? -1 : 0);
	CATCHUNIX(close(fd));

	memcpy(output, input, (size_t)buf.st_size);

	qsort(output, buf.st_size/sizeof(uint64_t), sizeof(uint64_t), compare);
  } else if (strcmp(argv[1], "split") == 0) {
	int fd;
	struct stat buf;
	size_t count;

	/* sort split <input> <output1> <output2> */

	CATCHUNIX(fd = open(argv[2], O_RDONLY));
	CATCHUNIX(fstat(fd, &buf));
	assert(buf.st_size % sizeof(uint64_t) == 0);
	assert(buf.st_size/2 % sizeof(uint64_t) == 0);
	FILE *input = fdopen(fd, "r");
	CATCHUNIX(input == NULL ? -1 : 0);
	CATCHUNIX(setvbuf(input, malloc(1LL<<20), _IOFBF, (1LL<<20)));

	FILE *output1 = fopen(argv[3], "w");
	CATCHUNIX(output1 == NULL ? -1 : 0);
	CATCHUNIX(setvbuf(output1, malloc(1LL<<20), _IOFBF, (1LL<<20)));
	for (count = 0; count < buf.st_size/sizeof(uint64_t)/2; count++) {
		uint64_t i;
		size_t n;
		n = fread(&i, sizeof(i), 1, input);
		CATCHUNIX(n == 0 && (errno = ferror(input)) ? -1 : 0);
		assert(n == 1);
		n = fwrite(&i, sizeof(i), 1, output1);
		CATCHUNIX(n == 0 && (errno = ferror(output1)) ? -1 : 0);
	}
	fclose(output1);

	FILE *output2 = fopen(argv[4], "w");
	CATCHUNIX(output2 == NULL ? -1 : 0);
	CATCHUNIX(setvbuf(output2, malloc(1LL<<20), _IOFBF, (1LL<<20)));
	for (count = 0; count < buf.st_size/sizeof(uint64_t)/2; count++) {
		uint64_t i;
		size_t n;
		n = fread(&i, sizeof(i), 1, input);
		CATCHUNIX(n == 0 && (errno = ferror(input)) ? -1 : 0);
		assert(n == 1);
		n = fwrite(&i, sizeof(i), 1, output2);
		CATCHUNIX(n == 0 && (errno = ferror(output2)) ? -1 : 0);
	}
	fclose(output2);

	fclose(input);
  } else if (strcmp(argv[1], "merge") == 0) {
	int fd;
	struct stat buf1, buf2;

	/* sort merge <output> <input1> <input2> */

	CATCHUNIX(fd = open(argv[3], O_RDONLY));
	CATCHUNIX(fstat(fd, &buf1));
	assert(buf1.st_size % sizeof(uint64_t) == 0);
	FILE *input1 = fdopen(fd, "r");
	CATCHUNIX(input1 == NULL ? -1 : 0);
	CATCHUNIX(setvbuf(input1, malloc(1LL<<20), _IOFBF, (1LL<<20)));

	CATCHUNIX(fd = open(argv[4], O_RDONLY));
	CATCHUNIX(fstat(fd, &buf2));
	assert(buf2.st_size % sizeof(uint64_t) == 0);
	FILE *input2 = fdopen(fd, "r");
	CATCHUNIX(input2 == NULL ? -1 : 0);
	CATCHUNIX(setvbuf(input2, malloc(1LL<<20), _IOFBF, (1LL<<20)));

	CATCHUNIX(fd = open(argv[2], O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR));
	assert((buf1.st_size+buf2.st_size) % sizeof(uint64_t) == 0);
	FILE *output = fdopen(fd, "w");
	CATCHUNIX(output == NULL ? -1 : 0);
	CATCHUNIX(setvbuf(output, malloc(1LL<<20), _IOFBF, (1LL<<20)));

	{
		uint64_t i1, i2;
		size_t n;
		n = fread(&i1, sizeof(i1), 1, input1);
		CATCHUNIX(n == 0 && (errno = ferror(input1)) ? -1 : 0);
		n = fread(&i2, sizeof(i2), 1, input2);
		CATCHUNIX(n == 0 && (errno = ferror(input2)) ? -1 : 0);
		while (1) {
			if (i1 <= i2) {
				n = fwrite(&i1, sizeof(i1), 1, output);
				CATCHUNIX(n == 0 && (errno = ferror(output)) ? -1 : 0);
				n = fread(&i1, sizeof(i1), 1, input1);
				CATCHUNIX(n == 0 && (errno = ferror(input1)) ? -1 : 0);
				if (n == 0) {
					while (1) {
						n = fread(&i2, sizeof(i2), 1, input2);
						CATCHUNIX(n == 0 && (errno = ferror(input2)) ? -1 : 0);
						if (n == 1) {
							n = fwrite(&i2, sizeof(i2), 1, output);
							CATCHUNIX(n == 0 && (errno = ferror(output)) ? -1 : 0);
						} else {
							break;
						}
					}
					break;
				}
			} else {
				n = fwrite(&i2, sizeof(i2), 1, output);
				CATCHUNIX(n == 0 && (errno = ferror(output)) ? -1 : 0);
				n = fread(&i2, sizeof(i2), 1, input2);
				CATCHUNIX(n == 0 && (errno = ferror(input2)) ? -1 : 0);
				if (n == 0) {
					while (1) {
						n = fread(&i1, sizeof(i1), 1, input1);
						CATCHUNIX(n == 0 && (errno = ferror(input1)) ? -1 : 0);
						if (n == 1) {
							n = fwrite(&i1, sizeof(i1), 1, output);
							CATCHUNIX(n == 0 && (errno = ferror(output)) ? -1 : 0);
						} else {
							break;
						}
					}
					break;
				}
			}
		}
		assert(feof(input1) && feof(input2));
		fclose(input1);
		fclose(input2);
		fclose(output);
	}
  } else {
	exit(EXIT_FAILURE);
  }

  return 0;
}
static int interpolate (chirp_jobid_t id, char task_path[CHIRP_PATH_MAX], char serv_path[CHIRP_PATH_MAX])
{
	int rc;
	char *mark;

	for (mark = serv_path; (mark = strchr(mark, '%')); ) {
		switch (mark[1]) {
			case 'g':
			case 'h':
			case 's':
			{
				/* replace with hash of task_path */
				unsigned char digest[SHA1_DIGEST_LENGTH];
				if (mark[1] == 'h')
					CATCHUNIX(sha1_file(task_path, digest) ? 0 : -1);
				else if (mark[1] == 'g')
					sqlite3_randomness(SHA1_DIGEST_LENGTH, digest);
				else if (mark[1] == 's') {
					struct stat64 buf;
					CATCHUNIX(stat64(task_path, &buf));
					if (buf.st_size <= MAX_SIZE_HASH) {
						CATCHUNIX(sha1_file(task_path, digest) ? 0 : -1);
					} else {
						sqlite3_randomness(SHA1_DIGEST_LENGTH, digest);
					}
				}

				if (strlen(serv_path)+sizeof(digest)*2 < CHIRP_PATH_MAX) {
					size_t i;
					memmove(mark+sizeof(digest)*2, mark+2, strlen(mark+2)+1);
					for (i = 0; i < sizeof(digest); i++) {
						char hex[3];
						CATCHUNIX(snprintf(hex, sizeof(hex), "%02X", (unsigned int)digest[i]));
						assert(rc == 2);
						mark[i*2] = hex[0];
						mark[i*2+1] = hex[1];
					}
					mark += sizeof(digest)*2;
				} else {
					CATCH(ENAMETOOLONG);
				}
				break;
			}
			case 'j':
			{
				char str[64];
				CATCHUNIX(snprintf(str, sizeof(str), "%" PRICHIRP_JOBID_T, id));
				assert((size_t)rc < sizeof(str));
				if (strlen(serv_path)+strlen(str) < CHIRP_PATH_MAX) {
					memmove(mark+strlen(str), mark+2, strlen(mark+2)+1);
					memcpy(mark, str, strlen(str));
					mark += strlen(str);
				} else {
					CATCH(ENAMETOOLONG);
				}
				break;
			}
			default:
				mark += 1; /* ignore */
				break;
		}
	}

	rc = 0;
	goto out;
out:
	return rc;
}
static int bindfile (sqlite3 *db, chirp_jobid_t id, const char *subject, const char *sandbox, struct url_binding **urlsp, const char *task_path, const char *serv_path, const char *binding, const char *type, enum BINDSTATE mode)
{
	static const char SQL[] =
		"UPDATE JobFile"
		"	SET serv_path = ?, size = ?"
		"	WHERE id = ? AND task_path = ? AND type = 'OUTPUT'";

	int rc;
	sqlite3_stmt *stmt = NULL;
	const char *current = SQL;

	char task_path_resolved[CHIRP_PATH_MAX] = "";
	char serv_path_interpolated[CHIRP_PATH_MAX] = "";
	char serv_path_resolved[CHIRP_PATH_MAX] = "";
	char task_path_dir[CHIRP_PATH_MAX] = ""; /* directory containing task_path_resolved */

	CATCHUNIX(snprintf(task_path_resolved, sizeof(task_path_resolved), "%s/%s", sandbox, task_path));
	if ((size_t)rc >= sizeof(task_path_resolved))
		CATCH(ENAMETOOLONG);
	path_dirname(task_path_resolved, task_path_dir);

	if (strcmp(binding, "URL") == 0) {
		if (strcmp(type, "INPUT") != 0)
			CATCH(EINVAL);
		if (mode == BOOTSTRAP) {
			debug(D_DEBUG, "binding `%s' for future URL fetch `%s'", task_path, serv_path);
			CATCHUNIX(create_dir(task_path_dir, S_IRWXU) ? 0 : -1);
			struct url_binding *url = malloc(sizeof(struct url_binding));
			CATCHUNIX(url ? 0 : -1);
			memset(url, 0, sizeof(struct url_binding));
			strncpy(url->path, "", sizeof(url->path));
			url->url = NULL;
			url->next = *urlsp;
			*urlsp = url;
			CATCHUNIX(snprintf(url->path, sizeof(url->path), "%s", task_path));
			CATCHUNIX((url->url = strdup(serv_path)) ? 0 : -1);
		}
		rc = 0;
		goto out;
	}

	strncpy(serv_path_interpolated, serv_path, sizeof(serv_path_interpolated)-1);
	if (mode == STRAPBOOT && strcmp(type, "OUTPUT") == 0)
		CATCH(interpolate(id, task_path_resolved, serv_path_interpolated));
	serv_path = serv_path_interpolated;
	CATCH(chirp_fs_local_resolve(serv_path, serv_path_resolved));

	if (mode == BOOTSTRAP) {
		debug(D_DEBUG, "binding `%s' as `%s'", task_path, serv_path);

		CATCHUNIX(create_dir(task_path_dir, S_IRWXU) ? 0 : -1);

		if (strcmp(type, "INPUT") == 0) {
			if (strcmp(binding, "LINK") == 0) {
				CATCHUNIX(link(serv_path_resolved, task_path_resolved));
			} else if (strcmp(binding, "COPY") == 0) {
				CATCHUNIX(copy_file_to_file(serv_path_resolved, task_path_resolved));
			} else assert(0);
			CATCHUNIX(chmod(serv_path_resolved, S_IRWXU));
		}
	} else if (mode == STRAPBOOT) {
		if (strcmp(type, "OUTPUT") == 0) {
			struct stat info;

			debug(D_DEBUG, "binding output file `%s' as `%s'", task_path, serv_path);
			if (strcmp(binding, "LINK") == 0) {
				CATCHUNIXIGNORE(unlink(serv_path_resolved), ENOENT); /* ignore error/success */
				CATCHUNIX(link(task_path_resolved, serv_path_resolved));
			} else if (strcmp(binding, "COPY") == 0) {
				CATCHUNIXIGNORE(unlink(serv_path_resolved), ENOENT);
				CATCHUNIX(copy_file_to_file(task_path_resolved, serv_path_resolved));
			}

			if (stat(serv_path_resolved, &info) == 0) {
				sqlcatch(sqlite3_prepare_v2(db, current, -1, &stmt, &current));
				sqlcatch(sqlite3_bind_text(stmt, 1, serv_path, -1, SQLITE_STATIC));
				sqlcatch(sqlite3_bind_int64(stmt, 2, info.st_size));
				sqlcatch(sqlite3_bind_int64(stmt, 3, (sqlite3_int64)id));
				sqlcatch(sqlite3_bind_text(stmt, 4, task_path, -1, SQLITE_STATIC));
				sqlcatchcode(sqlite3_step(stmt), SQLITE_DONE);
				sqlcatch(sqlite3_finalize(stmt); stmt = NULL);
			}
		}
	} else assert(0);
예제 #20
0
파일: shell.c 프로젝트: Baguage/cctools
int shellcode(const char *cmd, const char * const env[], const char *input, size_t len, buffer_t *Bout, buffer_t *Berr, int *status)
{
	int rc;
	int in[2] = {-1, -1};
	int out[2] = {-1, -1};
	int err[2] = {-1, -1};
	pid_t child = 0;
	const char * const _env[] = {NULL};
	struct timeval start, stop;

	gettimeofday(&start, NULL);

	if (env == NULL)
		env = _env;

	CATCHUNIX(pipe(in));
	CATCHUNIX(pipe(out));
	CATCHUNIX(pipe(err));

	CATCHUNIX(child = fork());

	if(child == 0) {
		return execute(cmd, env, in, out, err);
	}

	CATCHUNIX(close(in[0]));
	in[0] = -1;
	CATCHUNIX(close(out[1]));
	out[1] = -1;
	CATCHUNIX(close(err[1]));
	err[1] = -1;

	CATCHUNIX(fcntl(in[1], F_GETFL));
	CATCHUNIX(fcntl(in[1], F_SETFL, rc|O_NONBLOCK));

	CATCHUNIX(fcntl(out[0], F_GETFL));
	CATCHUNIX(fcntl(out[0], F_SETFL, rc|O_NONBLOCK));

	CATCHUNIX(fcntl(err[0], F_GETFL));
	CATCHUNIX(fcntl(err[0], F_SETFL, rc|O_NONBLOCK));

	while (1) {
		char b[1<<16];
		pid_t w;
		ssize_t result;

		CATCHUNIX(w = waitpid(child, status, WNOHANG));

		if (len) {
			result = write(in[1], input, len);
			if (result == -1 && errno != EAGAIN && errno != EINTR) {
				CATCH(errno);
			} else if (result > 0) {
				input += result;
				len -= (size_t)result;
			}
		} else if (in[1] >= 0) {
			close(in[1]);
			in[1] = -1;
		}

		result = read(out[0], b, sizeof(b));
		if (result == -1 && errno != EAGAIN && errno != EINTR) {
			CATCH(errno);
		} else if (result > 0 && Bout) {
			buffer_putlstring(Bout, b, (size_t)result);
		}

		result = read(err[0], b, sizeof(b));
		if (result == -1 && errno != EAGAIN && errno != EINTR) {
			CATCH(errno);
		} else if (result > 0 && Berr) {
			buffer_putlstring(Berr, b, (size_t)result);
		}

		if (w == child)
			break;
	}
	child = 0;

	rc = 0;
	goto out;
out:
	if (child > 0) {
		kill(child, SIGKILL);
		waitpid(child, NULL, 0);
	}
	if (in[0] >= 0) close(in[0]);
	if (in[1] >= 0) close(in[1]);
	if (out[0] >= 0) close(out[0]);
	if (out[1] >= 0) close(out[1]);
	if (err[0] >= 0) close(err[0]);
	if (err[1] >= 0) close(err[1]);
	gettimeofday(&stop, NULL);
	debug(D_DEBUG, "shellcode finished in %.2fs", (double)(stop.tv_sec-start.tv_sec) + (stop.tv_usec-start.tv_usec)*1e-6);
	return RCUNIX(rc);
}