On 14 Jan 2002 at 15:42, Ian Abbott wrote:
> On 14 Jan 2002 at 15:00, Herold Heiko wrote:
>
> > On the other hand, a little research in src/utils.c, make_directory()
> > clearly shows only '/' is used as a directory separator.
> >
> > I'm wondering where the correct place for patching this (#ifdef WINDOWS
> > obviously) would be - I suppose main.c, about line 648,
> > case 'P':
> > setval ("dirprefix", optarg);
> > break;
> >
> > would be ok ? Or better call something in mswindows.c ? This would leave
> > all the internal representation like before.
>
> A possible change is to make cmd_file() in init.c remap '\' to '/'
> when compiled for MS Windows. The C library for Windows seems to
> cope with either character as a directory separator.
>
> Then there is just the -P C: part of the problem to deal with. I
> haven't investigated that properly yet, but I guess some bit of
> code is looking for a relative subdirectory named C: or something.
Here is a patch to deal with the -P C:\temp (and similar) problems
on Windows.
Firstly, I changed cmd_file() in init.c to allow '\' as a directory
separator for Windows, and to change all occurences of '\' to '/'
for consistency with the remainder of Wget, since the Windows C
libraries allow '/' to be used as a directory separator. This
allows you to use directory prefixes such as /temp or \temp under
Windows.
Next I added a cmd_directory() function in init.c, which is just
like cmd_file(), but strips off any trailing directory separators,
and made the -P (dirprefix) option call cmd_directory instead of
cmd_file. This allows you to use directory prefixes such as /temp/
or \temp\ under windows. The degenerate case of '/' (or '\') ends
up as a zero-length string but that is okay because when Wget uses
the directory prefix it appends '/' to it anyway (except when the
directory prefix is '.'). Using either -P / or -P "" effectively
results in files being placed in the root directory.
Next I changed make_directory() in utils.c to allow mkdir() to
fail, but to return the result of the final call to mkdir() (except
when a subsequent call to file_exists_p() for the next path
component returns true, in which case a previous mkdir() failure is
ignored). This allows directory prefixes such as c:\temp or c:/temp
to be used and also allows prefixes such as \\server\share\dir
to be used to use a directory on a SMB (network) share.
It works with everything I've thrown at it so far and the UNIX
stuff still works. Apart from -P "" behaving a bit strangely (same
as -P /), the other slight oddity is -P C: which behaves the same
as -P C:/ and causes files to be created in the root directory of
drive C:, rather than the current directory of drive C: as might be
expected by a Windows/DOS user.
And I lied: I actually made the changes in the reverse order to
what I stated!
src/ChangeLog:
2002-01-15 Ian Abbott <[EMAIL PROTECTED]>
* init.c (cmd_file): Change `\' to `/' for Windows (yes, really!)
(cmd_directory): New function. Like cmd_file(), but strips
trailing directory separators.
(commands): Change action for "dirprefix" from `cmd_file' to
`cmd_directory'.
* utils.c (make_directory): Allow intermediate `mkdir' calls to
fail, as not all path components that do not exist should be
directory components, especially under Windows.
Index: src/init.c
===================================================================
RCS file: /pack/anoncvs/wget/src/init.c,v
retrieving revision 1.44
diff -u -r1.44 init.c
--- src/init.c 2001/12/13 19:19:03 1.44
+++ src/init.c 2002/01/15 18:12:43
@@ -79,6 +79,7 @@
CMD_DECLARE (cmd_number_inf);
CMD_DECLARE (cmd_string);
CMD_DECLARE (cmd_file);
+CMD_DECLARE (cmd_directory);
CMD_DECLARE (cmd_time);
CMD_DECLARE (cmd_vector);
@@ -117,7 +118,7 @@
{ "debug", &opt.debug, cmd_boolean },
#endif
{ "deleteafter", &opt.delete_after, cmd_boolean },
- { "dirprefix", &opt.dir_prefix, cmd_file },
+ { "dirprefix", &opt.dir_prefix, cmd_directory },
{ "dirstruct", NULL, cmd_spec_dirstruct },
{ "domains", &opt.domains, cmd_vector },
{ "dotbytes", &opt.dot_bytes, cmd_bytes },
@@ -674,7 +675,11 @@
/* #### If VAL is empty, perhaps should set *CLOSURE to NULL. */
- if (!enable_tilde_expansion || !(*val == '~' && *(val + 1) == '/'))
+ if (!enable_tilde_expansion || !(*val == '~' && (*(val + 1) == '/'
+#ifdef WINDOWS
+ || *(val + 1) == '\\'
+#endif
+ )))
{
noexpand:
*pstring = xstrdup (val);
@@ -688,12 +693,21 @@
goto noexpand;
homelen = strlen (home);
- while (homelen && home[homelen - 1] == '/')
+ while (homelen && (home[homelen - 1] == '/'
+#ifdef WINDOWS
+ || home[homelen - 1] == '\\'
+#endif
+ ))
home[--homelen] = '\0';
/* Skip the leading "~/". */
+#ifdef WINDOWS
+ for (++val; *val == '/' || *val == '\\'; val++)
+ ;
+#else
for (++val; *val == '/'; val++)
;
+#endif
result = xmalloc (homelen + 1 + strlen (val));
memcpy (result, home, homelen);
@@ -702,6 +716,29 @@
*pstring = result;
}
+#ifdef WINDOWS
+ /* Convert "\" to "/". */
+ {
+ char *s;
+ for (s = *pstring; *s; s++)
+ if (*s == '\\')
+ *s = '/';
+ }
+#endif
+ return 1;
+}
+
+/* Like cmd_file, but strips trailing '/' characters. */
+static int
+cmd_directory (const char *com, const char *val, void *closure)
+{
+ char *s, *t;
+ if (!cmd_file (com, val, closure))
+ return 0;
+ s = *(char **)closure;
+ t = s + strlen (s);
+ while (t > s && *--t == '/')
+ *t = '\0';
return 1;
}
Index: src/utils.c
===================================================================
RCS file: /pack/anoncvs/wget/src/utils.c,v
retrieving revision 1.43
diff -u -r1.43 utils.c
--- src/utils.c 2001/12/17 14:05:08 1.43
+++ src/utils.c 2002/01/15 18:12:49
@@ -579,6 +579,7 @@
{
int quit = 0;
int i;
+ int ret = 0;
char *dir;
/* Make a copy of dir, to be able to write to it. Otherwise, the
@@ -594,18 +595,19 @@
if (!dir[i])
quit = 1;
dir[i] = '\0';
- /* Check whether the directory already exists. */
+ /* Check whether the directory already exists. Allow creation of
+ of intermediate directories to fail, as the initial path components
+ are not necessarily directories! */
if (!file_exists_p (dir))
- {
- if (mkdir (dir, 0777) < 0)
- return -1;
- }
+ ret = mkdir (dir, 0777);
+ else
+ ret = 0;
if (quit)
break;
else
dir[i] = '/';
}
- return 0;
+ return ret;
}
/* Merge BASE with FILE. BASE can be a directory or a file name, FILE