diff --git a/include/fnmatch.h b/include/fnmatch.h new file mode 100644 index 000000000..fd2131347 --- /dev/null +++ b/include/fnmatch.h @@ -0,0 +1,53 @@ +/* $OpenBSD: fnmatch.h,v 1.8 2005/12/13 00:35:22 millert Exp $ */ +/* $NetBSD: fnmatch.h,v 1.5 1994/10/26 00:55:53 cgd Exp $ */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)fnmatch.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _FNMATCH_H_ +#define _FNMATCH_H_ + +#define FNM_NOMATCH 1 /* Match failed. */ +#define FNM_NOSYS 2 /* Function not supported (unused). */ + +#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */ +#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */ +#define FNM_PERIOD 0x04 /* Period must be matched by period. */ + +#define FNM_LEADING_DIR 0x08 /* Ignore / after Imatch. */ +#define FNM_CASEFOLD 0x10 /* Case insensitive search. */ +#define FNM_IGNORECASE FNM_CASEFOLD +#define FNM_FILE_NAME FNM_PATHNAME + + +int fnmatch(const char *, const char *, int); + +#endif /* !_FNMATCH_H_ */ diff --git a/include/unistd.h b/include/unistd.h index e7c8bd682..c353472c2 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -133,6 +133,7 @@ _PROTOTYPE( long pathconf, (const char *_path, int _name) ); _PROTOTYPE( int pause, (void) ); _PROTOTYPE( int pipe, (int _fildes[2]) ); _PROTOTYPE( ssize_t read, (int _fd, void *_buf, size_t _n) ); +_PROTOTYPE( ssize_t pread, (int, void *, size_t, off_t) ); _PROTOTYPE( int rmdir, (const char *_path) ); _PROTOTYPE( int setgid, (_mnx_Gid_t _gid) ); _PROTOTYPE( int setegid, (_mnx_Gid_t _gid) ); diff --git a/lib/libc/posix/Makefile.inc b/lib/libc/posix/Makefile.inc index 52d761d52..dd7912d60 100644 --- a/lib/libc/posix/Makefile.inc +++ b/lib/libc/posix/Makefile.inc @@ -98,10 +98,12 @@ SRCS+= \ _wait.c \ _waitpid.c \ _write.c \ + fnmatch.c \ getloadavg.c \ getopt.c \ gettimeofday.c \ glob.c \ nice.c \ priority.c \ + pread.c \ usleep.c diff --git a/lib/libc/posix/charclass.h b/lib/libc/posix/charclass.h new file mode 100644 index 000000000..c780f1658 --- /dev/null +++ b/lib/libc/posix/charclass.h @@ -0,0 +1,31 @@ +/* + * Public domain, 2008, Todd C. Miller + * + * $OpenBSD: charclass.h,v 1.1 2008/10/01 23:04:13 millert Exp $ + */ + +/* + * POSIX character class support for fnmatch() and glob(). + */ +static struct cclass { + const char *name; + int (*isctype)(int); +} cclasses[] = { + { "alnum", isalnum }, + { "alpha", isalpha }, +#ifndef _MINIX + { "blank", isblank }, +#endif + { "cntrl", iscntrl }, + { "digit", isdigit }, + { "graph", isgraph }, + { "lower", islower }, + { "print", isprint }, + { "punct", ispunct }, + { "space", isspace }, + { "upper", isupper }, + { "xdigit", isxdigit }, + { NULL, NULL } +}; + +#define NCCLASSES (sizeof(cclasses) / sizeof(cclasses[0]) - 1) diff --git a/lib/libc/posix/fnmatch.c b/lib/libc/posix/fnmatch.c new file mode 100644 index 000000000..2388f8263 --- /dev/null +++ b/lib/libc/posix/fnmatch.c @@ -0,0 +1,251 @@ +/* $OpenBSD: fnmatch.c,v 1.14 2008/10/01 23:04:13 millert Exp $ */ + +/* + * Copyright (c) 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Guido van Rossum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6. + * Compares a filename or pathname to a pattern. + */ + +#include +#include +#include +#include + +#include "charclass.h" + +#define EOS '\0' + +#define RANGE_MATCH 1 +#define RANGE_NOMATCH 0 +#define RANGE_ERROR (-1) + +static int rangematch(const char *, char, int, char **); +static int classmatch(const char *, char, int, const char **); + +int +fnmatch(const char *pattern, const char *string, int flags) +{ + const char *stringstart; + char *newp; + char c, test; + + for (stringstart = string;;) + switch (c = *pattern++) { + case EOS: + if ((flags & FNM_LEADING_DIR) && *string == '/') + return (0); + return (*string == EOS ? 0 : FNM_NOMATCH); + case '?': + if (*string == EOS) + return (FNM_NOMATCH); + if (*string == '/' && (flags & FNM_PATHNAME)) + return (FNM_NOMATCH); + if (*string == '.' && (flags & FNM_PERIOD) && + (string == stringstart || + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) + return (FNM_NOMATCH); + ++string; + break; + case '*': + c = *pattern; + /* Collapse multiple stars. */ + while (c == '*') + c = *++pattern; + + if (*string == '.' && (flags & FNM_PERIOD) && + (string == stringstart || + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) + return (FNM_NOMATCH); + + /* Optimize for pattern with * at end or before /. */ + if (c == EOS) { + if (flags & FNM_PATHNAME) + return ((flags & FNM_LEADING_DIR) || + strchr(string, '/') == NULL ? + 0 : FNM_NOMATCH); + else + return (0); + } else if (c == '/' && (flags & FNM_PATHNAME)) { + if ((string = strchr(string, '/')) == NULL) + return (FNM_NOMATCH); + break; + } + + /* General case, use recursion. */ + while ((test = *string) != EOS) { + if (!fnmatch(pattern, string, flags & ~FNM_PERIOD)) + return (0); + if (test == '/' && (flags & FNM_PATHNAME)) + break; + ++string; + } + return (FNM_NOMATCH); + case '[': + if (*string == EOS) + return (FNM_NOMATCH); + if (*string == '/' && (flags & FNM_PATHNAME)) + return (FNM_NOMATCH); + if (*string == '.' && (flags & FNM_PERIOD) && + (string == stringstart || + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) + return (FNM_NOMATCH); + + switch (rangematch(pattern, *string, flags, &newp)) { + case RANGE_ERROR: + /* not a good range, treat as normal text */ + goto normal; + case RANGE_MATCH: + pattern = newp; + break; + case RANGE_NOMATCH: + return (FNM_NOMATCH); + } + ++string; + break; + case '\\': + if (!(flags & FNM_NOESCAPE)) { + if ((c = *pattern++) == EOS) { + c = '\\'; + --pattern; + } + } + /* FALLTHROUGH */ + default: + normal: + if (c != *string && !((flags & FNM_CASEFOLD) && + (tolower((unsigned char)c) == + tolower((unsigned char)*string)))) + return (FNM_NOMATCH); + ++string; + break; + } + /* NOTREACHED */ +} + +static int +rangematch(const char *pattern, char test, int flags, char **newp) +{ + int negate, ok, rv; + char c, c2; + + /* + * A bracket expression starting with an unquoted circumflex + * character produces unspecified results (IEEE 1003.2-1992, + * 3.13.2). This implementation treats it like '!', for + * consistency with the regular expression syntax. + * J.T. Conklin (conklin@ngai.kaleida.com) + */ + if ((negate = (*pattern == '!' || *pattern == '^'))) + ++pattern; + + if (flags & FNM_CASEFOLD) + test = (char)tolower((unsigned char)test); + + /* + * A right bracket shall lose its special meaning and represent + * itself in a bracket expression if it occurs first in the list. + * -- POSIX.2 2.8.3.2 + */ + ok = 0; + c = *pattern++; + do { + if (c == '[' && *pattern == ':') { + do { + rv = classmatch(pattern + 1, test, + (flags & FNM_CASEFOLD), &pattern); + if (rv == RANGE_MATCH) + ok = 1; + c = *pattern++; + } while (rv != RANGE_ERROR && c == '[' && *pattern == ':'); + if (c == ']') + break; + } + if (c == '\\' && !(flags & FNM_NOESCAPE)) + c = *pattern++; + if (c == EOS) + return (RANGE_ERROR); + if (c == '/' && (flags & FNM_PATHNAME)) + return (RANGE_NOMATCH); + if ((flags & FNM_CASEFOLD)) + c = (char)tolower((unsigned char)c); + if (*pattern == '-' + && (c2 = *(pattern+1)) != EOS && c2 != ']') { + pattern += 2; + if (c2 == '\\' && !(flags & FNM_NOESCAPE)) + c2 = *pattern++; + if (c2 == EOS) + return (RANGE_ERROR); + if (flags & FNM_CASEFOLD) + c2 = (char)tolower((unsigned char)c2); + if (c <= test && test <= c2) + ok = 1; + } else if (c == test) + ok = 1; + } while ((c = *pattern++) != ']'); + + *newp = (char *)pattern; + return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH); +} + +static int +classmatch(const char *pattern, char test, int foldcase, const char **ep) +{ + struct cclass *cc; + const char *colon; + size_t len; + int rval = RANGE_NOMATCH; + + if ((colon = strchr(pattern, ':')) == NULL || colon[1] != ']') { + *ep = pattern - 2; + return(RANGE_ERROR); + } + *ep = colon + 2; + len = (size_t)(colon - pattern); + + if (foldcase && strncmp(pattern, "upper:]", 7) == 0) + pattern = "lower:]"; + for (cc = cclasses; cc->name != NULL; cc++) { + if (!strncmp(pattern, cc->name, len) && cc->name[len] == '\0') { + if (cc->isctype((unsigned char)test)) + rval = RANGE_MATCH; + break; + } + } + if (cc->name == NULL) { + /* invalid character class, return EOS */ + *ep = colon + strlen(colon); + rval = RANGE_ERROR; + } + return(rval); +} diff --git a/lib/libc/posix/pread.c b/lib/libc/posix/pread.c new file mode 100644 index 000000000..a1af0223e --- /dev/null +++ b/lib/libc/posix/pread.c @@ -0,0 +1,27 @@ +#include +#include + +ssize_t pread(int fd, void *buffer, size_t nbytes, off_t where) +{ + off_t here; + ssize_t r; + + if((here = lseek(fd, 0, SEEK_CUR)) < 0) + return -1; + + if(lseek(fd, where, SEEK_SET) < 0) + return -1; + + if((r=read(fd, buffer, nbytes)) < 0) { + int e = errno; + lseek(fd, here, SEEK_SET); + errno = e; + return -1; + } + + if(lseek(fd, here, SEEK_SET) < 0) + return -1; + + return r; +} + diff --git a/lib/libc/stdio/Makefile.inc b/lib/libc/stdio/Makefile.inc index c4de4f8ac..a4a0c5409 100644 --- a/lib/libc/stdio/Makefile.inc +++ b/lib/libc/stdio/Makefile.inc @@ -44,6 +44,7 @@ SRCS+= \ setbuf.c \ setvbuf.c \ sprintf.c \ + snprintf.c \ sscanf.c \ tmpfile.c \ tmpnam.c \ diff --git a/lib/libc/stdio/snprintf.c b/lib/libc/stdio/snprintf.c new file mode 100644 index 000000000..efe4c4491 --- /dev/null +++ b/lib/libc/stdio/snprintf.c @@ -0,0 +1,24 @@ +/* + * snprintf - print limited formatted output on an array + */ +/* $Header$ */ + +#include +#include +#include +#include "loc_incl.h" + +int +snprintf(char *s, size_t n, const char *format, ...) +{ + va_list ap; + int retval; + + va_start(ap, format); + + retval = vsnprintf(s, n, format, ap); + + va_end(ap); + + return retval; +} diff --git a/lib/libc/stdio/sprintf.c b/lib/libc/stdio/sprintf.c index c40b080de..5fe46af36 100644 --- a/lib/libc/stdio/sprintf.c +++ b/lib/libc/stdio/sprintf.c @@ -23,17 +23,3 @@ sprintf(char *s, const char *format, ...) return retval; } -int -snprintf(char *s, size_t n, const char *format, ...) -{ - va_list ap; - int retval; - - va_start(ap, format); - - retval = vsnprintf(s, n, format, ap); - - va_end(ap); - - return retval; -} diff --git a/man/man2/read.2 b/man/man2/read.2 index 4326ac06a..ca9571ec0 100644 --- a/man/man2/read.2 +++ b/man/man2/read.2 @@ -7,7 +7,7 @@ .TH READ 2 "May 23, 1986" .UC 4 .SH NAME -read \- read input +read, pread \- read input .SH SYNOPSIS .nf .ft B @@ -15,6 +15,7 @@ read \- read input #include ssize_t read(int \fId\fP, void *\fIbuf\fP, size_t \fInbytes\fP) +ssize_t pread(int \fId\fP, void *\fIbuf\fP, size_t \fInbytes\fP, off_t \fIoffset\fP) .fi .SH DESCRIPTION .B Read @@ -49,6 +50,11 @@ before the end-of-file, but in no other case. .PP If the returned value is 0, then end-of-file has been reached. +.PP +The +.B pread +system call performs the same functions, but reads from the specified +position in the file without modifying the file pointer. .SH "RETURN VALUE If successful, the number of bytes actually read is returned. @@ -57,6 +63,8 @@ Otherwise, a \-1 is returned and the global variable is set to indicate the error. .SH "ERRORS .B Read +and +.B pread will fail if one or more of the following are true: .TP 15 [EBADF] @@ -75,9 +83,19 @@ any data arrived by the delivery of a signal. [EAGAIN] The file was marked for non-blocking I/O, and no data were ready to be read. +.PP +The +.B pread +system call may also return any of the +.B lseek +errors. .SH "SEE ALSO" .BR dup (2), .BR fcntl (2), .BR open (2), .BR pipe (2), +.BR lseek (2), .BR write (2). +.SH NOTES +.B pread +is currently implemented as a library function instead of a system call. diff --git a/man/man3/fnmatch.3 b/man/man3/fnmatch.3 new file mode 100644 index 000000000..80c54bd20 --- /dev/null +++ b/man/man3/fnmatch.3 @@ -0,0 +1,120 @@ +.\" Copyright (c) 1989, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" Guido van Rossum. +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)fnmatch.3 8.3 (Berkeley) 4/28/95 +.\" $FreeBSD: src/lib/libc/gen/fnmatch.3,v 1.19.6.1 2008/11/25 02:59:29 kensmith Exp $ +.\" +.TH FNMATCH 3 "July 18, 2004" +.AT 3 +.SH NAME +fnmatch \- test whether a filename or pathname matches a shell-style pattern +.SH SYNOPSIS +.nf +.ft B +#include + +int fnmatch(const char *\fIpattern\fP, const char *\fIstring\fP, int \fIflags\fP); +.ft R +.fi +.SH DESCRIPTION +The +.B fnmatch +function matches patterns according to the rules used by the shell. +It checks the string specified by the +.IR string +argument to see if it matches the pattern specified by the +.IR pattern +argument. +.PP +The +.IR flags +argument modifies the interpretation of +.IR pattern +and +.IR string . +The value of +.IR flags +is the bitwise inclusive OR of any of the following +constants, which are defined in the include file fnmatch.h. +.TP 15 +FNM_NOESCAPE +Normally, every occurrence of a backslash followed by a character in +.IR pattern +is replaced by that character. +This is done to negate any special meaning for the character. +If the FNM_NOESCAPE +flag is set, a backslash character is treated as an ordinary character. +.TP 15 +FNM_PATHNAME +Slash characters in +.IR string +must be explicitly matched by slashes in +.IR pattern . +If this flag is not set, then slashes are treated as regular characters. +.TP 15 +FNM_PERIOD +Leading periods in +.IR string +must be explicitly matched by periods in +.IR pattern . +If this flag is not set, then leading periods are treated as regular +characters. +The definition of leading is related to the specification of FNM_PATHNAME. +A period is always leading if it is the first character in +.IR string . +Additionally, if FNM_PATHNAME is set, a period is leading +if it immediately follows a slash. +.TP 15 +FNM_LEADING_DIR +Ignore /* rest after successful +.IR pattern +matching. +.TP 15 +FNM_CASEFOLD +Ignore case distinctions in both the +.IR pattern +and the +.IR string . +.SH RETURN VALUES +The +.B fnmatch +function returns zero if +.IR string +matches the pattern specified by +.IR pattern , +otherwise, it returns the value FNM_NOMATCH. +.SH SEE ALSO +.BR sh (1), +.BR regex (3), +.SH HISTORY +The +.B fnmatch +function first appeared in 4.4BSD. +.SH BUGS +The pattern * matches the empty string, even if FNM_PATHNAME is specified.