Subversion Repositories DevTools

Rev

Rev 313 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
313 dpurdie 1
/***************************************************************************
2
* Module name   : realpath.c
3
* Module type   : CMDFILE source file
4
* Environment(s): n/a
5
*
6
* Description:
7
     realpath resolves all links and references to '.' and
8
     .' in "file_name" and stores it in "resolved_name".
9
 
10
     It can handle both relative and absolute path names. 
11
     For absolute path names and relative path whose resolved
12
     name cannot be expressed relatively (for example,
13
     ../../reldir), it returns the resolved absolute name.  For
14
     other relative names, it returns the resolved relative name.
15
 
16
     resolved name must be be big enough (MAXPATHLEN) to
17
     contain the fully resolved path name.
18
 
19
Returns:
20
     The realpath function returns the address of the string 
21
     containing the name of the resolved directory, unless an 
22
     error occurs, in which case NULL is returned.
23
 
24
*
25
* Version   Who      Date        Description
26
            APY      02/03/00    Created
27
*
28
* $Source: /cvsroot/device/DEVL/UTILS/CMDFILE/realpath.c,v $            
29
* $Revision: 1.5 $ $Date: 2004/10/08 03:07:37 $ $State: Exp $ 
30
* $Author: ayoung $ $Locker:  $
31
*.........................................................................*/
32
/*
33
*     Include Files
34
*     ---------------
35
*/
36
#include <ctype.h>
37
#include <unistd.h>
38
#if defined(WIN32)
39
#include <windows.h>
40
#endif
41
#include "cmdfile.h"
42
 
43
const char *        Realpath( const char *name, char *buf );
44
#if defined(MSDOS)
45
static void         dos_realpath( const char *in, char *out, char sep );
46
#endif
47
 
48
 
49
int
50
do_realpath( String_t *str, const char *s )
51
{
52
    char name[ PATH_MAX ], buf[ PATH_MAX ];
53
    int  len;
54
 
55
    if (expected(s++, ',') > 0 &&
56
            (len = pathargument(s, name, PATH_MAX)) > 0)
57
    {
58
        const char *p;
59
 
60
        p = Realpath( name, buf );
61
        verbose( " realpath(%s) = %s", name, p );
62
        StringPath( str, p );
63
        return (1+len);
64
    }
65
    return (-1);
66
}
67
 
68
 
69
const char *
70
Realpath(const char *name, char *buf)
71
{
72
#if defined(unix)
73
    const char *p;
74
 
75
    memset(buf, 0, PATH_MAX); 			/* PURIFY - solaris realpath illuse of 'buf'*/
76
    if ((p = realpath(name, buf)) == name && name != NULL)
77
	if (buf == NULL)
78
	{					/* NULL output buffer */
79
	    errno = EFAULT;
80
	    p = NULL;
81
	}
82
	else
83
	{					/* 'abs' match, copy to dest */
84
	    (void) strcpy(buf, name);
85
	    p = buf;
86
	}
87
    return (p);
88
 
89
#elif defined(WIN32)
90
    const char *p;
91
 
92
                                                /* restore full path */
93
    if ((p = _fullpath(buf, name, PATH_MAX)) == NULL && name != NULL)
94
	if (buf == NULL)
95
	{					/* NULL output buffer */
96
	    errno = EFAULT;
97
	    p = NULL;
98
	}
99
	else
100
	{					/* 'abs' match, copy to dest */
101
	    (void) strcpy(buf, name);
102
	    p = buf;
103
	}
104
    return (p);
105
 
106
#elif defined(MSDOS)
107
    char sep;
108
 
109
    sep = strchr(name, '/') ? '/' : '\\';       /* handle UNIX, default MSDOS */
110
    (void) dos_realpath(name, buf, sep);
111
    return (buf);
112
 
113
#else
114
#error Unknown target OS ...
115
#endif
116
}
117
 
118
 
