Ejemplo n.º 1
0
FILE *
fdopen(int fd, const char *mode)
{
	FILE *fp;
	int flags, oflags, fdflags, tmp;

	/*
	 * File descriptors are a full int, but _file is only a short.
	 * If we get a valid file descriptor that is greater than
	 * SHRT_MAX, then the fd will get sign-extended into an
	 * invalid file descriptor.  Handle this case by failing the
	 * open.
	 */
	if (fd > SHRT_MAX) {
		errno = EMFILE;
		return (NULL);
	}

	if ((flags = __sflags(mode, &oflags)) == 0)
		return (NULL);

	/* Make sure the mode the user wants is a subset of the actual mode. */
	if ((fdflags = _fcntl(fd, F_GETFL, 0)) < 0)
		return (NULL);
	/* Work around incorrect O_ACCMODE. */
	tmp = fdflags & (O_ACCMODE | O_EXEC);
	if (tmp != O_RDWR && (tmp != (oflags & O_ACCMODE))) {
		errno = EINVAL;
		return (NULL);
	}

	if ((fp = __sfp()) == NULL)
		return (NULL);

	if ((oflags & O_CLOEXEC) && _fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
		fp->_flags = 0;
		return (NULL);
	}

	fp->_flags = flags;
	/*
	 * If opened for appending, but underlying descriptor does not have
	 * O_APPEND bit set, assert __SAPP so that __swrite() caller
	 * will _sseek() to the end before write.
	 */
	/* XXX: Reuse __SALC for O_APPEND. */
	if (fdflags & O_APPEND)
		fp->_flags |= __SALC;
	else if (oflags & O_APPEND)
		fp->_flags |= __SAPP;
	fp->_file = fd;
	fp->_cookie = fp;
	fp->_read = __sread;
	fp->_write = __swrite;
	fp->_seek = __sseek;
	fp->_close = __sclose;
	return (fp);
}
Ejemplo n.º 2
0
/*
 * Open a directory with existing file descriptor.
 */
