/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1992-2011 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (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) 2009-07-24 $\n]"
"[+NAME?pathchk - check pathnames for portability]"
"[+DESCRIPTION?\bpathchk\b checks each \apathname\a to see if it is "
"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:components?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.]"
"}"
"[P:path?Write a diagnostic for each pathname operand that:]"
"{"
"[+-?Contains any component with \b-\b as the first character.]"
"[+-?Is empty.]"
"}"
"[a:all|portability?Equivalent to \b--components\b \b--path\b.]"
"\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
*/
{
register long r;
errno = 0;
return LONG_MAX;
return r;
}
/*
* returns 1 if <path> passes test
*/
{
register int c;
if(!*path)
{
return -1;
}
if(mode & COMPONENTS)
{
}
else
{
tmp[1] = 0;
name_max = r;
path_max = r;
if(*cp!='/')
{
{
if(!(cpold = getcwd((char*)0, 0)) && errno == EINVAL && (cpold = newof(0, char, PATH_MAX, 0)) && !getcwd(cpold, PATH_MAX))
{
cpold = 0;
}
if(cpold)
{
{
*++cp = 0;
name_max = r;
path_max=r;
{
break;
}
while(*cp!='/')
cp--;
}
}
}
while(*cp=='/')
cp++;
}
if(name_max==0)
if(path_max==0)
{
while((c= *cp++) && c!='/');
goto err;
errno=0;
cp[-1] = 0;
r = mypathconf(path, 0);
if((cp[-1]=c)==0)
cp--;
else while(*cp=='/')
cp++;
if(r>=0)
continue;
#ifdef ENAMETOOLONG
else if(errno==ENAMETOOLONG)
{
return -1;
}
#endif /*ENAMETOOLONG*/
else
break;
}
}
{
{
return -1;
}
while((c= *cp++) && c!='/')
{
buf[0] = c;
buf[1] = 0;
return -1;
}
goto err;
if(c==0)
break;
while(*cp=='/')
cp++;
}
{
return -1;
}
return 0;
err:
return -1;
}
int
{
register int mode = 0;
register char* s;
for (;;)
{
{
case 'a':
continue;
case 'p':
mode |= COMPONENTS;
continue;
case 'P':
continue;
case ':':
break;
case '?':
break;
}
break;
}
while (s = *argv++)
return error_info.errors != 0;
}