119
#if defined(MSDOS)
120
/* realpath ---
121
 *
122
 *  Takes as input an arbitrary path.  Fixes up the path by:
123
 *      1.  Convert relative path to absolute
124
 *      2.  Removing consecutive slashes
125
 *      3.  Removing trailing slashes
126
 *      4.  Making the path absolute if it wasn't already
127
 *      5.  Removing "." in the path
128
 *      6.  Removing ".." entries in the path (and the directory above them)
129
 */
130
static char         *get_cwd(char *out, int drive, char sep);
131
 
132
static void
133
dos_realpath( const char *in, char *out, char sep )
134
{
135
    register const char *i = in;
136
    register char *o = out;
137
 
138
/* Convert relative path to absolute */
139
    {
140
        int drive;
141
 
142
        if (*(i+1) == ':' &&
143
                ((*i >= 'a' && *i <= 'z') || (*i >= 'A' && *i <= 'Z'))) {
144
            if (*i >= 'a' && *i <= 'z')
145
                drive = *i - 'a';
146
            else drive = *i - 'A';
147
            *o++ = *i++;
148
            *o++ = *i++;
149
        } else {
150
            drive = GetDisk();
151
            *o++ = drive + 'A';
152
            *o++ = ':';
153
        }
154
        if (!is_slash(*i))
155
            o = get_cwd(o, drive, sep);
156
    }
157
 
158
/* Step through the input path */
159
    while (*i != '\0')
160
    {
161
    /* Skip input slashes */
162
        if (is_slash(*i))
163
        {
164
            i++;
165
            continue;
166
        }
167
 
168
    /* Skip "." and output nothing */
169
        if (*i == '.' && is_term(*(i + 1)))
170
        {
171
            i++; continue;
172
        }
173
 
174
    /* Skip ".." and remove previous output directory */
175
        if (*i == '.' && *(i + 1) == '.' && is_term(*(i + 2)))
176
        {
177
        /* Don't back up over drive spec or consume ../.. */
178
            if (o > out+2 && strncmp(o-2, "..", 2) != 0)
179
            {
180
            /* Consume .. and parent directory */
181
                i += 2;
182
                while (--o > out+2 && !is_slash(*o))
183
                    ;
184
                continue;
185
            }
186
        }
187
 
188
    /* Copy path component from in to p */
189
        *o++ = sep;
190
 
191
    /* Copy next filename/directory */
192
        while (!is_term(*i))
193
            *o++ = *i++;
194
    }
195
    *o = '\0';
196
}
197
 
198
 
199
static int
200
get_disk(void)
201
{
202
#ifdef __WATCOMC__
203
    unsigned drive;
204
    _dos_getdrive(&drive);
205
    return 0;
206
#else
207
    union REGS regs;
208
    regs.h.ah = 0x19;                           /* DOS Get Default Drive call */
209
    regs.h.al = 0;
210
    (void) intdos(&regs, &regs);
211
    return regs.h.al;
212
#endif
213
}
214
 
215
 
216
static char *
217
get_cwd(char *out, int drive, char sep)
218
{
219
    char cwd[ PATH_MAX ];
220
    register char *p, *o;
221
 
222
/* Get current work directory */
223
    {
224
        union REGS  regs;
225
        regs.h.ah   = 0x47;
226
        regs.h.dl   = drive + 1;
227
    #ifdef __386__
228
        regs.x.esi  = (unsigned long) cwd;
229
    #else
230
        regs.x.si   = (unsigned long) cwd;
231
    #endif
232
        (void) intdos(&regs, &regs);
233
    #ifdef __WATCOMC__
234
        if (regs.w.cflag != 0) {
235
            errno = regs.w.ax;
236
            return out;
237
        }
238
    #else
239
        if (regs.x.cflag != 0) {
240
            errno = regs.x.ax;
241
            return out;
242
        }
243
    #endif
244
    }
245
 
246
/* Copy and convert path */
247
    for (p = cwd, o = out+1; *p; p++)
248
         *o++ = is_slash(*p) ? sep : *p;
249
    *o = '\0';
250
 
251
/* Root path, don't insert "/", it'll be added later */
252
    if (*(out+1) != '\0')
253
        *out = sep;
254
    else *out = '\0';
255
    return (out + strlen(out));
256
}
257
#endif  /*MSDOS*/
258