DIR *
fdopendir(int fd)
{

	if (_fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
		return (NULL);
	return (__opendir_common(fd, DTF_HIDEW|DTF_NODUP, true));
}
Ejemplo n.º 3
0
short _isatty(int fd)
{
    register short lub;

    lub = (int) _fcntl(&stdin[fd], 5, (size_t) 0);
    return (lub >= CONIN && lub <= CONOUT)
        || (lub >= COM1 && lub <= COM4)
        || (lub >= COM5 && lub <= COM16);
}
Ejemplo n.º 4
0
static int
register_to_daemon(void) {
	int flags;
	char test = 't';

	daemon_fd = connect_to_daemon(LISTEN_SOCKET_FILE);

	flags = _fcntl(daemon_fd, F_GETFD, 0);
	if (_fcntl(daemon_fd, F_SETFD, flags & FD_CLOEXEC) == -1) {
		sysv_print_err("fcntl error\n");
		return (-1);
	}

	/* Send a message such that daemon can obtain process credentials.*/
	send_msg_with_cred(daemon_fd, &test, sizeof(test));

	sysv_print("register to daemon: sock fd = %d\n", daemon_fd);

	return (0);
}
Ejemplo n.º 5
0
int
lockf(int filedes, int function, off_t size)
{
	struct flock fl;
	int cmd;

	fl.l_start = 0;
	fl.l_len = size;
	fl.l_whence = SEEK_CUR;

	switch (function) {
	case F_ULOCK:
		cmd = F_SETLK;
		fl.l_type = F_UNLCK;
		break;
	case F_LOCK:
		cmd = F_SETLKW;
		fl.l_type = F_WRLCK;
		break;
	case F_TLOCK:
		cmd = F_SETLK;
		fl.l_type = F_WRLCK;
		break;
	case F_TEST:
		fl.l_type = F_WRLCK;
		if (_fcntl(filedes, F_GETLK, &fl) == -1)
			return (-1);
		if (fl.l_type == F_UNLCK || (fl.l_sysid == 0 && fl.l_pid == getpid()))
			return (0);
		errno = EAGAIN;
		return (-1);
		/* NOTREACHED */
	default:
		errno = EINVAL;
		return (-1);
		/* NOTREACHED */
	}

	return (_fcntl(filedes, cmd, &fl));
}
Ejemplo n.º 6
0
FILE *_fdopen_r(struct _reent *ptr, int fd, const char *mode)
{
    register FILE *fp;
    int flags, oflags;
#ifdef F_GETFL
    int fdflags, fdmode;
#endif

    if ((flags = __sflags(ptr, mode, &oflags)) == 0)
        return 0;

        /* make sure the mode the user wants is a subset of the actual mode */
#ifdef F_GETFL
    if ((fdflags = _fcntl(fd, F_GETFL, 0)) < 0)
        return 0;
    fdmode = fdflags & O_ACCMODE;
    if (fdmode != O_RDWR && (fdmode != (oflags & O_ACCMODE)))
    {
        ptr->_errno = EBADF;
        return 0;
    }
#endif

    if ((fp = __sfp(ptr)) == 0)
        return 0;
    fp->_flags = flags;
    /*
     * If opened for appending, but underlying descriptor
     * does not have O_APPEND bit set, assert __SAPP so that
     * __swrite() will lseek to end before each write.
     */
    if ((oflags & O_APPEND)
#ifdef F_GETFL
        && !(fdflags & O_APPEND)
#endif
    )
        fp->_flags |= __SAPP;
    fp->_file = fd;
    fp->_cookie = (void *)fp;

#undef _read
#undef _write
#undef _seek
#undef _close

    fp->_read = __sread;
    fp->_write = __swrite;
    fp->_seek = __sseek;
    fp->_close = __sclose;
    return fp;
}
Ejemplo n.º 7
0
/* Should be called with mutex acquired */
static void
connectlog(void)
{
	struct sockaddr_un SyslogAddr;	/* AF_UNIX address of local logger */

	if (LogFile == -1) {
		if ((LogFile = _socket(AF_UNIX, SOCK_DGRAM, 0)) == -1)
			return;
		(void)_fcntl(LogFile, F_SETFD, 1);
	}
	if (LogFile != -1 && status == NOCONN) {
		SyslogAddr.sun_len = sizeof(SyslogAddr);
		SyslogAddr.sun_family = AF_UNIX;

		/*
		 * First try priveleged socket. If no success,
		 * then try default socket.
		 */
		(void)strncpy(SyslogAddr.sun_path, _PATH_LOG_PRIV,
		    sizeof SyslogAddr.sun_path);
		if (_connect(LogFile, (struct sockaddr *)&SyslogAddr,
		    sizeof(SyslogAddr)) != -1)
			status = CONNPRIV;

		if (status == NOCONN) {
			(void)strncpy(SyslogAddr.sun_path, _PATH_LOG,
			    sizeof SyslogAddr.sun_path);
			if (_connect(LogFile, (struct sockaddr *)&SyslogAddr,
			    sizeof(SyslogAddr)) != -1)
				status = CONNDEF;
		}

		if (status == NOCONN) {
			/*
			 * Try the old "/dev/log" path, for backward
			 * compatibility.
			 */
			(void)strncpy(SyslogAddr.sun_path, _PATH_OLDLOG,
			    sizeof SyslogAddr.sun_path);
			if (_connect(LogFile, (struct sockaddr *)&SyslogAddr,
			    sizeof(SyslogAddr)) != -1)
				status = CONNDEF;
		}

		if (status == NOCONN) {
			(void)_close(LogFile);
			LogFile = -1;
		}
	}
}
Ejemplo n.º 8
0
/*
 * Open a directory with existing file descriptor.
 */
DIR *
fdopendir(int fd)
{
	struct stat statb;

	/* Check that fd is associated with a directory. */
	if (_fstat(fd, &statb) != 0)
		return (NULL);
	if (!S_ISDIR(statb.st_mode)) {
		errno = ENOTDIR;
		return (NULL);
	}
	if (_fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
		return (NULL);
	return (__opendir_common(fd, NULL, DTF_HIDEW|DTF_NODUP));
}
Ejemplo n.º 9
0
/*
 * Opens the connection with the specified params. Initializes all kqueues.
 */
struct cached_connection_ *
__open_cached_connection(struct cached_connection_params const *params)
{
	struct cached_connection_ *retval;
	struct kevent eventlist;
	struct sockaddr_un client_address;
	int client_address_len, client_socket;
	int res;

	assert(params != NULL);

	client_socket = _socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
	client_address.sun_family = PF_LOCAL;
	strncpy(client_address.sun_path, params->socket_path,
	    sizeof(client_address.sun_path));
	client_address_len = sizeof(client_address.sun_family) +
	    strlen(client_address.sun_path) + 1;

	res = _connect(client_socket, (struct sockaddr *)&client_address,
	    client_address_len);
	if (res == -1) {
		_close(client_socket);
		return (NULL);
	}
	_fcntl(client_socket, F_SETFL, O_NONBLOCK);

	retval = malloc(sizeof(struct cached_connection_));
	assert(retval != NULL);
	memset(retval, 0, sizeof(struct cached_connection_));

	retval->sockfd = client_socket;

	retval->write_queue = kqueue();
	assert(retval->write_queue != -1);

	EV_SET(&eventlist, retval->sockfd, EVFILT_WRITE, EV_ADD, 0, 0, NULL);
	res = _kevent(retval->write_queue, &eventlist, 1, NULL, 0, NULL);

	retval->read_queue = kqueue();
	assert(retval->read_queue != -1);

	EV_SET(&eventlist, retval->sockfd, EVFILT_READ, EV_ADD, 0, 0, NULL);
	res = _kevent(retval->read_queue, &eventlist, 1, NULL, 0, NULL);

	return (retval);
}
Ejemplo n.º 10
0
int
__dup3(int oldfd, int newfd, int flags)
{
	int how;

	if (oldfd == newfd) {
		errno = EINVAL;
		return (-1);
	}

	if (flags & ~O_CLOEXEC) {
		errno = EINVAL;
		return (-1);
	}

	how = (flags & O_CLOEXEC) ? F_DUP2FD_CLOEXEC : F_DUP2FD;

	return (_fcntl(oldfd, how, newfd));
}
Ejemplo n.º 11
0
int
__rpc_raise_fd(int fd)
{
	int nfd;

	if (fd >= __rpc_minfd)
		return (fd);

	if ((nfd = _fcntl(fd, F_DUPFD, __rpc_minfd)) == -1)
		return (fd);

	if (_fsync(nfd) == -1) {
		_close(nfd);
		return (fd);
	}

	if (_close(fd) == -1) {
		/* this is okay, we will syslog an error, then use the new fd */
		syslog(LOG_ERR, "could not close() fd %d; mem & fd leak", fd);
	}

	return (nfd);
}
Ejemplo n.º 12
0
FILE *
fdopen(int fd, const char *mode)
{
	FILE *fp;
	int flags, oflags, fdflags, tmp;

	if ((flags = __sflags(mode, &oflags)) == 0)
		return (NULL);

	/* Make sure the mode the user wants is a subset of the actual mode. */
	if ((fdflags = _fcntl(fd, F_GETFL, 0)) < 0)
		return (NULL);
	tmp = fdflags & O_ACCMODE;
	if (tmp != O_RDWR && (tmp != (oflags & O_ACCMODE))) {
		errno = EINVAL;
		return (NULL);
	}

	if ((fp = __sfp()) == NULL)
		return (NULL);
	fp->pub._flags = flags;
	/*
	 * If opened for appending, but underlying descriptor does not have
	 * O_APPEND bit set, assert __SAPP so that __swrite() caller
	 * will _sseek() to the end before write.
	 */
	if ((oflags & O_APPEND) && !(fdflags & O_APPEND))
		fp->pub._flags |= __SAPP;
	fp->pub._fileno = fd;
	fp->_cookie = fp;
	fp->_read = __sread;
	fp->_write = __swrite;
	fp->_seek = __sseek;
	fp->_close = __sclose;
	return (fp);
}
Ejemplo n.º 13
0
int
shm_open(const char *path, int flags, mode_t mode)
{
	int fd;
	struct stat stab;

	if ((flags & O_ACCMODE) == O_WRONLY)
		return (EINVAL);

	fd = _open(path, flags, mode);
	if (fd != -1) {
		if (_fstat(fd, &stab) != 0 || !S_ISREG(stab.st_mode)) {
			_close(fd);
			errno = EINVAL;
			return (-1);
		}

		if (_fcntl(fd, F_SETFL, (int)FPOSIXSHM) != 0) {
			_close(fd);
			return (-1);
		}
	}
	return (fd);
}
Ejemplo n.º 14
0
/*
 * This is the simplified interface to the client rpc layer.
 * The client handle is not destroyed here and is reused for
 * the future calls to same prog, vers, host and nettype combination.
 *
 * The total time available is 25 seconds.
 */
enum clnt_stat
rpc_call(const char *host,			/* host name */
	rpcprog_t prognum,			/* program number */
	rpcvers_t versnum,			/* version number */
	rpcproc_t procnum,			/* procedure number */
	xdrproc_t inproc,
	const char *in,
	xdrproc_t outproc,			/* in/out XDR procedures */
	char  *out,				/* recv/send data */
	const char *nettype)			/* nettype */
{
	struct rpc_call_private *rcp = NULL;
	enum clnt_stat clnt_stat;
	struct timeval timeout, tottimeout;
	static thread_key_t rpc_call_key;
	int main_thread = 1;

	if ((main_thread = thr_main())) {
		rcp = rpc_call_private_main;
	} else {
		if (rpc_call_key == 0) {
			mutex_lock(&tsd_lock);
			if (rpc_call_key == 0)
				thr_keycreate(&rpc_call_key, rpc_call_destroy);
			mutex_unlock(&tsd_lock);
		}
		rcp = (struct rpc_call_private *)thr_getspecific(rpc_call_key);
	}
	if (rcp == NULL) {
		rcp = malloc(sizeof (*rcp));
		if (rcp == NULL) {
			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
			rpc_createerr.cf_error.re_errno = errno;
			return (rpc_createerr.cf_stat);
		}
		if (main_thread)
			rpc_call_private_main = rcp;
		else
			thr_setspecific(rpc_call_key, (void *) rcp);
		rcp->valid = 0;
		rcp->client = NULL;
	}
	if ((nettype == NULL) || (nettype[0] == 0))
		nettype = "netpath";
	if (!(rcp->valid && rcp->pid == getpid() &&
		(rcp->prognum == prognum) &&
		(rcp->versnum == versnum) &&
		(!strcmp(rcp->host, host)) &&
		(!strcmp(rcp->nettype, nettype)))) {
		int fd;

		rcp->valid = 0;
		if (rcp->client)
			CLNT_DESTROY(rcp->client);
		/*
		 * Using the first successful transport for that type
		 */
		rcp->client = clnt_create(host, prognum, versnum, nettype);
		rcp->pid = getpid();
		if (rcp->client == NULL) {
			return (rpc_createerr.cf_stat);
		}
		/*
		 * Set time outs for connectionless case.  Do it
		 * unconditionally.  Faster than doing a t_getinfo()
		 * and then doing the right thing.
		 */
		timeout.tv_usec = 0;
		timeout.tv_sec = 5;
		CLNT_CONTROL(rcp->client,
				CLSET_RETRY_TIMEOUT, (char *)(void *)&timeout);
		if (CLNT_CONTROL(rcp->client, CLGET_FD, (char *)(void *)&fd))
			_fcntl(fd, F_SETFD, 1);	/* make it "close on exec" */
		rcp->prognum = prognum;
		rcp->versnum = versnum;
		if ((strlen(host) < (size_t)MAXHOSTNAMELEN) &&
		    (strlen(nettype) < (size_t)NETIDLEN)) {
			strcpy(rcp->host, host);
			strcpy(rcp->nettype, nettype);
			rcp->valid = 1;
		} else {
			rcp->valid = 0;
		}
	} /* else reuse old client */
	tottimeout.tv_sec = 25;
	tottimeout.tv_usec = 0;
	/*LINTED const castaway*/
	clnt_stat = CLNT_CALL(rcp->client, procnum, inproc, (char *) in,
	    outproc, out, tottimeout);
	/*
	 * if call failed, empty cache
	 */
	if (clnt_stat != RPC_SUCCESS)
		rcp->valid = 0;
	return (clnt_stat);
}
Ejemplo n.º 15
0
int
rcmd_af(char **ahost, int rport, const char *locuser, const char *remuser,
	const char *cmd, int *fd2p, int af)
{
	struct addrinfo hints, *res, *ai;
	struct sockaddr_storage from;
	fd_set reads;
	sigset_t oldmask, newmask;
	pid_t pid;
	int s, aport, lport, timo, error;
	char c, *p;
	int refused, nres;
	char num[8];
	static char canonnamebuf[MAXDNAME];	/* is it proper here? */

	/* call rcmdsh() with specified remote shell if appropriate. */
	if (!issetugid() && (p = getenv("RSH"))) {
		struct servent *sp = getservbyname("shell", "tcp");

		if (sp && sp->s_port == rport)
			return (rcmdsh(ahost, rport, locuser, remuser,
			    cmd, p));
	}

	/* use rsh(1) if non-root and remote port is shell. */
	if (geteuid()) {
		struct servent *sp = getservbyname("shell", "tcp");

		if (sp && sp->s_port == rport)
			return (rcmdsh(ahost, rport, locuser, remuser,
			    cmd, NULL));
	}

	pid = getpid();

	memset(&hints, 0, sizeof(hints));
	hints.ai_flags = AI_CANONNAME;
	hints.ai_family = af;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = 0;
	snprintf(num, sizeof(num), "%d", ntohs(rport));
	error = getaddrinfo(*ahost, num, &hints, &res);
	if (error) {
		fprintf(stderr, "rcmd: getaddrinfo: %s\n",
			gai_strerror(error));
		if (error == EAI_SYSTEM)
			fprintf(stderr, "rcmd: getaddrinfo: %s\n",
				strerror(errno));
		return (-1);
	}

	if (res->ai_canonname &&
	    strlen(res->ai_canonname) + 1 < sizeof(canonnamebuf)) {
		strncpy(canonnamebuf, res->ai_canonname, sizeof(canonnamebuf));
		*ahost = canonnamebuf;
	}
	nres = 0;
	for (ai = res; ai; ai = ai->ai_next)
		nres++;
	ai = res;
	refused = 0;
	sigemptyset(&newmask);
	sigaddset(&newmask, SIGURG);
	_sigprocmask(SIG_BLOCK, (const sigset_t *)&newmask, &oldmask);
	for (timo = 1, lport = IPPORT_RESERVED - 1;;) {
		s = rresvport_af(&lport, ai->ai_family);
		if (s < 0) {
			if (errno != EAGAIN && ai->ai_next) {
				ai = ai->ai_next;
				continue;
			}
			if (errno == EAGAIN)
				fprintf(stderr,
				    "rcmd: socket: All ports in use\n");
			else
				fprintf(stderr, "rcmd: socket: %s\n",
				    strerror(errno));
			freeaddrinfo(res);
			_sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask,
			    NULL);
			return (-1);
		}
		_fcntl(s, F_SETOWN, pid);
		if (_connect(s, ai->ai_addr, ai->ai_addrlen) >= 0)
			break;
		_close(s);
		if (errno == EADDRINUSE) {
			lport--;
			continue;
		}
		if (errno == ECONNREFUSED)
			refused = 1;
		if (ai->ai_next == NULL && (!refused || timo > 16)) {
			fprintf(stderr, "%s: %s\n", *ahost, strerror(errno));
			freeaddrinfo(res);
			_sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask,
			    NULL);
			return (-1);
		}
		if (nres > 1) {
			int oerrno = errno;

			getnameinfo(ai->ai_addr, ai->ai_addrlen, paddr,
			    sizeof(paddr), NULL, 0, NI_NUMERICHOST);
			fprintf(stderr, "connect to address %s: ", paddr);
			errno = oerrno;
			perror(0);
		}
		if ((ai = ai->ai_next) == NULL) {
			/* refused && timo <= 16 */
			struct timespec time_to_sleep, time_remaining;

			time_to_sleep.tv_sec = timo;
			time_to_sleep.tv_nsec = 0;
			_nanosleep(&time_to_sleep, &time_remaining);
			timo *= 2;
			ai = res;
			refused = 0;
		}
		if (nres > 1) {
			getnameinfo(ai->ai_addr, ai->ai_addrlen, paddr,
			    sizeof(paddr), NULL, 0, NI_NUMERICHOST);
			fprintf(stderr, "Trying %s...\n", paddr);
		}
	}
	lport--;
	if (fd2p == 0) {
		_write(s, "", 1);
		lport = 0;
	} else {
		int s2 = rresvport_af(&lport, ai->ai_family), s3;
		socklen_t len = ai->ai_addrlen;
		int nfds;

		if (s2 < 0)
			goto bad;
		_listen(s2, 1);
		snprintf(num, sizeof(num), "%d", lport);
		if (_write(s, num, strlen(num)+1) != strlen(num)+1) {
			fprintf(stderr,
			    "rcmd: write (setting up stderr): %s\n",
			    strerror(errno));
			_close(s2);
			goto bad;
		}
		nfds = max(s, s2)+1;
		if(nfds > FD_SETSIZE) {
			fprintf(stderr, "rcmd: too many files\n");
			_close(s2);
			goto bad;
		}
again:
		FD_ZERO(&reads);
		FD_SET(s, &reads);
		FD_SET(s2, &reads);
		errno = 0;
		if (_select(nfds, &reads, 0, 0, 0) < 1 || !FD_ISSET(s2, &reads)){
			if (errno != 0)
				fprintf(stderr,
				    "rcmd: select (setting up stderr): %s\n",
				    strerror(errno));
			else
				fprintf(stderr,
				"select: protocol failure in circuit setup\n");
			_close(s2);
			goto bad;
		}
		s3 = _accept(s2, (struct sockaddr *)&from, &len);
		switch (from.ss_family) {
		case AF_INET:
			aport = ntohs(((struct sockaddr_in *)&from)->sin_port);
			break;
#ifdef INET6
		case AF_INET6:
			aport = ntohs(((struct sockaddr_in6 *)&from)->sin6_port);
			break;
#endif
		default:
			aport = 0;	/* error */
			break;
		}
		/*
		 * XXX careful for ftp bounce attacks. If discovered, shut them
		 * down and check for the real auxiliary channel to connect.
		 */
		if (aport == 20) {
			_close(s3);
			goto again;
		}
		_close(s2);
		if (s3 < 0) {
			fprintf(stderr,
			    "rcmd: accept: %s\n", strerror(errno));
			lport = 0;
			goto bad;
		}
		*fd2p = s3;
		if (aport >= IPPORT_RESERVED || aport < IPPORT_RESERVED / 2) {
			fprintf(stderr,
			    "socket: protocol failure in circuit setup.\n");
			goto bad2;
		}
	}
	_write(s, locuser, strlen(locuser)+1);
	_write(s, remuser, strlen(remuser)+1);
	_write(s, cmd, strlen(cmd)+1);
	if (_read(s, &c, 1) != 1) {
		fprintf(stderr,
		    "rcmd: %s: %s\n", *ahost, strerror(errno));
		goto bad2;
	}
	if (c != 0) {
		while (_read(s, &c, 1) == 1) {
			_write(STDERR_FILENO, &c, 1);
			if (c == '\n')
				break;
		}
		goto bad2;
	}
	_sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask, NULL);
	freeaddrinfo(res);
	return (s);
