ftp.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2004/12/12/10:17:38

X-Authentication-Warning: delorie.com: mail set sender to djgpp-bounces using -f
From: <alexbodn AT 012 DOT net DOT il>
To: djgpp AT delorie DOT com
Subject: network files unc under windows xp
Date: Sun, 12 Dec 2004 17:16:34 +0200
MIME-Version: 1.0
Message-Id: <20041212151634.CMIQ11445.fep4@[212.117.129.234]>
Reply-To: djgpp AT delorie DOT com

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 &apos;\&apos;, 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 == &apos;/&apos;)
+       *p = &apos;\\&apos;;
+  }
   /* collapse multiple slashes to a single slash */
-  for (; *path; path++)
+  for (p = path; *p; ++p)
   {
-    if (path[0] != &apos;/&apos; || path[1] != &apos;/&apos;)
+    if (*p != &apos;\\&apos; || *(p + 1) != &apos;\\&apos; || 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&apos;t
      represent the root directory */
   if (o-2 >= __tb+offset
-      && _farnspeekb(o-1) == &apos;/&apos;
+      && _farnspeekb(o-1) == &apos;\\&apos;
       && _farnspeekb(o-2) != &apos;:&apos;)
     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 -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019