summaryrefslogtreecommitdiff
path: root/usr/src/lib/libcmd/common/pathchk.c
diff options
context:
space:
mode:
authorchin <none@none>2007-08-17 12:01:52 -0700
committerchin <none@none>2007-08-17 12:01:52 -0700
commitda2e3ebdc1edfbc5028edf1354e7dd2fa69a7968 (patch)
tree5280d3b78e289fe9551371ab6e7f15ef9944ea14 /usr/src/lib/libcmd/common/pathchk.c
parent073dbf9103ef2a2b05d8a16e2d26db04e0374b0e (diff)
downloadillumos-joyent-da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968.tar.gz
6437624 RFE: Add ksh93 (as /usr/bin/ksh93) and libshell.so to OS/Net
6505835 AST tools and library (libpp) required for creating l10n messages for ksh93 PSARC/2006/550 Korn Shell 93 Integration PSARC/2006/587 /etc/ksh.kshrc for ksh93 PSARC/2007/035 ksh93 Amendments Contributed by Roland Mainz <roland.mainz@nrubsig.org> --HG-- rename : usr/src/lib/libcmd/common/mapfile-vers => deleted_files/usr/src/lib/libcmd/common/mapfile-vers rename : usr/src/lib/libcmd/common/placeholder.c => deleted_files/usr/src/lib/libcmd/common/placeholder.c
Diffstat (limited to 'usr/src/lib/libcmd/common/pathchk.c')
-rw-r--r--usr/src/lib/libcmd/common/pathchk.c248
1 files changed, 248 insertions, 0 deletions
diff --git a/usr/src/lib/libcmd/common/pathchk.c b/usr/src/lib/libcmd/common/pathchk.c
new file mode 100644
index 0000000000..fff22f52bf
--- /dev/null
+++ b/usr/src/lib/libcmd/common/pathchk.c
@@ -0,0 +1,248 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * pathchk
+ *
+ * Written by David Korn
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: pathchk (AT&T Research) 2006-09-19 $\n]"
+USAGE_LICENSE
+"[+NAME?pathchk - check pathnames for portability]"
+"[+DESCRIPTION?\bpathchk\b checks each \apathname\a to see if it "
+ "is valid and/or portable. A \apathname\a is valid if it "
+ "can be used to access or create a file without causing syntax "
+ "errors. A file is portable, if no truncation will result on "
+ "any conforming POSIX.1 implementation.]"
+"[+?By default \bpathchk\b checks each component of each \apathname\a "
+ "based on the underlying file system. A diagnostic is written "
+ "to standard error for each pathname that:]{"
+ "[+-?Is longer than \b$(getconf PATH_MAX)\b bytes.]"
+ "[+-?Contains any component longer than \b$(getconf NAME_MAX)\b bytes.]"
+ "[+-?Contains any directory component in a directory that is "
+ "not searchable.]"
+ "[+-?Contains any character in any component that is not valid in "
+ "its containing directory.]"
+ "[+-?Is empty.]"
+ "}"
+"[p:portability?Instead of performing length checks on the underlying "
+ "file system, write a diagnostic for each pathname operand that:]{"
+ "[+-?Is longer than \b$(getconf _POSIX_PATH_MAX)\b bytes.]"
+ "[+-?Contains any component longer than "
+ "\b$(getconf _POSIX_NAME_MAX)\b bytes.]"
+ "[+-?Contains any character in any component that is not in the "
+ "portable filename character set.]"
+#if 0
+ "[+-?Contains any component with \b-\b as the first character.]"
+#endif
+ "[+-?Is empty.]"
+ "}"
+"\n"
+"\npathname ...\n"
+"\n"
+"[+EXIT STATUS?]{"
+ "[+0?All \apathname\a operands passed all of the checks.]"
+ "[+>0?An error occurred.]"
+"}"
+"[+SEE ALSO?\bgetconf\b(1), \bcreat\b(2), \bpathchk\b(2)]"
+;
+
+
+#include <cmd.h>
+#include <ls.h>
+
+#define isport(c) (((c)>='a' && (c)<='z') || ((c)>='A' && (c)<='Z') || ((c)>='0' && (c)<='9') || (strchr("._-",(c))!=0) )
+
+/*
+ * call pathconf and handle unlimited sizes
+ */
+static long mypathconf(const char *path, int op)
+{
+ register long r;
+
+ static const char* ops[] = { "NAME_MAX", "PATH_MAX" };
+
+ errno=0;
+ if((r=strtol(astconf(ops[op], path, NiL), NiL, 0))<0 && errno==0)
+ return(LONG_MAX);
+ return(r);
+}
+
+/*
+ * returns 1 if <path> passes test
+ */
+static int pathchk(char* path, int mode)
+{
+ register char *cp=path, *cpold;
+ register int c;
+ register long r,name_max,path_max;
+ char buf[2];
+
+ if(!*path)
+ {
+ error(2,"path is empty");
+ return(0);
+ }
+ if(mode)
+ {
+ name_max = _POSIX_NAME_MAX;
+ path_max = _POSIX_PATH_MAX;
+ }
+ else
+ {
+ char tmp[2];
+ name_max = path_max = 0;
+ tmp[0] = (*cp=='/'? '/': '.');
+ tmp[1] = 0;
+ if((r=mypathconf(tmp, 0)) > _POSIX_NAME_MAX)
+ name_max = r;
+ if((r=mypathconf(tmp, 1)) > _POSIX_PATH_MAX)
+ path_max = r;
+ if(*cp!='/')
+ {
+ if(name_max==0||path_max==0)
+ {
+ if(!(cpold = getcwd((char*)0, 0)) && errno == EINVAL && (cpold = newof(0, char, PATH_MAX, 0)) && !getcwd(cpold, PATH_MAX))
+ {
+ free(cpold);
+ cpold = 0;
+ }
+ if(cpold)
+ {
+ cp = cpold + strlen(cpold);
+ while(name_max==0 || path_max==0)
+ {
+ if(cp>cpold)
+ while(--cp>cpold && *cp=='/');
+ *++cp = 0;
+ if(name_max==0 && (r=mypathconf(cpold, 0)) > _POSIX_NAME_MAX)
+ name_max = r;
+ if(path_max==0 && (r=mypathconf(cpold, 1)) > _POSIX_PATH_MAX)
+ path_max=r;
+ if(--cp==cpold)
+ {
+ free(cpold);
+ break;
+ }
+ while(*cp!='/')
+ cp--;
+ }
+ cp=path;
+ }
+ }
+ while(*cp=='/')
+ cp++;
+ }
+ if(name_max==0)
+ name_max=_POSIX_NAME_MAX;
+ if(path_max==0)
+ path_max=_POSIX_PATH_MAX;
+ while(*(cpold=cp))
+ {
+ while((c= *cp++) && c!='/');
+ if((cp-cpold) > name_max)
+ goto err;
+ errno=0;
+ cp[-1] = 0;
+ r = mypathconf(path, 0);
+ if((cp[-1]=c)==0)
+ cp--;
+ else while(*cp=='/')
+ cp++;
+ if(r>=0)
+ name_max=(r<_POSIX_NAME_MAX?_POSIX_NAME_MAX:r);
+ else if(errno==EINVAL)
+ continue;
+#ifdef ENAMETOOLONG
+ else if(errno==ENAMETOOLONG)
+ {
+ error(2,"%s: pathname too long",path);
+ return(0);
+ }
+#endif /*ENAMETOOLONG*/
+ else
+ break;
+ }
+ }
+ while(*(cpold=cp))
+ {
+ if(mode && *cp == '-')
+ {
+ error(2,"%s: path component begins with '-'",path,fmtquote(buf, NiL, "'", 1, 0));
+ return(0);
+ }
+ while((c= *cp++) && c!='/')
+ if(mode && !isport(c))
+ {
+ buf[0] = c;
+ buf[1] = 0;
+ error(2,"%s: '%s' not in portable character set",path,fmtquote(buf, NiL, "'", 1, 0));
+ return(0);
+ }
+ if((cp-cpold) > name_max)
+ goto err;
+ if(c==0)
+ break;
+ while(*cp=='/')
+ cp++;
+ }
+ if((cp-path) >= path_max)
+ {
+ error(2,"%s: pathname too long",path);
+ return(0);
+ }
+ return(1);
+err:
+ error(2,"%s: component name %.*s too long",path,cp-cpold-1,cpold);
+ return(0);
+}
+
+int
+b_pathchk(int argc, char** argv, void* context)
+{
+ register int n, mode=0;
+ register char *cp;
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ while (n = optget(argv, usage)) switch (n)
+ {
+ case 'p':
+ mode = 1;
+ break;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
+ argv += opt_info.index;
+ if(*argv==0 || error_info.errors)
+ error(ERROR_usage(2),"%s", optusage((char*)0));
+ while(cp = *argv++)
+ {
+ if(!pathchk(cp,mode))
+ error_info.errors=1;
+ }
+ return(error_info.errors);
+}