bad2:
	if (lport)
		_close(*fd2p);
bad:
	_close(s);
	_sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask, NULL);
	freeaddrinfo(res);
	return (-1);
}
Ejemplo n.º 16
0
/*
 * Common routine for opendir(3), __opendir2(3) and fdopendir(3).
 */
static DIR *
__opendir_common(int fd, const char *name, int flags)
{
	DIR *dirp;
	int incr;
	int saved_errno;
	int unionstack;
	struct stat statb;

	dirp = NULL;
	/* _fstat() the open handler because the file may have changed.  */
	if (_fstat(fd, &statb) != 0)
		goto fail;
	if (!S_ISDIR(statb.st_mode)) {
		errno = ENOTDIR;
		goto fail;
	}
	if (_fcntl(fd, F_SETFD, FD_CLOEXEC) == -1 ||
	    (dirp = malloc(sizeof(DIR) + sizeof(struct _telldir))) == NULL)
		goto fail;

	dirp->dd_td = (struct _telldir *)((char *)dirp + sizeof(DIR));
	LIST_INIT(&dirp->dd_td->td_locq);
	dirp->dd_td->td_loccnt = 0;

	/*
	 * Use the system page size if that is a multiple of DIRBLKSIZ.
	 * Hopefully this can be a big win someday by allowing page
	 * trades to user space to be done by _getdirentries().
	 */
	incr = getpagesize();
	if ((incr % DIRBLKSIZ) != 0) 
		incr = DIRBLKSIZ;

	/*
	 * Determine whether this directory is the top of a union stack.
	 */
	if (flags & DTF_NODUP) {
		struct statfs sfb;

		if (_fstatfs(fd, &sfb) < 0)
			goto fail;
		unionstack = !strcmp(sfb.f_fstypename, "unionfs")
		    || (sfb.f_flags & MNT_UNION);
	} else {
		unionstack = 0;
	}

	if (unionstack) {
		int len = 0;
		int space = 0;
		char *buf = 0;
		char *ddptr = 0;
		char *ddeptr;
		int n;
		struct dirent **dpv;

		/*
		 * The strategy here is to read all the directory
		 * entries into a buffer, sort the buffer, and
		 * remove duplicate entries by setting the inode
		 * number to zero.
		 */

		do {
			/*
			 * Always make at least DIRBLKSIZ bytes
			 * available to _getdirentries
			 */
			if (space < DIRBLKSIZ) {
				space += incr;
				len += incr;
				buf = reallocf(buf, len);
				if (buf == NULL)
					goto fail;
				ddptr = buf + (len - space);
			}

			n = _getdirentries(fd, ddptr, space, &dirp->dd_seek);
			if (n > 0) {
				ddptr += n;
				space -= n;
			}
		} while (n > 0);

		ddeptr = ddptr;
		flags |= __DTF_READALL;

		/*
		 * Re-open the directory.
		 * This has the effect of rewinding back to the
		 * top of the union stack and is needed by
		 * programs which plan to fchdir to a descriptor
		 * which has also been read -- see fts.c.
		 */
		if (flags & DTF_REWIND) {
			(void)_close(fd);
			if ((fd = _open(name, O_RDONLY | O_DIRECTORY)) == -1) {
				saved_errno = errno;
				free(buf);
				free(dirp);
				errno = saved_errno;
				return (NULL);
			}
		}

		/*
		 * There is now a buffer full of (possibly) duplicate
		 * names.
		 */
		dirp->dd_buf = buf;

		/*
		 * Go round this loop twice...
		 *
		 * Scan through the buffer, counting entries.
		 * On the second pass, save pointers to each one.
		 * Then sort the pointers and remove duplicate names.
		 */
		for (dpv = 0;;) {
			n = 0;
			ddptr = buf;
			while (ddptr < ddeptr) {
				struct dirent *dp;

				dp = (struct dirent *) ddptr;
				if ((long)dp & 03L)
					break;
				if ((dp->d_reclen <= 0) ||
				    (dp->d_reclen > (ddeptr + 1 - ddptr)))
					break;
				ddptr += dp->d_reclen;
				if (dp->d_fileno) {
					if (dpv)
						dpv[n] = dp;
					n++;
				}
			}

			if (dpv) {
				struct dirent *xp;

				/*
				 * This sort must be stable.
				 */
				mergesort(dpv, n, sizeof(*dpv),
				    opendir_compar);

				dpv[n] = NULL;
				xp = NULL;

				/*
				 * Scan through the buffer in sort order,
				 * zapping the inode number of any
				 * duplicate names.
				 */
				for (n = 0; dpv[n]; n++) {
					struct dirent *dp = dpv[n];

					if ((xp == NULL) ||
					    strcmp(dp->d_name, xp->d_name)) {
						xp = dp;
					} else {
						dp->d_fileno = 0;
					}
					if (dp->d_type == DT_WHT &&
					    (flags & DTF_HIDEW))
						dp->d_fileno = 0;
				}

				free(dpv);
				break;
			} else {
				dpv = malloc((n+1) * sizeof(struct dirent *));
				if (dpv == NULL)
					break;
			}
		}

		dirp->dd_len = len;
		dirp->dd_size = ddptr - dirp->dd_buf;
	} else {
		dirp->dd_len = incr;
		dirp->dd_size = 0;
		dirp->dd_buf = malloc(dirp->dd_len);
		if (dirp->dd_buf == NULL)
			goto fail;
		dirp->dd_seek = 0;
		flags &= ~DTF_REWIND;
	}

	dirp->dd_loc = 0;
	dirp->dd_fd = fd;
	dirp->dd_flags = flags;
	dirp->dd_lock = NULL;

	/*
	 * Set up seek point for rewinddir.
	 */
	dirp->dd_rewind = telldir(dirp);

	return (dirp);

fail:
	saved_errno = errno;
	free(dirp);
	(void)_close(fd);
	errno = saved_errno;
	return (NULL);
}
Ejemplo n.º 17
0
/*ARGSUSED*/
static bool_t
rendezvous_request(SVCXPRT *xprt, struct rpc_msg *msg)
{
	int sock, flags;
	struct cf_rendezvous *r;
	struct cf_conn *cd;
	struct sockaddr_storage addr;
	socklen_t len;
	struct __rpc_sockinfo si;
	SVCXPRT *newxprt;
	fd_set cleanfds;

	assert(xprt != NULL);
	assert(msg != NULL);

	r = (struct cf_rendezvous *)xprt->xp_p1;
again:
	len = sizeof addr;
	if ((sock = _accept(xprt->xp_fd, (struct sockaddr *)(void *)&addr,
	    &len)) < 0) {
		if (errno == EINTR)
			goto again;
		/*
		 * Clean out the most idle file descriptor when we're
		 * running out.
		 */
		if (errno == EMFILE || errno == ENFILE) {
			cleanfds = svc_fdset;
			__svc_clean_idle(&cleanfds, 0, FALSE);
			goto again;
		}
		return (FALSE);
	}
	/*
	 * make a new transporter (re-uses xprt)
	 */
	newxprt = makefd_xprt(sock, r->sendsize, r->recvsize);
	newxprt->xp_rtaddr.buf = mem_alloc(len);
	if (newxprt->xp_rtaddr.buf == NULL)
		return (FALSE);
	memcpy(newxprt->xp_rtaddr.buf, &addr, len);
	newxprt->xp_rtaddr.len = len;
#ifdef PORTMAP
	if (addr.ss_family == AF_INET || addr.ss_family == AF_LOCAL) {
		newxprt->xp_raddr = *(struct sockaddr_in *)newxprt->xp_rtaddr.buf;
		newxprt->xp_addrlen = sizeof (struct sockaddr_in);
	}
#endif				/* PORTMAP */
	if (__rpc_fd2sockinfo(sock, &si) && si.si_proto == IPPROTO_TCP) {
		len = 1;
		/* XXX fvdl - is this useful? */
		_setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &len, sizeof (len));
	}

	cd = (struct cf_conn *)newxprt->xp_p1;

	cd->recvsize = r->recvsize;
	cd->sendsize = r->sendsize;
	cd->maxrec = r->maxrec;

	if (cd->maxrec != 0) {
		flags = _fcntl(sock, F_GETFL, 0);
		if (flags  == -1)
			return (FALSE);
		if (_fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1)
			return (FALSE);
		if (cd->recvsize > cd->maxrec)
			cd->recvsize = cd->maxrec;
		cd->nonblock = TRUE;
		__xdrrec_setnonblock(&cd->xdrs, cd->maxrec);
	} else
		cd->nonblock = FALSE;

	gettimeofday(&cd->last_recv_time, NULL);

	return (FALSE); /* there is never an rpc msg to be processed */
}
Ejemplo n.º 18
0
int
_ftello(FILE *fp, fpos_t *offset)
{
	fpos_t pos;
	size_t n;
	int dflags;

	if (fp->_seek == NULL) {
		errno = ESPIPE;			/* historic practice */
		return (1);
	}

	/*
	 * Find offset of underlying I/O object, then
	 * adjust for buffered bytes.
	 */
	if (fp->_flags & __SOFF)
		pos = fp->_offset;
	else {
		pos = _sseek(fp, (fpos_t)0, SEEK_CUR);
		if (pos == -1)
			return (1);
	}
	if (fp->_flags & __SRD) {
		/*
		 * Reading.  Any unread characters (including
		 * those from ungetc) cause the position to be
		 * smaller than that in the underlying object.
		 */
		if ((pos -= (HASUB(fp) ? fp->_ur : fp->_r)) < 0) {
			fp->_flags |= __SERR;
			errno = EIO;
			return (1);
		}
		if (HASUB(fp))
			pos -= fp->_r;  /* Can be negative at this point. */
	} else if ((fp->_flags & __SWR) && fp->_p != NULL) {
		dflags = 0;
		if (fp->_flags & __SAPP)
			dflags = O_APPEND;
		else if (fp->_file != -1 &&
			 (dflags = _fcntl(fp->_file, F_GETFL)) < 0)
			return (1);
		if ((dflags & O_APPEND) &&
		    (pos = _sseek(fp, (fpos_t)0, SEEK_END)) == -1) {
			if ((fp->_flags & __SOPT) || __sflush(fp) ||
			    (pos = _sseek(fp, (fpos_t)0, SEEK_CUR)) == -1)
				return (1);
			else {
				*offset = pos;
				return (0);
			}
		}
		/*
		 * Writing.  Any buffered characters cause the
		 * position to be greater than that in the
		 * underlying object.
		 */
		n = fp->_p - fp->_bf._base;
		if (pos > OFF_MAX - n) {
			errno = EOVERFLOW;
			return (1);
		}
		pos += n;
	}
	*offset = pos;
	return (0);
}
Ejemplo n.º 19
0
DIR *
__fdopendir2(int fd, int flags)
{
	DIR *dirp;
	int incr;
	int saved_errno;
	struct stat statb;

	dirp = NULL;

	if (_fstat(fd, &statb) != 0)
		goto fail;
	if (!S_ISDIR(statb.st_mode)) {
		errno = ENOTDIR;
		goto fail;
	}
	if (_fcntl(fd, F_SETFD, FD_CLOEXEC) == -1 ||
	    (dirp = malloc(sizeof(DIR))) == NULL)
		goto fail;

	/*
	 * Use the system page size if that is a multiple of DIRBLKSIZ.
	 * Hopefully this can be a big win someday by allowing page
	 * trades to user space to be done by _getdirentries().
	 */
	incr = getpagesize();
	if ((incr % DIRBLKSIZ) != 0) 
		incr = DIRBLKSIZ;

	dirp->dd_len = incr;
	dirp->dd_buf = malloc(dirp->dd_len);
	if (dirp->dd_buf == NULL)
		goto fail;
	flags &= ~DTF_REWIND;

	dirp->dd_loc = 0;
	dirp->dd_fd = fd;
	dirp->dd_flags = flags;
	dirp->dd_lock = NULL;

	/*
	 * Set up seek point for rewinddir.
	 */
	dirp->dd_seek = 0;
	dirp->dd_rewind = telldir(dirp);

	/*
	 * The file offset of the fd passed to fdopendir() determines the
	 * initial entry returned by readdir().  Save this offset so that
	 * telldir() right after fdopendir() returns a value pointing to this
	 * initial entry.  
	 * We don't have to worry about misaligned file offsets.  The kernel
	 * deals with these.
	 */
	if ((dirp->dd_seek = lseek(fd, 0, SEEK_CUR)) < 0)
		goto fail;

	return (dirp);

fail:
	saved_errno = errno;
	if (dirp != NULL) {
		_reclaim_telldir(dirp);
		free(dirp->dd_buf);
	}
	free(dirp);
	errno = saved_errno;
	return (NULL);
}
Ejemplo n.º 20
0
/*
 * Keep the handle cached.  This call may be made quite often.
 */
