Blame | Last modification | View Log | RSS feed
/**************************************************************************** Module name : realpath.c* Module type : CMDFILE source file* Environment(s): n/a** Description:realpath resolves all links and references to '.' and.' in "file_name" and stores it in "resolved_name".It can handle both relative and absolute path names.For absolute path names and relative path whose resolvedname cannot be expressed relatively (for example,../../reldir), it returns the resolved absolute name. Forother relative names, it returns the resolved relative name.resolved name must be be big enough (MAXPATHLEN) tocontain the fully resolved path name.Returns:The realpath function returns the address of the stringcontaining the name of the resolved directory, unless anerror occurs, in which case NULL is returned.** Version Who Date DescriptionAPY 02/03/00 Created** $Source: /cvsroot/device/DEVL/UTILS/CMDFILE/realpath.c,v $* $Revision: 1.5 $ $Date: 2004/10/08 03:07:37 $ $State: Exp $* $Author: ayoung $ $Locker: $*.........................................................................*//** Include Files* ---------------*/#include <ctype.h>#include <unistd.h>#if defined(WIN32)#include <windows.h>#endif#include "cmdfile.h"const char * Realpath( const char *name, char *buf );#if defined(MSDOS)static void dos_realpath( const char *in, char *out, char sep );#endifintdo_realpath( String_t *str, const char *s ){char name[ PATH_MAX ], buf[ PATH_MAX ];int len;if (expected(s++, ',') > 0 &&(len = pathargument(s, name, PATH_MAX)) > 0){const char *p;p = Realpath( name, buf );verbose( " realpath(%s) = %s", name, p );StringPath( str, p );return (1+len);}return (-1);}const char *Realpath(const char *name, char *buf){#if defined(unix)const char *p;memset(buf, 0, PATH_MAX); /* PURIFY - solaris realpath illuse of 'buf'*/if ((p = realpath(name, buf)) == name && name != NULL)if (buf == NULL){ /* NULL output buffer */errno = EFAULT;p = NULL;}else{ /* 'abs' match, copy to dest */(void) strcpy(buf, name);p = buf;}return (p);#elif defined(WIN32)const char *p;/* restore full path */if ((p = _fullpath(buf, name, PATH_MAX)) == NULL && name != NULL)if (buf == NULL){ /* NULL output buffer */errno = EFAULT;p = NULL;}else{ /* 'abs' match, copy to dest */(void) strcpy(buf, name);p = buf;}return (p);#elif defined(MSDOS)char sep;sep = strchr(name, '/') ? '/' : '\\'; /* handle UNIX, default MSDOS */(void) dos_realpath(name, buf, sep);return (buf);#else#error Unknown target OS ...#endif}#if defined(MSDOS)/* realpath ---** Takes as input an arbitrary path. Fixes up the path by:* 1. Convert relative path to absolute* 2. Removing consecutive slashes* 3. Removing trailing slashes* 4. Making the path absolute if it wasn't already* 5. Removing "." in the path* 6. Removing ".." entries in the path (and the directory above them)*/static char *get_cwd(char *out, int drive, char sep);static voiddos_realpath( const char *in, char *out, char sep ){register const char *i = in;register char *o = out;/* Convert relative path to absolute */{int drive;if (*(i+1) == ':' &&((*i >= 'a' && *i <= 'z') || (*i >= 'A' && *i <= 'Z'))) {if (*i >= 'a' && *i <= 'z')drive = *i - 'a';else drive = *i - 'A';*o++ = *i++;*o++ = *i++;} else {drive = GetDisk();*o++ = drive + 'A';*o++ = ':';}if (!is_slash(*i))o = get_cwd(o, drive, sep);}/* Step through the input path */while (*i != '\0'){/* Skip input slashes */if (is_slash(*i)){i++;continue;}/* Skip "." and output nothing */if (*i == '.' && is_term(*(i + 1))){i++; continue;}/* Skip ".." and remove previous output directory */if (*i == '.' && *(i + 1) == '.' && is_term(*(i + 2))){/* Don't back up over drive spec or consume ../.. */if (o > out+2 && strncmp(o-2, "..", 2) != 0){/* Consume .. and parent directory */i += 2;while (--o > out+2 && !is_slash(*o));continue;}}/* Copy path component from in to p */*o++ = sep;/* Copy next filename/directory */while (!is_term(*i))*o++ = *i++;}*o = '\0';}static intget_disk(void){#ifdef __WATCOMC__unsigned drive;_dos_getdrive(&drive);return 0;#elseunion REGS regs;regs.h.ah = 0x19; /* DOS Get Default Drive call */regs.h.al = 0;(void) intdos(®s, ®s);return regs.h.al;#endif}static char *get_cwd(char *out, int drive, char sep){char cwd[ PATH_MAX ];register char *p, *o;/* Get current work directory */{union REGS regs;regs.h.ah = 0x47;regs.h.dl = drive + 1;#ifdef __386__regs.x.esi = (unsigned long) cwd;#elseregs.x.si = (unsigned long) cwd;#endif(void) intdos(®s, ®s);#ifdef __WATCOMC__if (regs.w.cflag != 0) {errno = regs.w.ax;return out;}#elseif (regs.x.cflag != 0) {errno = regs.x.ax;return out;}#endif}/* Copy and convert path */for (p = cwd, o = out+1; *p; p++)*o++ = is_slash(*p) ? sep : *p;*o = '\0';/* Root path, don't insert "/", it'll be added later */if (*(out+1) != '\0')*out = sep;else *out = '\0';return (out + strlen(out));}#endif /*MSDOS*/