Пример #1
0
int
main(int argc, char **argv)
{
	gfarm_error_t e;
	int c, use_conn, flags, op = 0;
	const char *filename, *filename2 = NULL;
	char *path;
	struct op_closure closure;
	struct gfm_connection *conn;
	gfarm_error_t (*inode_request_op)(struct gfm_connection *,
		struct gfp_xdr_context *, void *, const char *) = NULL;
	gfarm_error_t (*name_request_op)(struct gfm_connection *,
		struct gfp_xdr_context *, void *,
		const char *, const char *) = NULL;

	if (argc > 0)
		program_name = basename(argv[0]);

	e = gfarm_initialize(&argc, &argv);
	if (e != GFARM_ERR_NO_ERROR) {
		fprintf(stderr, "gfarm_initialize: %s\n",
		    gfarm_error_string(e));
		return (EXIT_ERR);
	}

	while ((c = getopt(argc, argv, "IJNPQRSp")) != -1) {
		switch (c) {
		case OP_INODE_OP:
		case OP_INODE_OP_NF:
		case OP_NAME_OP:
		case OP_NAME2_OP:
		case OP_NAME2_OP_OL:
		case OP_REALPATH:
		case OP_SHOW_SVR:
			if (op != 0) {
				fprintf(stderr,
				    "%s : too many options", program_name);
				usage();
			}
			op = c;
			break;
		case 'p': /* for OP_NAME_OP */
			open_parent = 1;
			break;
		default:
			fprintf(stderr, "%s: unknown option -%c\n",
			    program_name, c);
			usage();
		}
	}
	if (optind == 1)
		usage();
	argc -= optind;
	argv += optind;
	switch (op) {
	case OP_NAME2_OP:
	case OP_NAME2_OP_OL:
		use_conn = 1;
		if (argc != 2)
			usage();
		break;
	case OP_SHOW_SVR:
		if (argc != 0)
			usage();
		break;
	default:
		if (argc != 1)
			usage();
		break;
	}
	filename = argv[0];
	if (argc > 0)
		filename2 = argv[1];
	memset(&closure, 0, sizeof(closure));

	if (use_conn &&
	    (e = gfm_client_connection_and_process_acquire_by_path(
		    "/", &conn)) != GFARM_ERR_NO_ERROR) {
		fprintf(stderr, "%s: %s",
		    program_name, gfarm_error_string(e));
		exit(1);
	}

	switch (op) {
	case OP_INODE_OP:
		if ((e = gfm_inode_op_modifiable(filename,
		    GFARM_FILE_RDONLY,
		    inode_op_request, inode_op_result,
		    inode_op_success, inode_op_cleanup, NULL, &closure))
		    != GFARM_ERR_NO_ERROR) {
			fprintf(stderr, "gfm_inode_op : %s\n",
			    gfarm_error_string(e));
			break;
		}
		assert(closure.request);
		assert(closure.result);
		assert(closure.success);
		assert(closure.cleanup == 0);
		printf("%ld\n", (long)closure.f1.ino);
		break;
	case OP_INODE_OP_NF:
		if ((e = gfm_inode_op_no_follow_modifiable(filename,
		    GFARM_FILE_RDONLY,
		    inode_op_request, inode_op_result,
		    inode_op_success, inode_op_cleanup,
		    NULL, &closure))
		    != GFARM_ERR_NO_ERROR) {
			fprintf(stderr, "gfm_inode_op_no_follow : %s\n",
			    gfarm_error_string(e));
			break;
		}
		assert(closure.request);
		assert(closure.result);
		assert(closure.success);
		assert(closure.cleanup == 0);
		printf("%ld\n", (long)closure.f1.ino);
		break;
	case OP_NAME_OP:
		if ((e = gfm_name_op_modifiable(filename,
		    GFARM_ERR_OPERATION_NOT_PERMITTED,
		    name_op_request, name_op_result,
		    name_op_success, NULL, &closure))
		    != GFARM_ERR_NO_ERROR) {
			fprintf(stderr, "gfm_name_op : %s\n",
			    gfarm_error_string(e));
			break;
		}
		assert(closure.request);
		assert(closure.result);
		assert(closure.success);
		assert(closure.cleanup == 0);
		assert(strlen(closure.f1.name) > 0);
		assert(closure.f1.ino > 0);
		printf("%ld %s\n", (long)closure.f1.ino,
		    closure.f1.name);
		break;
	case OP_NAME2_OP:
	case OP_NAME2_OP_OL:
		if (op == OP_NAME2_OP) {
			flags = 0;
			name_request_op = name2_op_request;
		} else {
			flags = GFARM_FILE_SYMLINK_NO_FOLLOW |
			    GFARM_FILE_OPEN_LAST_COMPONENT;
			closure.is_stat_or_open = 1;
			inode_request_op = name2_op_ol_request;
		}
		if ((e = gfm_name2_op_modifiable(filename, filename2, flags,
		    inode_request_op, name_request_op,
		    name2_op_result, name2_op_success,
		    name2_op_cleanup, NULL, &closure))
		    != GFARM_ERR_NO_ERROR) {
			fprintf(stderr, "gfm_name2_op : %s\n",
			    gfarm_error_string(e));
			break;
		}

		assert(closure.request);
		assert(closure.result);
		assert(closure.success);
		assert(closure.cleanup == 0);
		assert(strlen(closure.f1.name) > 0);
		assert(closure.f1.ino > 0);
		printf("%ld %s %ld %s\n",
		    (long)closure.f1.ino, closure.f1.name,
		    (long)closure.f2.ino, closure.f2.name);
		break;
	case OP_REALPATH:
		if ((e = gfs_realpath(filename, &path))
		    != GFARM_ERR_NO_ERROR) {
			fprintf(stderr, "gfs_realpath : %s\n",
			    gfarm_error_string(e));
			break;
		}
		printf("%s\n", path);
		free(path);
		break;
	case OP_SHOW_SVR:
		printf("%s:%d\n", gfarm_ctxp->metadb_server_name,
		    gfarm_ctxp->metadb_server_port);
		e = GFARM_ERR_NO_ERROR;
		break;
	default:
		assert(0);
	}

	if (e != GFARM_ERR_NO_ERROR) {
		switch (e) {
		case GFARM_ERR_PATH_IS_ROOT:
			return (EXIT_PATH_ROOT);
		case GFARM_ERR_NO_SUCH_FILE_OR_DIRECTORY:
			return (EXIT_NO_SUCH_FILE);
		case GFARM_ERR_CROSS_DEVICE_LINK:
			return (EXIT_CROSS_DEVICE);
		case GFARM_ERR_TOO_MANY_LEVELS_OF_SYMBOLIC_LINK:
			return (EXIT_MANY_LVL_OF_SYMLNK);
		case GFARM_ERR_OPERATION_NOT_PERMITTED:
			return (EXIT_OPE_NOT_PERM);
		default:
			return (EXIT_ERR);
		}
	}
	if ((e = gfarm_terminate()) != GFARM_ERR_NO_ERROR) {
		fprintf(stderr, "gfarm_terminate: %s\n",
		    gfarm_error_string(e));
		return (EXIT_ERR);
	}
	return (EXIT_OK);
}
Пример #2
0
int
main(int argc, char *argv[], char *envp[])
{
	char *e, *gfarm_url, *local_path, **new_env, *cwd_env, *pwd_env;
	int i, j, status, envc, rank = -1, nodes = -1;
	pid_t pid;
	static const char env_node_rank[] = "GFARM_NODE_RANK=";
	static const char env_node_size[] = "GFARM_NODE_SIZE=";
	static const char env_flags[] = "GFARM_FLAGS=";
	static const char env_gfs_pwd[] = "GFS_PWD=";
	static const char env_pwd[] = "PWD=";
	char rankbuf[sizeof(env_node_rank) + GFARM_INT64STRLEN];
	char nodesbuf[sizeof(env_node_size) + GFARM_INT64STRLEN];
	char flagsbuf[sizeof(env_flags) + 3];
	char cwdbuf[PATH_MAX * 2], pwdbuf[PATH_MAX * 2];

	e = gfarm_initialize(&argc, &argv);
	if (e != NULL) {
		errmsg("gfarm_initialize", e);
		exit(1);
	}

	/*
	 * don't use getopt(3) here, because getopt(3) in glibc refers
	 * argv[] passed to main(), instead of argv[] passed to getopt(3).
	 */
	for (i = 1; i < argc; i++) {
		if (argv[i][0] != '-')
			break;
		for (j = 1; argv[i][j] != '\0'; j++) {
			switch (argv[i][j]) {
			case 'I':
				if (argv[i][j + 1] != '\0') {
					rank = strtol(&argv[i][j+1], NULL, 0);
					j += strlen(&argv[i][j + 1]);
				} else if (i + 1 < argc) {
					rank = strtol(argv[++i], NULL, 0);
					j = strlen(argv[i]) - 1;
				} else {
					errmsg("-I", "missing argument");
					print_usage();
				}
				break;
			case 'N':
				if (argv[i][j + 1] != '\0') {
					nodes = strtol(&argv[i][j+1], NULL, 0);
					j += strlen(&argv[i][j + 1]);
				} else if (i + 1 < argc) {
					nodes = strtol(argv[++i], NULL, 0);
					j = strlen(argv[i]) - 1;
				} else {
					errmsg("-N", "missing argument");
					print_usage();
				}
				break;
			case 's':
				rank = 0;
				nodes = 1;
				break;
			case 'h':
			case '?':
				print_usage();
			default:
				fprintf(stderr, "%s: invalid option -- %c\n",
				    progname, argv[i][j]);
				print_usage();
			}
		}
	}
	argc -= i;
	argv += i;
	if (argc == 0)
		print_usage();

	e = gfs_realpath(argv[0], &gfarm_url);
	if (e != NULL) {
		/* XXX check `e' */
		local_path = search_path(argv[0]);
	} else {
		e = gfarm_url_program_get_local_path(gfarm_url, &local_path);
		if (e != NULL) {
			errmsg(gfarm_url, e);
			exit(1);
		}
	}

	e = modify_ld_library_path();
	if (e != NULL) {
		errmsg("modify_ld_library_path", e);
		/* continue */
	}

	/*
	 * the followings are only needed for pid==0 case.
	 * but isn't it better to check errors before fork(2)?
	 *
	 * If gfs_pio_get_node_{rank,size}() fails, continue to
	 * execute as a single process (not parallel processes).
	 */
	if (rank == -1) {
		e = gfs_pio_get_node_rank(&rank);
		if (e != NULL)
			rank = 0;
	}
	if (nodes == -1) {
		e = gfs_pio_get_node_size(&nodes);
		if (e != NULL)
			nodes = 1;
	}
	for (envc = 0; envp[envc] != NULL; envc++)
		;
	new_env = malloc(sizeof(*new_env) * (envc + 5 + 1));
	memcpy(cwdbuf, GFARM_URL_PREFIX, GFARM_URL_PREFIX_LENGTH);
	e = gfs_getcwd(cwdbuf + GFARM_URL_PREFIX_LENGTH,
		sizeof(cwdbuf) - GFARM_URL_PREFIX_LENGTH);
	if (e != NULL) {
		errmsg("cannot get current directory", e);
		exit(1);
	}
	if ((cwd_env = malloc(strlen(cwdbuf) + sizeof(env_gfs_pwd))) == NULL) {
		fprintf(stderr, "%s: no memory for %s%s\n",
		    progname, env_gfs_pwd, cwdbuf);
		exit(1);
	}
	(void)chdir(cwdbuf); /* rely on syscall hook. it is ok if it fails */
	getcwd(pwdbuf, sizeof pwdbuf);
	pwd_env = malloc(strlen(pwdbuf) + sizeof(env_pwd));
	if (pwd_env == NULL) {
		fprintf(stderr, "%s: no memory for %s%s\n",
		    progname, env_pwd, pwdbuf);
		exit(1);
	}
	envc = 0;
	for (i = 0; (e = envp[i]) != NULL; i++) {
		if (memcmp(e, env_node_rank, sizeof(env_node_rank) -1 ) != 0 &&
		    memcmp(e, env_node_size, sizeof(env_node_size) -1 ) != 0 &&
		    memcmp(e, env_flags, sizeof(env_flags) - 1 ) != 0 &&
		    memcmp(e, env_gfs_pwd, sizeof(env_gfs_pwd) - 1) != 0 &&
		    memcmp(e, env_pwd, sizeof(env_pwd) - 1 ) != 0)
			new_env[envc++] = e;
	}
	sprintf(rankbuf, "%s%d", env_node_rank, rank);
	new_env[envc++] = rankbuf;
	sprintf(nodesbuf, "%s%d", env_node_size, nodes);
	new_env[envc++] = nodesbuf;
	sprintf(flagsbuf, "%s%s%s%s", env_flags,
	    gf_profile ? "p" : "",
	    gf_on_demand_replication ? "r" : "",
	    gf_hook_default_global ? "g" : "");
	new_env[envc++] = flagsbuf;
	sprintf(cwd_env, "%s%s", env_gfs_pwd, cwdbuf);
	new_env[envc++] = cwd_env;
	sprintf(pwd_env, "%s%s", env_pwd, pwdbuf);
	new_env[envc++] = pwd_env;
	new_env[envc++] = NULL;

	if (gf_stdout == NULL && gf_stderr == NULL) {
		/* what we need is to call exec(2) */
		pid = 0;
	} else {
		/*
		 * we have to call fork(2) and exec(2), to close
		 * gf_stdout and gf_stderr by calling gfarm_terminate()
		 * after the child program finished.
		 */
		pid = fork();
	}

	switch (pid) {
	case -1:
		perror(PROGRAM_NAME ": fork");
		status = 255;
		break;
	case 0:
		if (gf_stdout == NULL && gf_stderr == NULL) {
			/*
			 * not to display profile statistics
			 * on gfarm_terminate()
			 */
			gfs_profile(gf_profile = 0);

			e = gfarm_terminate();
			if (e != NULL)
				errmsg("(child) gfarm_terminate", e);
		} else {
			/*
			 * otherwise don't call gfarm_terminate(), because:
			 * - it closes gf_stdout and gf_stderr.
			 * - it causes:
			 *   "gfarm_terminate: Can't contact LDAP server"
			 *   on the parent process.
			 */
		}
		execve(local_path, argv, new_env);
		if (errno != ENOEXEC) {
			perror(local_path);
		} else {
			/*
			 * argv[-1] must be available,
			 * because there should be "gfexec" at least.
			 */
			argv[-1] = BOURNE_SHELL;
			argv[0] = local_path;
			execve(BOURNE_SHELL, argv - 1, new_env);
		}
		_exit(255);
	default:
		if (waitpid(pid, &status, 0) == -1) {
			perror(PROGRAM_NAME ": waitpid");
			status = 255;
		} else if (WIFSIGNALED(status)) {
			fprintf(stderr, "%s: signal %d received%s.\n",
			    gfarm_host_get_self_name(), WTERMSIG(status),
			    WCOREDUMP(status) ? " (core dumped)" : "");
			status = 255;
		} else {
			status = WEXITSTATUS(status);
		}
		break;
	}

	/* not to display profile statistics on gfarm_terminate() */
	gfs_profile(gf_profile = 0);

	e = gfarm_terminate();
	if (e != NULL) {
		errmsg("gfarm_terminate", e);
		exit(1);
	}
	exit(status);
}