int join_namespace_by_fd(int dirfd, char *typestr) {
	int type;
	if (strcmp(typestr, "net") == 0)
		type = CLONE_NEWNET;
	else if (strcmp(typestr, "mnt") == 0)
		type = CLONE_NEWNS;
	else if (strcmp(typestr, "ipc") == 0)
		type = CLONE_NEWIPC;
	else if (strcmp(typestr, "pid") == 0)
		type = CLONE_NEWPID;
	else if (strcmp(typestr, "uts") == 0)
		type = CLONE_NEWUTS;
	else if (strcmp(typestr, "user") == 0)
		type = CLONE_NEWUSER;
	else
		assert(0);

	char *path;
	if (asprintf(&path, "ns/%s", typestr) == -1)
		errExit("asprintf");

	int fd = openat(dirfd, path, O_RDONLY|O_CLOEXEC);
	free(path);
	if (fd < 0)
		goto errout;

	// require that target namespace is owned by
	// the current user namespace (Linux >= 4.9)
	struct stat self_userns;
	if (stat("/proc/self/ns/user", &self_userns) == 0) {
		int usernsfd = ioctl(fd, NS_GET_USERNS);
		if (usernsfd != -1) {
			struct stat dest_userns;
			if (fstat(usernsfd, &dest_userns) < 0)
				errExit("fstat");
			close(usernsfd);
			if (dest_userns.st_ino != self_userns.st_ino ||
			    dest_userns.st_dev != self_userns.st_dev) {
				close(fd);
				goto errout;
			}
		}
	}

	if (syscall(__NR_setns, fd, type) < 0) {
		close(fd);
		goto errout;
	}

	close(fd);
	return 0;

errout:
	fprintf(stderr, "Error: cannot join namespace %s\n", typestr);
	return -1;
}
int join_namespace_by_fd(int dirfd, char *typestr) {
	int type;
	if (strcmp(typestr, "net") == 0)
		type = CLONE_NEWNET;
	else if (strcmp(typestr, "mnt") == 0)
		type = CLONE_NEWNS;
	else if (strcmp(typestr, "ipc") == 0)
		type = CLONE_NEWIPC;
	else if (strcmp(typestr, "pid") == 0)
		type = CLONE_NEWPID;
	else if (strcmp(typestr, "uts") == 0)
		type = CLONE_NEWUTS;
	else if (strcmp(typestr, "user") == 0)
		type = CLONE_NEWUSER;
	else
		assert(0);

	char *path;
	if (asprintf(&path, "ns/%s", typestr) == -1)
		errExit("asprintf");

	int fd = openat(dirfd, path, O_RDONLY|O_CLOEXEC);
	free(path);
	if (fd < 0)
		goto errout;

	 
	 
	struct stat self_userns;
	if (stat("/proc/self/ns/user", &self_userns) == 0) {
		int usernsfd = ioctl(fd, NS_GET_USERNS);
		if (usernsfd != -1) {
			struct stat dest_userns;
			if (fstat(usernsfd, &dest_userns) < 0)
				errExit("fstat");
			close(usernsfd);
			if (dest_userns.st_ino != self_userns.st_ino ||
			    dest_userns.st_dev != self_userns.st_dev) {
				close(fd);
				goto errout;
			}
		}
	}

	if (syscall(__NR_setns, fd, type) < 0) {
		close(fd);
		goto errout;
	}

	close(fd);
	return 0;

errout:
	fprintf(stderr, "Error: cannot join namespace %s\n", typestr);
	return -1;
}