static CLIENT *
getkeyserv_handle(int vers)
{
	void *localhandle;
	struct netconfig *nconf;
	struct netconfig *tpconf;
	struct key_call_private *kcp = key_call_private_main;
	struct timeval wait_time;
	struct utsname u;
	int main_thread;
	int fd;
	static thread_key_t key_call_key;

#define	TOTAL_TIMEOUT	30	/* total timeout talking to keyserver */
#define	TOTAL_TRIES	5	/* Number of tries */

	if ((main_thread = thr_main())) {
		kcp = key_call_private_main;
	} else {
		if (key_call_key == 0) {
			mutex_lock(&tsd_lock);
			if (key_call_key == 0)
				thr_keycreate(&key_call_key, key_call_destroy);
			mutex_unlock(&tsd_lock);
		}
		kcp = (struct key_call_private *)thr_getspecific(key_call_key);
	}
	if (kcp == NULL) {
		kcp = (struct key_call_private *)malloc(sizeof (*kcp));
		if (kcp == NULL) {
			return (NULL);
		}
		if (main_thread)
			key_call_private_main = kcp;
		else
			thr_setspecific(key_call_key, (void *) kcp);
		kcp->client = NULL;
	}

	/* if pid has changed, destroy client and rebuild */
	if (kcp->client != NULL && kcp->pid != getpid()) {
		clnt_destroy(kcp->client);
		kcp->client = NULL;
	}

	if (kcp->client != NULL) {
		/* if uid has changed, build client handle again */
		if (kcp->uid != geteuid()) {
			kcp->uid = geteuid();
			auth_destroy(kcp->client->cl_auth);
			kcp->client->cl_auth =
				authsys_create("", kcp->uid, 0, 0, NULL);
			if (kcp->client->cl_auth == NULL) {
				clnt_destroy(kcp->client);
				kcp->client = NULL;
				return (NULL);
			}
		}
		/* Change the version number to the new one */
		clnt_control(kcp->client, CLSET_VERS, (void *)&vers);
		return (kcp->client);
	}
	if (!(localhandle = setnetconfig())) {
		return (NULL);
	}
	tpconf = NULL;
	if (uname(&u) == -1)
	{
		endnetconfig(localhandle);
		return (NULL);
	}
	while ((nconf = getnetconfig(localhandle)) != NULL) {
		if (strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) {
			/*
			 * We use COTS_ORD here so that the caller can
			 * find out immediately if the server is dead.
			 */
			if (nconf->nc_semantics == NC_TPI_COTS_ORD) {
				kcp->client = clnt_tp_create(u.nodename,
					KEY_PROG, vers, nconf);
				if (kcp->client)
					break;
			} else {
				tpconf = nconf;
			}
		}
	}
	if ((kcp->client == NULL) && (tpconf))
		/* Now, try the CLTS or COTS loopback transport */
		kcp->client = clnt_tp_create(u.nodename,
			KEY_PROG, vers, tpconf);
	endnetconfig(localhandle);

	if (kcp->client == NULL) {
		return (NULL);
	}
	kcp->uid = geteuid();
	kcp->pid = getpid();
	kcp->client->cl_auth = authsys_create("", kcp->uid, 0, 0, NULL);
	if (kcp->client->cl_auth == NULL) {
		clnt_destroy(kcp->client);
		kcp->client = NULL;
		return (NULL);
	}

	wait_time.tv_sec = TOTAL_TIMEOUT/TOTAL_TRIES;
	wait_time.tv_usec = 0;
	clnt_control(kcp->client, CLSET_RETRY_TIMEOUT,
		(char *)&wait_time);
	if (clnt_control(kcp->client, CLGET_FD, (char *)&fd))
		_fcntl(fd, F_SETFD, 1);	/* make it "close on exec" */

	return (kcp->client);
}
Ejemplo n.º 21
0
int rcmd_af(char **ahost, unsigned short rport, const char *locuser,
    const char *remuser, const char *cmd, int *fd2p, int af)
{
	int s, timo = 1;
	ssize_t retval;
	pid_t pid;
	struct sockaddr_storage caddr, faddr;
	struct sockaddr_in *sin;
	struct sockaddr_in6 *sin6;
	struct addrinfo hints;
	struct addrinfo *res, *resp;
	size_t addrlen;
	int rc;
#define	MAX_SHORTSTRLEN 6
	char aport[MAX_SHORTSTRLEN];
	char c;
	int lport = 0;
#ifdef SYSV
	sigset_t oldmask;
	sigset_t newmask;
	struct sigaction oldaction;
	struct sigaction newaction;
#else
	int oldmask;
#endif /* SYSV */
	fd_set fdset;
	int selret;
	char *addr;
	static char hostname[MAXHOSTNAMELEN];
	socklen_t len;
	char abuf[INET6_ADDRSTRLEN];

	if (!(af == AF_INET || af == AF_INET6 || af == AF_UNSPEC)) {
		errno = EAFNOSUPPORT;
		return (-1);
	}

	pid = getpid();
	memset(&hints, 0, sizeof (hints));
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_flags = AI_CANONNAME;
	if (af == AF_INET6) {
		hints.ai_flags |= AI_V4MAPPED;
		hints.ai_family = AF_UNSPEC;
	} else {
		hints.ai_family = af;
	}
	(void) snprintf(aport, MAX_SHORTSTRLEN, "%u", ntohs(rport));
	rc = getaddrinfo(*ahost, aport, &hints, &res);
	if (rc != 0) {
		(void) fprintf(stderr,
		    _dgettext(TEXT_DOMAIN, "%s: unknown host%s\n"),
		    *ahost, rc == EAI_AGAIN ? " (try again later)" : "");
		return (-1);
	}
	resp = res;
	(void) strlcpy(hostname, res->ai_canonname, MAXHOSTNAMELEN);
	*ahost = hostname;
#ifdef SYSV
	/* ignore SIGPIPE */
	bzero((char *)&newaction, sizeof (newaction));
	newaction.sa_handler = SIG_IGN;
	(void) _sigaction(SIGPIPE, &newaction, &oldaction);

	/* block SIGURG */
	bzero((char *)&newmask, sizeof (newmask));
	(void) _sigaddset(&newmask, SIGURG);
	(void) _sigprocmask(SIG_BLOCK, &newmask, &oldmask);
#else
	oldmask = _sigblock(sigmask(SIGURG));
#endif /* SYSV */
	for (;;) {
		s = rresvport_af(&lport, res->ai_family);
		if (s < 0) {
			int af = res->ai_family;

			/*
			 * See if we have any addresses of a different type
			 * to try.
			 */
			while (res != NULL && res->ai_family == af)
				res = res->ai_next;

			if (res != NULL)
				continue;

			if (errno == EAGAIN)
				(void) fprintf(stderr,
				    _dgettext(TEXT_DOMAIN,
				    "socket: All ports in use\n"));
			else
				perror("rcmd: socket");
#ifdef SYSV
			/* restore original SIGPIPE handler */
			(void) _sigaction(SIGPIPE, &oldaction,
			    (struct sigaction *)0);

			/* restore original signal mask */
			(void) _sigprocmask(SIG_SETMASK, &oldmask,
			    (sigset_t *)0);
#else
			sigsetmask(oldmask);
#endif /* SYSV */
			freeaddrinfo(resp);
			return (-1);
		}
		bzero((char *)&caddr, sizeof (caddr));
		bcopy(res->ai_addr, &caddr, res->ai_addrlen);
		addrlen = res->ai_addrlen;
		if (af == AF_INET6 && res->ai_addr->sa_family == AF_INET) {
			struct in6_addr ia6;
			struct sockaddr_in6 *in6addr;
			IN6_INADDR_TO_V4MAPPED(&((struct sockaddr_in *)
			    res->ai_addr)->sin_addr, &ia6);
			in6addr = (struct sockaddr_in6 *)&caddr;
			in6addr->sin6_addr = ia6;
			in6addr->sin6_family = AF_INET6;
			addrlen = sizeof (struct sockaddr_in6);
		}
		(void) _fcntl(s, F_SETOWN, pid);
		if (connect(s, (struct sockaddr *)&caddr, addrlen) >= 0)
			break;
		(void) close(s);
		if (errno == EADDRINUSE) {
			lport = 0;
			continue;
		}
		if (errno == ECONNREFUSED && timo <= 16) {
			(void) sleep(timo);
			timo *= 2;
			continue;
		}
		if (res->ai_next != NULL) {
			int oerrno = errno;
			if (res->ai_addr->sa_family == AF_INET6)
				addr = (char *)&((struct sockaddr_in6 *)
				    res->ai_addr)->sin6_addr;
			else
				addr = (char *)&((struct sockaddr_in *)
				    res->ai_addr)->sin_addr;
			(void) fprintf(stderr,
			    _dgettext(TEXT_DOMAIN, "connect to address %s: "),
			    inet_ntop(res->ai_addr->sa_family, addr,
			    abuf, sizeof (abuf)));
			errno = oerrno;
			perror(0);
			res = res->ai_next;
			if (res->ai_addr->sa_family == AF_INET6)
				addr = (char *)&((struct sockaddr_in6 *)
				    res->ai_addr)->sin6_addr;
			else
				addr = (char *)&((struct sockaddr_in *)
				    res->ai_addr)->sin_addr;
			(void) fprintf(stderr,
			    _dgettext(TEXT_DOMAIN, "Trying %s...\n"),
			    inet_ntop(res->ai_addr->sa_family, addr,
			    abuf, sizeof (abuf)));
			continue;
		}
		perror(*ahost);
		freeaddrinfo(resp);
#ifdef SYSV
		/* restore original SIGPIPE handler */
		(void) _sigaction(SIGPIPE, &oldaction,
		    (struct sigaction *)0);

		/* restore original signal mask */
		(void) _sigprocmask(SIG_SETMASK, &oldmask, (sigset_t *)0);
#else
		sigsetmask(oldmask);
#endif /* SYSV */
		return (-1);
	}
	lport = 0;
	if (fd2p == 0) {
		(void) write(s, "", 1);
	} else {
		int s2 = rresvport_af(&lport, res->ai_family), s3;

		len = (socklen_t)sizeof (faddr);

		if (s2 < 0)
			goto bad;
		(void) listen(s2, 1);
		(void) snprintf(aport, MAX_SHORTSTRLEN, "%d", lport);
		if (write(s, aport, strlen(aport)+1) != strlen(aport)+1) {
			perror(_dgettext(TEXT_DOMAIN,
			    "write: setting up stderr"));
			(void) close(s2);
			goto bad;
		}
		FD_ZERO(&fdset);
		FD_SET(s, &fdset);
		FD_SET(s2, &fdset);
		while ((selret = select(FD_SETSIZE, &fdset, (fd_set *)0,
		    (fd_set *)0, (struct timeval *)0)) > 0) {
			if (FD_ISSET(s, &fdset)) {
				/*
				 *	Something's wrong:  we should get no
				 *	data on this connection at this point,
				 *	so we assume that the connection has
				 *	gone away.
				 */
				(void) close(s2);
				goto bad;
			}
			if (FD_ISSET(s2, &fdset)) {
				/*
				 *	We assume this is an incoming connect
				 *	request and proceed normally.
				 */
				s3 = accept(s2, (struct sockaddr *)&faddr,
				    &len);
				FD_CLR(s2, &fdset);
				(void) close(s2);
				if (s3 < 0) {
					perror("accept");
					lport = 0;
					goto bad;
				}
				else
					break;
			}
		}
		if (selret == -1) {
			/*
			 *	This should not happen, and we treat it as
			 *	a fatal error.
			 */
			(void) close(s2);
			goto bad;
		}

		*fd2p = s3;
		switch (faddr.ss_family) {
		case AF_INET:
			sin = (struct sockaddr_in *)&faddr;
			if (ntohs(sin->sin_port) >= IPPORT_RESERVED) {
				(void) fprintf(stderr,
				    _dgettext(TEXT_DOMAIN,
					"socket: protocol failure in circuit "
					"setup.\n"));
				goto bad2;
			}
			break;
		case AF_INET6:
			sin6 = (struct sockaddr_in6 *)&faddr;
			if (ntohs(sin6->sin6_port) >= IPPORT_RESERVED) {
				(void) fprintf(stderr,
				    _dgettext(TEXT_DOMAIN,
					"socket: protocol failure in circuit "
					"setup.\n"));
				goto bad2;
			}
			break;
		default:
			(void) fprintf(stderr,
			    _dgettext(TEXT_DOMAIN,
			    "socket: protocol failure in circuit setup.\n"));
			goto bad2;
		}
	}
	(void) write(s, locuser, strlen(locuser)+1);
	(void) write(s, remuser, strlen(remuser)+1);
	(void) write(s, cmd, strlen(cmd)+1);
	retval = read(s, &c, 1);
	if (retval != 1) {
		if (retval == 0) {
			(void) fprintf(stderr,
			    _dgettext(TEXT_DOMAIN,
			    "Protocol error, %s closed connection\n"),
			    *ahost);
		} else if (retval < 0) {
			perror(*ahost);
		} else {
			(void) fprintf(stderr,
			    _dgettext(TEXT_DOMAIN,
			    "Protocol error, %s sent %d bytes\n"),
			    *ahost, retval);
		}
		goto bad2;
	}
	if (c != 0) {
		while (read(s, &c, 1) == 1) {
			(void) write(2, &c, 1);
			if (c == '\n')
				break;
		}
		goto bad2;
	}
#ifdef SYSV
	/* restore original SIGPIPE handler */
	(void) _sigaction(SIGPIPE, &oldaction, (struct sigaction *)0);

	/* restore original signal mask */
	(void) _sigprocmask(SIG_SETMASK, &oldmask, (sigset_t *)0);
#else
	sigsetmask(oldmask);
#endif /* SYSV */
	freeaddrinfo(resp);
	return (s);
bad2:
	if (lport)
		(void) close(*fd2p);
bad:
	(void) close(s);
#ifdef SYSV
	/* restore original SIGPIPE handler */
	(void) _sigaction(SIGPIPE, &oldaction, (struct sigaction *)0);

	/* restore original signal mask */
	(void) _sigprocmask(SIG_SETMASK, &oldmask, (sigset_t *)0);
#else
	sigsetmask(oldmask);
#endif /* SYSV */
	freeaddrinfo(resp);
	return (-1);
}
Ejemplo n.º 22
0
extern DB *
__hash_open(const char *file, int flags, int mode, const HASHINFO * info,
	    int dflags __unused)
{
	HTAB *hashp;
	struct stat statbuf;
	DB *dbp;
	int bpages, hdrsize, new_table, nsegs, save_errno;

	if ((flags & O_ACCMODE) == O_WRONLY) {
		errno = EINVAL;
		return (NULL);
	}

	if (!(hashp = (HTAB *)calloc(1, sizeof(HTAB))))
		return (NULL);
	hashp->fp = -1;

	/*
	 * Even if user wants write only, we need to be able to read
	 * the actual file, so we need to open it read/write. But, the
	 * field in the hashp structure needs to be accurate so that
	 * we can check accesses.
	 */
	hashp->flags = flags;

	new_table = 0;
	if (!file || (flags & O_TRUNC) ||
	    (stat(file, &statbuf) && (errno == ENOENT))) {
		if (errno == ENOENT)
			errno = 0; /* Just in case someone looks at errno */
		new_table = 1;
	}
	if (file) {
		if ((hashp->fp = _open(file, flags, mode)) == -1)
			RETURN_ERROR(errno, error0);

		/* if the .db file is empty, and we had permission to create
		   a new .db file, then reinitialize the database */
		if ((flags & O_CREAT) &&
		     _fstat(hashp->fp, &statbuf) == 0 && statbuf.st_size == 0)
			new_table = 1;

		_fcntl(hashp->fp, F_SETFD, 1);
	}
	if (new_table) {
		if (!(hashp = init_hash(hashp, file, info)))
			RETURN_ERROR(errno, error1);
	} else {
		/* Table already exists */
		if (info && info->hash)
			hashp->hash = info->hash;
		else
			hashp->hash = __default_hash;

		hdrsize = _read(hashp->fp, &hashp->hdr, sizeof(HASHHDR));
#if BYTE_ORDER == LITTLE_ENDIAN
		swap_header(hashp);
#endif
		if (hdrsize == -1)
			RETURN_ERROR(errno, error1);
		if (hdrsize != sizeof(HASHHDR))
			RETURN_ERROR(EFTYPE, error1);
		/* Verify file type, versions and hash function */
		if (hashp->MAGIC != HASHMAGIC)
			RETURN_ERROR(EFTYPE, error1);
#define	OLDHASHVERSION	1
		if (hashp->VERSION != HASHVERSION &&
		    hashp->VERSION != OLDHASHVERSION)
			RETURN_ERROR(EFTYPE, error1);
		if (hashp->hash(CHARKEY, sizeof(CHARKEY)) != hashp->H_CHARKEY)
			RETURN_ERROR(EFTYPE, error1);
		/*
		 * Figure out how many segments we need.  Max_Bucket is the
		 * maximum bucket number, so the number of buckets is
		 * max_bucket + 1.
		 */
		nsegs = (hashp->MAX_BUCKET + 1 + hashp->SGSIZE - 1) /
			 hashp->SGSIZE;
		hashp->nsegs = 0;
		if (alloc_segs(hashp, nsegs))
			/*
			 * If alloc_segs fails, table will have been destroyed
			 * and errno will have been set.
			 */
			return (NULL);
		/* Read in bitmaps */
		bpages = (hashp->SPARES[hashp->OVFL_POINT] +
		    (hashp->BSIZE << BYTE_SHIFT) - 1) >>
		    (hashp->BSHIFT + BYTE_SHIFT);

		hashp->nmaps = bpages;
		memset(&hashp->mapp[0], 0, bpages * sizeof(u_int32_t *));
	}

	/* Initialize Buffer Manager */
	if (info && info->cachesize)
		__buf_init(hashp, info->cachesize);
	else
		__buf_init(hashp, DEF_BUFSIZE);

	hashp->new_file = new_table;
	hashp->save_file = file && (hashp->flags & O_RDWR);
	hashp->cbucket = -1;
	if (!(dbp = (DB *)malloc(sizeof(DB)))) {
		save_errno = errno;
		hdestroy(hashp);
		errno = save_errno;
		return (NULL);
	}
	dbp->internal = hashp;
	dbp->close = hash_close;
	dbp->del = hash_delete;
	dbp->fd = hash_fd;
	dbp->get = hash_get;
	dbp->put = hash_put;
	dbp->seq = hash_seq;
	dbp->sync = hash_sync;
	dbp->type = DB_HASH;

#ifdef DEBUG
	fprintf(stderr,
"%s\n%s%p\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%x\n%s%x\n%s%d\n%s%d\n",
	    "init_htab:",
	    "TABLE POINTER   ", hashp,
	    "BUCKET SIZE     ", hashp->BSIZE,
	    "BUCKET SHIFT    ", hashp->BSHIFT,
	    "DIRECTORY SIZE  ", hashp->DSIZE,
	    "SEGMENT SIZE    ", hashp->SGSIZE,
	    "SEGMENT SHIFT   ", hashp->SSHIFT,
	    "FILL FACTOR     ", hashp->FFACTOR,
	    "MAX BUCKET      ", hashp->MAX_BUCKET,
	    "OVFL POINT	     ", hashp->OVFL_POINT,
	    "LAST FREED      ", hashp->LAST_FREED,
	    "HIGH MASK       ", hashp->HIGH_MASK,
	    "LOW  MASK       ", hashp->LOW_MASK,
	    "NSEGS           ", hashp->nsegs,
	    "NKEYS           ", hashp->NKEYS);
#endif
#ifdef HASH_STATISTICS
	hash_overflows = hash_accesses = hash_collisions = hash_expansions = 0;
#endif
	return (dbp);

error1:
	if (hashp != NULL)
		_close(hashp->fp);

error0:
	free(hashp);
	errno = save_errno;
	return (NULL);
}
Ejemplo n.º 23
0
/*
 * __BT_OPEN -- Open a btree.
 *
 * Creates and fills a DB struct, and calls the routine that actually
 * opens the btree.
 *
 * Parameters:
 *	fname:	filename (NULL for in-memory trees)
 *	flags:	open flag bits
 *	mode:	open permission bits
 *	b:	BTREEINFO pointer
 *
 * Returns:
 *	NULL on failure, pointer to DB on success.
 *
 */
