1515#include <sys/param.h>
1616#include <dirent.h>
1717#include <errno.h>
18+ #include <stdlib.h>
1819
1920#ifdef F___cwd
2021/* the present working directory variable. */
@@ -33,43 +34,36 @@ extern size_t __cwd_len;
3334#define defaultCWD "host:"
3435
3536enum SeparatorType {
37+ SeparatorTypeNotFound ,
3638 SeparatorTypeNone ,
3739 SeparatorTypePOSIX ,
38- SeparatorTypeWindows
40+ SeparatorTypeWindows ,
3941};
4042
4143#define isnum (c ) ((c) >= '0' && (c) <= '9')
4244
4345#ifdef F___get_drive
4446/* Return the number of bytes taken up by the "drive:" prefix,
4547 or -1 if it's not found */
46- int __get_drive (const char * dev , enum SeparatorType * usePOSIXSeparator )
48+ int __get_drive (const char * dev , enum SeparatorType * usePOSIXSeparator , int maxLen )
4749{
48- const char * tail ;
50+ const char * t ;
4951 const char * d ;
5052 int devname_len ;
5153
5254 /* Skip leading spaces */
53- d = dev ;
54- while (* d == ' ' )
55- {
56- d += 1 ;
57- }
55+ for (d = dev ; ((int )(d - dev ) < maxLen ) && * d == ' ' ; d += 1 );
5856
5957 /* Get colon position */
60- tail = strchr ( d , ':' );
61- if (tail == NULL )
58+ for ( t = d ; (( int )( t - dev ) < maxLen ) && * t && * t != ':' ; t += 1 );
59+ if (* t != ':' )
6260 {
63- return -1 ;
61+ * usePOSIXSeparator = SeparatorTypeNotFound ;
62+ return 0 ;
6463 }
6564
66- devname_len = (int )(tail - d );
67-
6865 /* Reduce length to not include index */
69- while (isnum (d [devname_len - 1 ]))
70- {
71- devname_len -= 1 ;
72- }
66+ for (devname_len = (int )(t - d ); isnum (d [devname_len - 1 ]); devname_len -= 1 );
7367
7468 * usePOSIXSeparator = SeparatorTypePOSIX ;
7569 switch (devname_len )
@@ -99,27 +93,37 @@ int __get_drive(const char *dev, enum SeparatorType *usePOSIXSeparator)
9993 * - device index
10094 * - colon
10195 */
102- return (tail - dev ) + 1 ;
96+ return (t - dev ) + 1 ;
10397}
10498#else
105- int __get_drive (const char * dev , enum SeparatorType * usePOSIXSeparator );
99+ int __get_drive (const char * dev , enum SeparatorType * usePOSIXSeparator , int maxLen );
106100#endif
107101
108102#ifdef F_getcwd
109103char * getcwd (char * buf , size_t size )
110104{
111- if (!buf ) {
105+ if (!buf )
106+ {
107+ size = __cwd_len + 1 ;
108+ buf = malloc (size );
109+ if (!buf )
110+ {
111+ errno = ENOMEM ;
112+ return NULL ;
113+ }
114+ }
115+ else if (!size )
116+ {
112117 errno = EINVAL ;
113118 return NULL ;
114- }
115-
116- if ( __cwd_len >= size ) {
119+ }
120+ else if ( size < ( __cwd_len + 1 ))
121+ {
117122 errno = ERANGE ;
118123 return NULL ;
119124 }
120125
121- memcpy (buf , __cwd , __cwd_len );
122- buf [__cwd_len ] = '\x00' ;
126+ snprintf (buf , size , "%*s" , __cwd_len , __cwd );
123127 return buf ;
124128}
125129#endif
@@ -202,43 +206,30 @@ int __path_absolute(const char *in, char *out, int len)
202206 int dr ;
203207 enum SeparatorType separatorType ;
204208 size_t in_len ;
209+ size_t out_len ;
205210
206211 in_len = strlen (in );
207212 /* See what the relative URL starts with */
208- dr = __get_drive (in , & separatorType );
213+ dr = __get_drive (in , & separatorType , in_len );
209214 char separator = separatorType == SeparatorTypePOSIX ? '/' : '\\' ;
210215
211- if (dr > 0 && (separatorType == SeparatorTypeNone || in [dr ] == separator )) {
216+ if (( separatorType != SeparatorTypeNotFound ) && (separatorType == SeparatorTypeNone || in [dr ] == separator )) {
212217 /* It starts with "drive:" and has no separator or "drive:/", so it's already absolute */
213- if (in_len >= len ) return -1 ;
214- strncpy (out , in , len );
215- } else if (dr > 0 && in [dr - 1 ] == ':' ) {
218+ out_len = snprintf (out , len , "%*s" , in_len , in );
219+ } else if ((separatorType != SeparatorTypeNotFound ) && in [dr - 1 ] == ':' ) {
216220 /* It starts with "drive:", so it's already absoulte, however it misses the "/" after unit */
217- if (in_len + 1 >= len ) return -2 ;
218- strncpy (out , in , dr );
219- out [dr ] = separator ;
220- strncpy (out + dr + 1 , in + dr , len - dr - 1 );
221+ out_len = snprintf (out , len , "%*s%c%*s" , dr , in , separator , in_len - dr , in + dr );
221222 } else if (in [0 ] == '\\' || in [0 ] == '/' ) {
222223 /* It's absolute, but missing the drive, so use cwd's drive */
223- if (__cwd_len + in_len >= len ) return -3 ;
224- memcpy (out , __cwd , __cwd_len );
225- out [__cwd_len ] = '\x00' ;
226- dr = __get_drive (out , & separatorType );
227- if (dr < 0 ) dr = 0 ;
228- out [dr ] = 0 ;
229- strncat (out , in , len );
224+ out_len = snprintf (out , len , "%*s%*s" , __get_drive (__cwd , & separatorType , __cwd_len ), __cwd , in_len , in );
230225 } else {
231226 /* It's not absolute, so append it to the current cwd */
232- if (__cwd_len + 1 + in_len >= len ) return -5 ;
233- memcpy (out , __cwd , __cwd_len );
234- out [__cwd_len ] = separator ;
235- out [__cwd_len + 1 ] = '\x00' ;
236- strncat (out , in , len );
227+ out_len = snprintf (out , len , "%*s%c%*s" , __cwd_len , __cwd , separator , in_len , in );
237228 }
229+ if (out_len >= len ) return -1 ;
238230
239231 /* Now normalize the pathname portion */
240- dr = __get_drive (out , & separatorType );
241- if (dr < 0 ) dr = 0 ;
232+ dr = __get_drive (out , & separatorType , out_len );
242233 return __path_normalize (out + dr , len - dr , separatorType == SeparatorTypePOSIX );
243234}
244235#endif
0 commit comments