diff options
Diffstat (limited to 'lib/libc')
| -rw-r--r-- | lib/libc/gen/disklabel.c | 3 | ||||
| -rw-r--r-- | lib/libc/gen/fts-compat.c | 30 | ||||
| -rw-r--r-- | lib/libc/gen/fts.c | 30 | ||||
| -rw-r--r-- | lib/libc/gen/getgrouplist.c | 18 | ||||
| -rw-r--r-- | lib/libc/gen/getnetgrent.c | 10 | ||||
| -rw-r--r-- | lib/libc/gen/getpwent.c | 27 | ||||
| -rw-r--r-- | lib/libc/gen/opendir.c | 233 | ||||
| -rw-r--r-- | lib/libc/gen/popen.c | 49 | ||||
| -rw-r--r-- | lib/libc/gen/syslog.c | 4 | 
9 files changed, 312 insertions, 92 deletions
diff --git a/lib/libc/gen/disklabel.c b/lib/libc/gen/disklabel.c index ac2894e3bd07..b5cef891d11d 100644 --- a/lib/libc/gen/disklabel.c +++ b/lib/libc/gen/disklabel.c @@ -36,12 +36,13 @@  static char sccsid[] = "@(#)disklabel.c	8.2 (Berkeley) 5/3/95";  #endif  static const char rcsid[] = -	"$Id$"; +	"$Id: disklabel.c,v 1.5 1997/02/22 14:58:01 peter Exp $";  #endif /* not lint */  #include <sys/param.h>  #define DKTYPENAMES  #include <sys/disklabel.h> +#include <ufs/ufs/dinode.h>  #include <ufs/ffs/fs.h>  #include <errno.h> diff --git a/lib/libc/gen/fts-compat.c b/lib/libc/gen/fts-compat.c index 8de23dfaa4f2..e53270725c60 100644 --- a/lib/libc/gen/fts-compat.c +++ b/lib/libc/gen/fts-compat.c @@ -32,7 +32,7 @@   */  #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)fts.c	8.4 (Berkeley) 4/16/94"; +static char sccsid[] = "@(#)fts.c	8.6 (Berkeley) 8/14/94";  #endif /* LIBC_SCCS and not lint */  #include <sys/param.h> @@ -556,7 +556,7 @@ fts_build(sp, type)  	FTSENT *cur, *tail;  	DIR *dirp;  	void *adjaddr; -	int cderrno, descend, len, level, maxlen, nlinks, saved_errno; +	int cderrno, descend, len, level, maxlen, nlinks, oflag, saved_errno;  	char *cp;  	/* Set current node pointer. */ @@ -566,7 +566,15 @@ fts_build(sp, type)  	 * Open the directory for reading.  If this fails, we're done.  	 * If being called from fts_read, set the fts_info field.  	 */ -	if ((dirp = opendir(cur->fts_accpath)) == NULL) { +#ifdef FTS_WHITEOUT +	if (ISSET(FTS_WHITEOUT)) +		oflag = DTF_NODUP|DTF_REWIND; +	else +		oflag = DTF_HIDEW|DTF_NODUP|DTF_REWIND; +#else +#define __opendir2(path, flag) opendir(path) +#endif +	if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) {  		if (type == BREAD) {  			cur->fts_info = FTS_DNR;  			cur->fts_errno = errno; @@ -671,6 +679,11 @@ mem1:				saved_errno = errno;  		p->fts_parent = sp->fts_cur;  		p->fts_level = level; +#ifdef FTS_WHITEOUT +		if (dp->d_type == DT_WHT) +			p->fts_flags |= FTS_ISW; +#endif +  		if (cderrno) {  			if (nlinks) {  				p->fts_info = FTS_NS; @@ -775,6 +788,17 @@ fts_stat(sp, p, follow)  	/* If user needs stat info, stat buffer already allocated. */  	sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp; +#ifdef FTS_WHITEOUT +	/* check for whiteout */ +	if (p->fts_flags & FTS_ISW) { +		if (sbp != &sb) { +			memset(sbp, '\0', sizeof (*sbp)); +			sbp->st_mode = S_IFWHT; +		} +		return (FTS_W); +	} +#endif +  	/*  	 * If doing a logical walk, or application requested FTS_FOLLOW, do  	 * a stat(2).  If that fails, check for a non-existent symlink.  If diff --git a/lib/libc/gen/fts.c b/lib/libc/gen/fts.c index 8de23dfaa4f2..e53270725c60 100644 --- a/lib/libc/gen/fts.c +++ b/lib/libc/gen/fts.c @@ -32,7 +32,7 @@   */  #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)fts.c	8.4 (Berkeley) 4/16/94"; +static char sccsid[] = "@(#)fts.c	8.6 (Berkeley) 8/14/94";  #endif /* LIBC_SCCS and not lint */  #include <sys/param.h> @@ -556,7 +556,7 @@ fts_build(sp, type)  	FTSENT *cur, *tail;  	DIR *dirp;  	void *adjaddr; -	int cderrno, descend, len, level, maxlen, nlinks, saved_errno; +	int cderrno, descend, len, level, maxlen, nlinks, oflag, saved_errno;  	char *cp;  	/* Set current node pointer. */ @@ -566,7 +566,15 @@ fts_build(sp, type)  	 * Open the directory for reading.  If this fails, we're done.  	 * If being called from fts_read, set the fts_info field.  	 */ -	if ((dirp = opendir(cur->fts_accpath)) == NULL) { +#ifdef FTS_WHITEOUT +	if (ISSET(FTS_WHITEOUT)) +		oflag = DTF_NODUP|DTF_REWIND; +	else +		oflag = DTF_HIDEW|DTF_NODUP|DTF_REWIND; +#else +#define __opendir2(path, flag) opendir(path) +#endif +	if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) {  		if (type == BREAD) {  			cur->fts_info = FTS_DNR;  			cur->fts_errno = errno; @@ -671,6 +679,11 @@ mem1:				saved_errno = errno;  		p->fts_parent = sp->fts_cur;  		p->fts_level = level; +#ifdef FTS_WHITEOUT +		if (dp->d_type == DT_WHT) +			p->fts_flags |= FTS_ISW; +#endif +  		if (cderrno) {  			if (nlinks) {  				p->fts_info = FTS_NS; @@ -775,6 +788,17 @@ fts_stat(sp, p, follow)  	/* If user needs stat info, stat buffer already allocated. */  	sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp; +#ifdef FTS_WHITEOUT +	/* check for whiteout */ +	if (p->fts_flags & FTS_ISW) { +		if (sbp != &sb) { +			memset(sbp, '\0', sizeof (*sbp)); +			sbp->st_mode = S_IFWHT; +		} +		return (FTS_W); +	} +#endif +  	/*  	 * If doing a logical walk, or application requested FTS_FOLLOW, do  	 * a stat(2).  If that fails, check for a non-existent symlink.  If diff --git a/lib/libc/gen/getgrouplist.c b/lib/libc/gen/getgrouplist.c index 702828e67a2e..1c2e42de545d 100644 --- a/lib/libc/gen/getgrouplist.c +++ b/lib/libc/gen/getgrouplist.c @@ -32,7 +32,7 @@   */  #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getgrouplist.c	8.1 (Berkeley) 6/4/93"; +static char sccsid[] = "@(#)getgrouplist.c	8.2 (Berkeley) 12/8/94";  #endif /* LIBC_SCCS and not lint */  /* @@ -68,17 +68,15 @@ getgrouplist(uname, agroup, groups, grpcnt)  	 * Scan the group file to find additional groups.  	 */  	setgrent(); -	while ( (grp = getgrent()) ) { -		for (i = 0; i < ngroups; i++) { -			if (grp->gr_gid == groups[i]) -				goto skip; -		} -		if (ngroups >= maxgroups) { -			ret = -1; -			break; -		} +	while (grp = getgrent()) { +		if (grp->gr_gid == agroup) +			continue;  		for (i = 0; grp->gr_mem[i]; i++) {  			if (!strcmp(grp->gr_mem[i], uname)) { +				if (ngroups >= maxgroups) { +					ret = -1; +					break; +				}  				groups[ngroups++] = grp->gr_gid;  				break;  			} diff --git a/lib/libc/gen/getnetgrent.c b/lib/libc/gen/getnetgrent.c index 46cc76462c92..662958aebc04 100644 --- a/lib/libc/gen/getnetgrent.c +++ b/lib/libc/gen/getnetgrent.c @@ -35,7 +35,7 @@   */  #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getnetgrent.c	8.1 (Berkeley) 6/4/93"; +static char sccsid[] = "@(#)getnetgrent.c	8.2 (Berkeley) 4/27/95";  #endif /* LIBC_SCCS and not lint */  #include <stdio.h> @@ -483,10 +483,10 @@ parse_netgrp(group)  			if (parse_netgrp(spos))  				continue;  		} -		/* Watch for null pointer dereferences, dammit! */ -		if (pos != NULL) -			while (*pos == ' ' || *pos == ',' || *pos == '\t') -				pos++; +		if (pos == NULL) +			break; +		while (*pos == ' ' || *pos == ',' || *pos == '\t') +			pos++;  	}  	return (0);  } diff --git a/lib/libc/gen/getpwent.c b/lib/libc/gen/getpwent.c index 66ed5c062d44..3cd9fdc09872 100644 --- a/lib/libc/gen/getpwent.c +++ b/lib/libc/gen/getpwent.c @@ -32,7 +32,7 @@   */  #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getpwent.c	8.1 (Berkeley) 6/4/93"; +static char sccsid[] = "@(#)getpwent.c	8.2 (Berkeley) 4/27/95";  #endif /* LIBC_SCCS and not lint */  #include <stdio.h> @@ -53,6 +53,11 @@ extern void setnetgrent __P(( char * ));  extern int getnetgrent __P(( char **, char **, char ** ));  extern int innetgr __P(( const char *, const char *, const char *, const char * )); +/* + * The lookup techniques and data extraction code here must be kept + * in sync with that in `pwd_mkdb'. + */ +  static struct passwd _pw_passwd;	/* password structure */  static DB *_pw_db;			/* password database */  static int _pw_keynum;			/* key counter */ @@ -162,12 +167,8 @@ getpwnam(name)  }  struct passwd * -#ifdef __STDC__ -getpwuid(uid_t uid) -#else  getpwuid(uid) -	int uid; -#endif +	uid_t uid;  {  	DBT key;  	int keyuid, rval; @@ -295,22 +296,20 @@ __hashpw(key)  	if (data.size > max && !(line = realloc(line, max += 1024)))  		return(0); +	/* THIS CODE MUST MATCH THAT IN pwd_mkdb. */  	t = line;  #define	EXPAND(e)	e = t; while ( (*t++ = *p++) ); +#define	SCALAR(v)	memmove(&(v), p, sizeof v); p += sizeof v  	EXPAND(_pw_passwd.pw_name);  	EXPAND(_pw_passwd.pw_passwd); -	bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int)); -	p += sizeof(int); -	bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int)); -	p += sizeof(int); -	bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t)); -	p += sizeof(time_t); +	SCALAR(_pw_passwd.pw_uid); +	SCALAR(_pw_passwd.pw_gid); +	SCALAR(_pw_passwd.pw_change);  	EXPAND(_pw_passwd.pw_class);  	EXPAND(_pw_passwd.pw_gecos);  	EXPAND(_pw_passwd.pw_dir);  	EXPAND(_pw_passwd.pw_shell); -	bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t)); -	p += sizeof(time_t); +	SCALAR(_pw_passwd.pw_expire);  	bcopy(p, (char *)&_pw_passwd.pw_fields, sizeof _pw_passwd.pw_fields);  	p += sizeof _pw_passwd.pw_fields;  	return(1); diff --git a/lib/libc/gen/opendir.c b/lib/libc/gen/opendir.c index a3db45b18d77..8c6afc6083c6 100644 --- a/lib/libc/gen/opendir.c +++ b/lib/libc/gen/opendir.c @@ -32,11 +32,12 @@   */  #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)opendir.c	8.2 (Berkeley) 2/12/94"; +static char sccsid[] = "@(#)opendir.c	8.8 (Berkeley) 5/1/95";  #endif /* LIBC_SCCS and not lint */  #include <sys/param.h>  #include <sys/stat.h> +#include <sys/mount.h>  #include <dirent.h>  #include <errno.h> @@ -45,62 +46,228 @@ static char sccsid[] = "@(#)opendir.c	8.2 (Berkeley) 2/12/94";  #include <unistd.h>  /* - * open a directory. + * Open a directory.   */  DIR *  opendir(name)  	const char *name;  { -	register DIR *dirp; -	register int fd; -	int saved_errno; -	struct stat sb; +	return (__opendir2(name, DTF_HIDEW|DTF_NODUP)); +} + +DIR * +__opendir2(name, flags) +	const char *name; +	int flags; +{ +	DIR *dirp; +	int fd; +	int incr; +	int unionstack; +	struct stat statb;  	/*  	 * stat() before open() because opening of special files may be  	 * harmful.  fstat() after open because the file may have changed.  	 */ -	if (stat(name, &sb) != 0) +	if (stat(name, &statb) != 0)  		return NULL; -	if (!S_ISDIR(sb.st_mode)) { +	if (!S_ISDIR(statb.st_mode)) {  		errno = ENOTDIR;  		return NULL;  	}  	if ((fd = open(name, O_RDONLY | O_NONBLOCK)) == -1) -		return NULL; -	dirp = NULL; -	if (fstat(fd, &sb) != 0) -		goto fail; -	if (!S_ISDIR(sb.st_mode)) { +		return (NULL); +	if (fstat(fd, &statb) || !S_ISDIR(statb.st_mode)) {  		errno = ENOTDIR; -		goto fail; +		close(fd); +		return (NULL);  	}  	if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1 || -	    (dirp = malloc(sizeof(DIR))) == NULL) -		goto fail; +	    (dirp = (DIR *)malloc(sizeof(DIR))) == NULL) { +		close(fd); +		return (NULL); +	} +  	/*  	 * Use the system page size if that is a multiple of DIRBLKSIZ -	 * this could speed things up in some cases we hope +	 * this could speed things up in some cases. +	 * Hopefully this can be a big win someday by allowing page +	 * trades to user space to be done by getdirentries().  	 */ -	dirp->dd_len = getpagesize(); -	if ((dirp->dd_len % DIRBLKSIZ) != 0)  -		dirp->dd_len = DIRBLKSIZ; -	dirp->dd_buf = malloc(dirp->dd_len); -	if (dirp->dd_buf == NULL) -		goto fail; -	dirp->dd_fd = fd; +	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) { +			free(dirp); +			close(fd); +			return (NULL); +		} +		unionstack = !strcmp(sfb.f_fstypename, "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 = realloc(buf, len); +				if (buf == NULL) { +					free(dirp); +					close(fd); +					return (NULL); +				} +				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)) == -1) { +				free(buf); +				free(dirp); +				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 ((int)dp & 03) +					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), alphasort); + +				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_buf = malloc(dirp->dd_len); +		if (dirp->dd_buf == NULL) { +			free(dirp); +			close (fd); +			return (NULL); +		} +		dirp->dd_seek = 0; +		flags &= ~DTF_REWIND; +	} +  	dirp->dd_loc = 0; -	dirp->dd_seek = 0; +	dirp->dd_fd = fd; +	dirp->dd_flags = flags; +  	/*  	 * Set up seek point for rewinddir.  	 */  	dirp->dd_rewind = telldir(dirp); -	return dirp; - -fail: -	saved_errno = errno; -	free(dirp); -	close(fd); -	errno = saved_errno; -	return NULL; + +	return (dirp);  } diff --git a/lib/libc/gen/popen.c b/lib/libc/gen/popen.c index 0d280461c1fb..ae809f5230e2 100644 --- a/lib/libc/gen/popen.c +++ b/lib/libc/gen/popen.c @@ -35,11 +35,12 @@   */  #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)popen.c	8.1 (Berkeley) 6/4/93"; +static char sccsid[] = "@(#)popen.c	8.3 (Berkeley) 5/3/95";  #endif /* LIBC_SCCS and not lint */  #include <sys/param.h>  #include <sys/wait.h> +#include <sys/socket.h>  #include <signal.h>  #include <errno.h> @@ -56,25 +57,31 @@ static struct pid {  } *pidlist;  FILE * -popen(program, type) -	const char *program; -	const char *type; +popen(command, type) +	const char *command, *type;  {  	struct pid *cur;  	FILE *iop; -	int pdes[2], pid; - -	if ( (*type != 'r' && *type != 'w') || type[1]) +	int pdes[2], pid, twoway; + +	/* +	 * Lite2 introduced two-way popen() pipes using socketpair(). +	 * FreeBSD's pipe() is bidirectional, so we use that. +	 */ +	if (strchr(type, '+')) { +		twoway = 1; +		type = "r+"; +	} else  { +		twoway = 0; +		if (*type != 'r' && *type != 'w' || type[1]) +			return (NULL); +	} +	if (pipe(pdes) < 0)  		return (NULL);  	if ((cur = malloc(sizeof(struct pid))) == NULL)  		return (NULL); -	if (pipe(pdes) < 0) { -		free(cur); -		return (NULL); -	} -  	switch (pid = vfork()) {  	case -1:			/* Error. */  		(void)close(pdes[0]); @@ -87,8 +94,11 @@ popen(program, type)  			if (pdes[1] != STDOUT_FILENO) {  				(void)dup2(pdes[1], STDOUT_FILENO);  				(void)close(pdes[1]); +				pdes[1] = STDOUT_FILENO;  			}  			(void) close(pdes[0]); +			if (twoway && (pdes[1] != STDIN_FILENO)) +				(void)dup2(pdes[1], STDIN_FILENO);  		} else {  			if (pdes[0] != STDIN_FILENO) {  				(void)dup2(pdes[0], STDIN_FILENO); @@ -96,7 +106,7 @@ popen(program, type)  			}  			(void)close(pdes[1]);  		} -		execl(_PATH_BSHELL, "sh", "-c", program, NULL); +		execl(_PATH_BSHELL, "sh", "-c", command, NULL);  		_exit(127);  		/* NOTREACHED */  	} @@ -130,11 +140,9 @@ pclose(iop)  {  	register struct pid *cur, *last;  	int omask; -	union wait pstat; +	int pstat;  	pid_t pid; -	(void)fclose(iop); -  	/* Find the appropriate file pointer. */  	for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)  		if (cur->fp == iop) @@ -142,12 +150,11 @@ pclose(iop)  	if (cur == NULL)  		return (-1); -	/* Get the status of the process. */ -	omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); +	(void)fclose(iop); +  	do { -		pid = waitpid(cur->pid, (int *) &pstat, 0); +		pid = waitpid(cur->pid, &pstat, 0);  	} while (pid == -1 && errno == EINTR); -	(void)sigsetmask(omask);  	/* Remove the entry from the linked list. */  	if (last == NULL) @@ -156,5 +163,5 @@ pclose(iop)  		last->next = cur->next;  	free(cur); -	return (pid == -1 ? -1 : pstat.w_status); +	return (pid == -1 ? -1 : pstat);  } diff --git a/lib/libc/gen/syslog.c b/lib/libc/gen/syslog.c index 0f3817ccbd7e..b1160c4574e8 100644 --- a/lib/libc/gen/syslog.c +++ b/lib/libc/gen/syslog.c @@ -33,10 +33,10 @@  #if defined(LIBC_SCCS) && !defined(lint)  /* -static char sccsid[] = "From: @(#)syslog.c	8.4 (Berkeley) 3/18/94"; +static char sccsid[] = "@(#)syslog.c	8.5 (Berkeley) 4/29/95";  */  static const char rcsid[] = -  "$Id$"; +  "$Id: syslog.c,v 1.11 1997/02/22 14:58:18 peter Exp $";  #endif /* LIBC_SCCS and not lint */  #include <sys/types.h>  | 