DB *
__bt_open(const char *fname, int flags, mode_t mode, const BTREEINFO *openinfo,
	  int dflags)
{
	struct stat sb;
	BTMETA m;
	BTREE *t;
	BTREEINFO b;
	DB *dbp;
	pgno_t ncache;
	ssize_t nr;
	int machine_lorder, saved_errno;

	t = NULL;

	/*
	 * Intention is to make sure all of the user's selections are okay
	 * here and then use them without checking.  Can't be complete, since
	 * we don't know the right page size, lorder or flags until the backing
	 * file is opened.  Also, the file's page size can cause the cachesize
	 * to change.
	 */
	machine_lorder = byteorder();
	if (openinfo) {
		b = *openinfo;

		/* Flags: R_DUP. */
		if (b.flags & ~(R_DUP))
			goto einval;

		/*
		 * Page size must be indx_t aligned and >= MINPSIZE.  Default
		 * page size is set farther on, based on the underlying file
		 * transfer size.
		 */
		if (b.psize &&
		    (b.psize < MINPSIZE || b.psize > MAX_PAGE_OFFSET + 1 ||
		    b.psize & (sizeof(indx_t) - 1) ))
			goto einval;

		/* Minimum number of keys per page; absolute minimum is 2. */
		if (b.minkeypage) {
			if (b.minkeypage < 2)
				goto einval;
		} else
			b.minkeypage = DEFMINKEYPAGE;

		/* If no comparison, use default comparison and prefix. */
		if (b.compare == NULL) {
			b.compare = __bt_defcmp;
			if (b.prefix == NULL)
				b.prefix = __bt_defpfx;
		}

		if (b.lorder == 0)
			b.lorder = machine_lorder;
	} else {
		b.compare = __bt_defcmp;
		b.cachesize = 0;
		b.flags = 0;
		b.lorder = machine_lorder;
		b.minkeypage = DEFMINKEYPAGE;
		b.prefix = __bt_defpfx;
		b.psize = 0;
	}

	/* Check for the ubiquitous PDP-11. */
	if (b.lorder != BIG_ENDIAN && b.lorder != LITTLE_ENDIAN)
		goto einval;

	/* Allocate and initialize DB and BTREE structures. */
	if ((t = (BTREE *)calloc(1, sizeof(BTREE))) == NULL)
		goto err;
	t->bt_fd = -1;			/* Don't close unopened fd on error. */
	t->bt_lorder = b.lorder;
	t->bt_order = NOT;
	t->bt_cmp = b.compare;
	t->bt_pfx = b.prefix;
	t->bt_rfd = -1;

	if ((t->bt_dbp = dbp = (DB *)calloc(1, sizeof(DB))) == NULL)
		goto err;
	if (t->bt_lorder != machine_lorder)
		F_SET(t, B_NEEDSWAP);

	dbp->type = DB_BTREE;
	dbp->internal = t;
	dbp->close = __bt_close;
	dbp->del = __bt_delete;
	dbp->fd = __bt_fd;
	dbp->get = __bt_get;
	dbp->put = __bt_put;
	dbp->seq = __bt_seq;
	dbp->sync = __bt_sync;

	/*
	 * If no file name was supplied, this is an in-memory btree and we
	 * open a backing temporary file.  Otherwise, it's a disk-based tree.
	 */
	if (fname) {
		switch (flags & O_ACCMODE) {
		case O_RDONLY:
			F_SET(t, B_RDONLY);
			break;
		case O_RDWR:
			break;
		case O_WRONLY:
		default:
			goto einval;
		}

		if ((t->bt_fd = _open(fname, flags, mode)) < 0)
			goto err;

	} else {
		if ((flags & O_ACCMODE) != O_RDWR)
			goto einval;
		if ((t->bt_fd = tmp()) == -1)
			goto err;
		F_SET(t, B_INMEM);
	}

	if (_fcntl(t->bt_fd, F_SETFD, 1) == -1)
		goto err;

	if (_fstat(t->bt_fd, &sb))
		goto err;
	if (sb.st_size) {
		if ((nr = _read(t->bt_fd, &m, sizeof(BTMETA))) < 0)
			goto err;
		if (nr != sizeof(BTMETA))
			goto eftype;

		/*
		 * Read in the meta-data.  This can change the notion of what
		 * the lorder, page size and flags are, and, when the page size
		 * changes, the cachesize value can change too.  If the user
		 * specified the wrong byte order for an existing database, we
		 * don't bother to return an error, we just clear the NEEDSWAP
		 * bit.
		 */
		if (m.magic == BTREEMAGIC)
			F_CLR(t, B_NEEDSWAP);
		else {
			F_SET(t, B_NEEDSWAP);
			M_32_SWAP(m.magic);
			M_32_SWAP(m.version);
			M_32_SWAP(m.psize);
			M_32_SWAP(m.free);
			M_32_SWAP(m.nrecs);
			M_32_SWAP(m.flags);
		}
		if (m.magic != BTREEMAGIC || m.version != BTREEVERSION)
			goto eftype;
		if (m.psize < MINPSIZE || m.psize > MAX_PAGE_OFFSET + 1 ||
		    m.psize & (sizeof(indx_t) - 1) )
			goto eftype;
		if (m.flags & ~SAVEMETA)
			goto eftype;
		b.psize = m.psize;
		F_SET(t, m.flags);
		t->bt_free = m.free;
		t->bt_nrecs = m.nrecs;
	} else {
		/*
		 * Set the page size to the best value for I/O to this file.
		 * Don't overflow the page offset type.
		 */
		if (b.psize == 0) {
			b.psize = sb.st_blksize;
			if (b.psize < MINPSIZE)
				b.psize = MINPSIZE;
			if (b.psize > MAX_PAGE_OFFSET + 1)
				b.psize = MAX_PAGE_OFFSET + 1;
		}

		/* Set flag if duplicates permitted. */
		if (!(b.flags & R_DUP))
			F_SET(t, B_NODUPS);

		t->bt_free = P_INVALID;
		t->bt_nrecs = 0;
		F_SET(t, B_METADIRTY);
	}

	t->bt_psize = b.psize;

	/* Set the cache size; must be a multiple of the page size. */
	if (b.cachesize && b.cachesize & (b.psize - 1) )
		b.cachesize += (~b.cachesize & (b.psize - 1) ) + 1;
	if (b.cachesize < b.psize * MINCACHE)
		b.cachesize = b.psize * MINCACHE;

	/* Calculate number of pages to cache. */
	ncache = (b.cachesize + t->bt_psize - 1) / t->bt_psize;

	/*
	 * The btree data structure requires that at least two keys can fit on
	 * a page, but other than that there's no fixed requirement.  The user
	 * specified a minimum number per page, and we translated that into the
	 * number of bytes a key/data pair can use before being placed on an
	 * overflow page.  This calculation includes the page header, the size
	 * of the index referencing the leaf item and the size of the leaf item
	 * structure.  Also, don't let the user specify a minkeypage such that
	 * a key/data pair won't fit even if both key and data are on overflow
	 * pages.
	 */
	t->bt_ovflsize = (t->bt_psize - BTDATAOFF) / b.minkeypage -
	    (sizeof(indx_t) + NBLEAFDBT(0, 0));
	if (t->bt_ovflsize < NBLEAFDBT(NOVFLSIZE, NOVFLSIZE) + sizeof(indx_t))
		t->bt_ovflsize =
		    NBLEAFDBT(NOVFLSIZE, NOVFLSIZE) + sizeof(indx_t);

	/* Initialize the buffer pool. */
	if ((t->bt_mp =
	    mpool_open(NULL, t->bt_fd, t->bt_psize, ncache)) == NULL)
		goto err;
	if (!F_ISSET(t, B_INMEM))
		mpool_filter(t->bt_mp, __bt_pgin, __bt_pgout, t);

	/* Create a root page if new tree. */
	if (nroot(t) == RET_ERROR)
		goto err;

	/* Global flags. */
	if (dflags & DB_LOCK)
		F_SET(t, B_DB_LOCK);
	if (dflags & DB_SHMEM)
		F_SET(t, B_DB_SHMEM);
	if (dflags & DB_TXN)
		F_SET(t, B_DB_TXN);

	return (dbp);

einval:	errno = EINVAL;
	goto err;

eftype:	errno = EFTYPE;
	goto err;

err:	saved_errno = errno;
	if (t) {
		if (t->bt_dbp)
			free(t->bt_dbp);
		if (t->bt_fd != -1)
			_close(t->bt_fd);
		free(t);
	}
	errno = saved_errno;
	return (NULL);
}