Mail Archives: djgpp/2004/12/12/10:17:38
This is a multi-part message in MIME format.
------=____1102864594009_u)0iT_6e-o
Content-Type: text/plain; charset=windows-1255
Content-Transfer-Encoding: 7bit
i have recently run into a failure to open unc named files locate on a network, when the os is windows xp.
unc file format: \\servername\directory_tree\filename.
this occures with files named //servername/..., which is the default notation under djgpp (e.g., argv[0]).
thus, every filename should have the path separator converted to '\', before been submitted to open(), access(), etc.
fortunately, there is a routine in the djdev source tree, which is been called before any os file access: putpath().
the djdev source tree may be downloaded at ftp://ftp.delorie.com/pub/djgpp/current/v2/djlsr203.zip,
and src/libc/dos/io/putpath.c should be applied the following patch:
--- /dosdev/djgpp/src/libc/dos/io/putpath.c 1999-06-03 13:27:36.000000000 +0000
+++ ./putpath.c 2004-12-12 17:06:30.000000000 +0000
@@ -144,12 +144,17 @@
path = p + 5;
}
+ for (p = path; *p; ++p)
+ {
+ if (*p == '/')
+ *p = '\\';
+ }
/* collapse multiple slashes to a single slash */
- for (; *path; path++)
+ for (p = path; *p; ++p)
{
- if (path[0] != '/' || path[1] != '/')
+ if (*p != '\\' || *(p + 1) != '\\' || p == path)
{
- _farnspokeb(o, *path);
+ _farnspokeb(o, *p);
o++;
if (--space < 2) /* safety check */
break;
@@ -159,7 +164,7 @@
/* remove trailing slash if it doesn't
represent the root directory */
if (o-2 >= __tb+offset
- && _farnspeekb(o-1) == '/'
+ && _farnspeekb(o-1) == '\\'
&& _farnspeekb(o-2) != ':')
o--;
best would be to re-make the whole libc, but even mere linking of the patched putpath.c (included for your convenience) in your project will do the magic.
of course, this solution will help with dos compatible file systems only, but we are dealing with dos software.
best regards,
alex
------=____1102864594009_u)0iT_6e-o
Content-Type: text/plain;
name="putpath.c"
Content-Disposition: inline;
filename="putpath.c"
/* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
#include <libc/stubs.h>
#include <libc/dosio.h>
#include <libc/farptrgs.h>
#include <go32.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
static const char env_delim = '~';
/* Can't use stackavail, since it pollutes the namespace... */
static int __inline__
enough_stack_p(void)
{
extern unsigned __djgpp_stack_limit;
unsigned sp;
__asm__ __volatile__ ("movl %%esp,%k0\n" : "=r" (sp) : );
return (int) (sp - __djgpp_stack_limit) > 4*1024;
}
int
_put_path(const char *path)
{
return _put_path2(path, 0);
}
int
_put_path2(const char *path, int offset)
{
int o = __tb+offset;
int space = _go32_info_block.size_of_transfer_buffer - offset;
const char *p = path;
if (path == 0)
{
errno = EFAULT;
abort();
}
_farsetsel(_dos_ds);
if (p[0] && p[1] == ':')
p += 2;
if (strncmp(p, "/dev/", 5) == 0)
{
if (strcmp(p+5, "null") == 0)
path = "nul";
else if (strcmp(p+5, "tty") == 0)
path = "con";
else if (((p[5] >= 'a' && p[5] <= 'z')
|| (p[5] >= 'A' && p[5] <= 'Z'))
&& (p[6] == '/' || p[6] == '\\' || p[6] == '\0'))
{
/* map /dev/a/ to a:/ */
_farnspokeb(o++, p[5]);
_farnspokeb(o++, ':');
path = p + 6;
space -= 2;
}
else if (strncmp(p+5, "env", 3) == 0
&& (p[8] == '/' || p[8] == '\\') && p[9])
{
/* /dev/env/FOO/bar: expand env var FOO and generate %FOO%/bar */
char *var_name, *d;
char *var_value;
int new_offset;
int use_default = 1;
int c;
p += 9; /* point to the beginning of the variable name */
var_name = alloca(strlen (p) + 1);
for (d = var_name; *p && *p != '/' && *p != '\\'; *d++ = *p++)
if (*p == env_delim)
{
if (p[1] == env_delim) /* two ~ in a row mean a literal ~ */
p++;
else
break;
}
*d = '\0';
var_value = getenv(d = var_name);
if (var_value && *var_value)
{
/* The value of the env var can include special constructs
like /dev/x/foo or even a reference to another env var, so
we need to recursively invoke ourselves. */
if (!enough_stack_p())
{
/* This is probably a case of infinite recursion caused by
a self-referencing /dev/env/foo value, in which case
ENAMETOOLONG is probably right. But it could also happen
if they were short on stack to begin with, in which case
we would lie if we use ENAMETOOLONG. So: */
errno = ENOMEM;
return offset;
}
new_offset = _put_path2(var_value, offset);
space -= new_offset - offset;
o += new_offset - offset;
use_default = 0;
}
if (*p == env_delim) /* use or skip the default value if present */
{
for (++p; *p; p++)
{
if (*p == env_delim)
{
if (p[1] == env_delim)
p++;
else
break;
}
if (use_default)
*d++ = *p;
}
if (use_default)
{
*d = '\0';
/* The default value may use special constructs as well. */
if (!enough_stack_p()) /* infinite recursion? */
{
errno = ENOMEM;
return offset;
}
new_offset = _put_path2(var_name, offset);
space -= new_offset - offset;
o += new_offset - offset;
}
if (*p == env_delim) /* a luser could forget the trailing '~' */
p++;
}
/* if the rest of path begins with a slash, remove the trailing
slash in the transfer buffer */
if ((*p == '/' || *p == '\\') && o-1 >= __tb+offset
&& ((c = _farnspeekb(o-1)) == '/' || c == '\\'))
o--;
path = p;
}
else if (p[5])
path = p + 5;
}
for (p = path; *p; ++p)
{
if (*p == '/')
*p = '\\';
}
/* collapse multiple slashes to a single slash */
for (p = path; *p; ++p)
{
if (*p != '\\' || *(p + 1) != '\\' || p == path)
{
_farnspokeb(o, *p);
o++;
if (--space < 2) /* safety check */
break;
}
}
/* remove trailing slash if it doesn't
represent the root directory */
if (o-2 >= __tb+offset
&& _farnspeekb(o-1) == '\\'
&& _farnspeekb(o-2) != ':')
o--;
/* null terminate it */
_farnspokeb(o, 0);
return o - __tb;
}
------=____1102864594009_u)0iT_6e-o--
- Raw text -