Mail Archives: djgpp-workers/2002/09/20/21:29:36
Hello,
An implementation of realpath would certainly help in the posix compliance
department. To help attain a compliant version, I've made some changes to
fixpath.c to make implementing realpath easier. For example, I changed
FILENAME_MAX to PATH_MAX. I also created a new function __canonicalize_path
with a return type compatible with what realpath returns. This way,
__canonicalize_path can function as a wrapper for both _fixpath and realpath.
BTW, while realpath mandates more checking than _fixpath, it still has some
flaws like its _fixpath cousin. For example, you can easily (and
deliberately) overflow the output buffer if enough space isn't provided for
it.
Index: fixpath.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/posix/sys/stat/fixpath.c,v
retrieving revision 1.7
diff -c -p -r1.7 fixpath.c
*** fixpath.c 17 Oct 2001 05:08:39 -0000 1.7
--- fixpath.c 21 Sep 2002 01:08:13 -0000
***************
*** 15,20 ****
--- 15,21 ----
#include <dos.h> /* For Win NT version check */
#include <sys/stat.h>
#include <libc/dosio.h>
+ #include <limits.h>
static unsigned use_lfn;
*************** static char *
*** 24,30 ****
__get_current_directory(char *out, int drive_number)
{
__dpmi_regs r;
! char tmpbuf[FILENAME_MAX];
memset(&r, 0, sizeof(r));
r.x.flags = 1; /* Set carry for safety */
--- 25,31 ----
__get_current_directory(char *out, int drive_number)
{
__dpmi_regs r;
! char tmpbuf[PATH_MAX];
memset(&r, 0, sizeof(r));
r.x.flags = 1; /* Set carry for safety */
*************** __get_current_directory(char *out, int d
*** 71,77 ****
r.x.ax = 0x7160;
r.x.cx = 0x8002; /* Get Long Path Name, using subst drive basis */
r.x.es = __tb_segment;
! r.x.di = __tb_offset + FILENAME_MAX;
tmpbuf[0] = drive_number + 'A';
tmpbuf[1] = ':';
--- 72,78 ----
r.x.ax = 0x7160;
r.x.cx = 0x8002; /* Get Long Path Name, using subst drive basis */
r.x.es = __tb_segment;
! r.x.di = __tb_offset + PATH_MAX;
tmpbuf[0] = drive_number + 'A';
tmpbuf[1] = ':';
*************** __get_current_directory(char *out, int d
*** 83,89 ****
if (!(r.x.flags & 1))
{
! dosmemget(__tb + FILENAME_MAX, sizeof(tmpbuf), tmpbuf);
/* Validate return form and drive matches what _fixpath expects. */
if (tmpbuf[0] == (drive_number + 'A') && tmpbuf[1] == ':')
--- 84,90 ----
if (!(r.x.flags & 1))
{
! dosmemget(__tb + PATH_MAX, sizeof(tmpbuf), tmpbuf);
/* Validate return form and drive matches what _fixpath expects. */
if (tmpbuf[0] == (drive_number + 'A') && tmpbuf[1] == ':')
*************** is_term(int c)
*** 117,123 ****
return c == '/' || c == '\\' || c == '\0';
}
! /* Takes as input an arbitrary path. Fixes up the path by:
1. Removing consecutive slashes
2. Removing trailing slashes
3. Making the path absolute if it wasn't already
--- 118,125 ----
return c == '/' || c == '\\' || c == '\0';
}
! /* Wrapper for the functions realpath and _fixpath.
! Takes as input an arbitrary path. Fixes up the path by:
1. Removing consecutive slashes
2. Removing trailing slashes
3. Making the path absolute if it wasn't already
*************** is_term(int c)
*** 125,144 ****
5. Removing ".." entries in the path (and the directory above them)
6. Adding a drive specification if one wasn't there
7. Converting all slashes to '/'
! */
! void
! _fixpath(const char *in, char *out)
{
int drive_number;
! char in1[FILENAME_MAX];
char *ip;
char *op = out;
int preserve_case = _preserve_fncase();
char *name_start;
int mbsize;
use_lfn = _use_lfn(in);
/* Perform the same magic conversions that _put_path does. */
_put_path(in);
dosmemget(__tb, sizeof(in1), in1);
--- 127,150 ----
5. Removing ".." entries in the path (and the directory above them)
6. Adding a drive specification if one wasn't there
7. Converting all slashes to '/'
! */
!
! char *
! __canonicalize_path(const char *in, char *out)
{
int drive_number;
! char in1[PATH_MAX];
char *ip;
char *op = out;
int preserve_case = _preserve_fncase();
char *name_start;
int mbsize;
+ char *op_limit;
use_lfn = _use_lfn(in);
+ op_limit = op + PATH_MAX;
+
/* Perform the same magic conversions that _put_path does. */
_put_path(in);
dosmemget(__tb, sizeof(in1), in1);
*************** _fixpath(const char *in, char *out)
*** 160,166 ****
if (*ip <= 'Z')
*op++ = drive_number + 'a';
else
! *op++ = *ip;
++ip;
}
*op++ = *ip++;
--- 166,172 ----
if (*ip <= 'Z')
*op++ = drive_number + 'a';
else
! * op++ = *ip;
++ip;
}
*op++ = *ip++;
*************** _fixpath(const char *in, char *out)
*** 213,218 ****
--- 219,231 ----
continue;
}
+ /* Buffer overflow check. */
+ if (op >= op_limit)
+ {
+ errno = ENAMETOOLONG;
+ return NULL;
+ }
+
/* Copy path component from in to out */
*op++ = '/';
#if 0
*************** _fixpath(const char *in, char *out)
*** 229,234 ****
--- 242,254 ----
}
else
*op++ = *ip++;
+
+ /* Check for buffer overflow. */
+ if (op >= op_limit)
+ {
+ errno = ENAMETOOLONG;
+ return NULL;
+ }
}
#endif
}
*************** _fixpath(const char *in, char *out)
*** 236,248 ****
/* If root directory, insert trailing slash */
if (op == out + 2) *op++ = '/';
/* Null terminate the output */
*op = '\0';
/* switch FOO\BAR to foo/bar, downcase where appropriate */
for (op = out + 3, name_start = op - 1; *name_start; op++)
{
! char long_name[FILENAME_MAX];
#if 1
/* skip multibyte character */
--- 256,275 ----
/* If root directory, insert trailing slash */
if (op == out + 2) *op++ = '/';
+ /* Check for buffer overflow. */
+ if (op >= op_limit)
+ {
+ errno = ENAMETOOLONG;
+ return NULL;
+ }
+
/* Null terminate the output */
*op = '\0';
/* switch FOO\BAR to foo/bar, downcase where appropriate */
for (op = out + 3, name_start = op - 1; *name_start; op++)
{
! char long_name[PATH_MAX];
#if 1
/* skip multibyte character */
*************** _fixpath(const char *in, char *out)
*** 286,298 ****
else if (*op == '\0')
break;
}
}
#ifdef TEST
int main (int argc, char *argv[])
{
! char fixed[FILENAME_MAX];
__dpmi_regs r;
if (argc > 2) {
--- 313,333 ----
else if (*op == '\0')
break;
}
+
+ return out;
+ }
+
+ void
+ _fixpath(const char *in, char *out)
+ {
+ __canonicalize_path(in, out);
}
#ifdef TEST
int main (int argc, char *argv[])
{
! char fixed[PATH_MAX];
__dpmi_regs r;
if (argc > 2) {
- Raw text -