#endif
#include <fcntl.h>
#include <assert.h>
+
+/* For TIOCGWINSZ and friends: */
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
+#ifdef HAVE_TERMIOS_H
+# include <termios.h>
+#endif
#include "wget.h"
#include "utils.h"
return copy;
}
+/* Return a count of how many times CHR occurs in STRING. */
+
+int
+count_char (const char *string, char chr)
+{
+ const char *p;
+ int count = 0;
+ for (p = string; *p; p++)
+ if (*p == chr)
+ ++count;
+ return count;
+}
+
/* Copy the string formed by two pointers (one on the beginning, other
on the char after the last char) to a new, malloc-ed location.
0-terminate it. */
Non-leading `../'s and trailing `..'s are handled by removing
portions of the path.
- E.g. "a/b/c/./../d/.." will yield "a/b". This function originates
- from GNU Bash.
+ E.g. "a/b/c/./../d/.." will yield "a/b/". This function originates
+ from GNU Bash and has been mutilated to unrecognition for use in
+ Wget.
Changes for Wget:
Always use '/' as stub_char.
Don't check for local things using canon_stat.
Change the original string instead of strdup-ing.
React correctly when beginning with `./' and `../'.
- Don't zip out trailing slashes. */
+ Don't zip out trailing slashes.
+ Return a value indicating whether any modifications took place.
+
+ If you dare change this function, take a careful look at the test
+ cases below, and make sure that they pass. */
+
int
path_simplify (char *path)
{
register int i, start;
int changes = 0;
- char stub_char;
if (!*path)
return 0;
- stub_char = '/';
-
if (path[0] == '/')
/* Preserve initial '/'. */
++path;
return changes;
}
+
+/* Test cases:
+ ps("") -> ""
+ ps("/") -> "/"
+ ps(".") -> ""
+ ps("..") -> ""
+ ps("/.") -> "/"
+ ps("/..") -> "/"
+ ps("foo") -> "foo"
+ ps("foo/bar") -> "foo/bar"
+ ps("foo//bar") -> "foo/bar" (possibly a bug)
+ ps("foo/../bar") -> "bar"
+ ps("foo/bar/..") -> "foo/"
+ ps("foo/bar/../x") -> "foo/x"
+ ps("foo/bar/../x/") -> "foo/x/"
+ ps("foo/..") -> ""
+ ps("/foo/..") -> "/"
+ ps("a/b/../../c") -> "c"
+ ps("/a/b/../../c") -> "/c"
+ ps("./a/../b") -> "b"
+ ps("/./a/../b") -> "/b"
+*/
\f
/* "Touch" FILE, i.e. make its atime and mtime equal to the time
specified with TM. */
}
/* Merge BASE with FILE. BASE can be a directory or a file name, FILE
- should be a file name. For example, file_merge("/foo/bar", "baz")
- will return "/foo/baz". file_merge("/foo/bar/", "baz") will return
- "foo/bar/baz".
+ should be a file name.
+
+ file_merge("/foo/bar", "baz") => "/foo/baz"
+ file_merge("/foo/bar/", "baz") => "/foo/bar/baz"
+ file_merge("foo", "bar") => "bar"
In other words, it's a simpler and gentler version of uri_merge_1. */
const char *cut = (const char *)strrchr (base, '/');
if (!cut)
- cut = base + strlen (base);
+ return xstrdup (file);
result = (char *)xmalloc (cut - base + 1 + strlen (file) + 1);
memcpy (result, base, cut - base);
match_backwards ("abc", "bc") -> 1
match_backwards ("abc", "ab") -> 0
match_backwards ("abc", "abc") -> 1 */
-static int
-match_backwards (const char *string, const char *pattern)
+int
+match_tail (const char *string, const char *pattern)
{
int i, j;
}
/* Checks whether string S matches each element of ACCEPTS. A list
- element are matched either with fnmatch() or match_backwards(),
+ element are matched either with fnmatch() or match_tail(),
according to whether the element contains wildcards or not.
If the BACKWARD is 0, don't do backward comparison -- just compare
{
if (backward)
{
- if (match_backwards (s, *accepts))
+ if (match_tail (s, *accepts))
return 1;
}
else
return 0;
}
-/* Return the malloc-ed suffix of STR. For instance:
+/* Return the location of STR's suffix (file extension). Examples:
suffix ("foo.bar") -> "bar"
suffix ("foo.bar.baz") -> "baz"
suffix ("/foo/bar") -> NULL
{
int i;
- for (i = strlen (str); i && str[i] != '/' && str[i] != '.'; i--);
+ for (i = strlen (str); i && str[i] != '/' && str[i] != '.'; i--)
+ ;
+
if (str[i++] == '.')
- return xstrdup (str + i);
+ return (char *)str + i;
else
return NULL;
}
/* Read a line from FP. The function reallocs the storage as needed
to accomodate for any length of the line. Reallocs are done
- storage exponentially, doubling the storage after each overflow to
- minimize the number of calls to realloc() and fgets(). The newline
+ exponentially, doubling the storage after each overflow to minimize
+ the number of calls to realloc() and fgets(). The newline
character at the end of line is retained.
After end-of-file is encountered without anything being read, NULL
is returned. NULL is also returned on error. To distinguish
- between these two cases, use the stdio function ferror(). */
+ between these two cases, use the stdio function ferror().
+
+ A future version of this function will be rewritten to use fread()
+ instead of fgets(), and to return the length of the line, which
+ will make the function usable on files with binary content. */
char *
read_whole_line (FILE *fp)
while (fgets (line + length, bufsize - length, fp))
{
length += strlen (line + length);
- assert (length > 0);
+ if (length == 0)
+ /* Possible for example when reading from a binary file where
+ a line begins with \0. */
+ continue;
+
if (line[length - 1] == '\n')
break;
+
/* fgets() guarantees to read the whole line, or to use up the
space we've given it. We can double the buffer
unconditionally. */
return wsz.ws_col;
#endif /* TIOCGWINSZ */
}
+
+#if 0
+/* A debugging function for checking whether an MD5 library works. */
+
+#include "gen-md5.h"
+
+char *
+debug_test_md5 (char *buf)
+{
+ unsigned char raw[16];
+ static char res[33];
+ unsigned char *p1;
+ char *p2;
+ int cnt;
+ ALLOCA_MD5_CONTEXT (ctx);
+
+ gen_md5_init (ctx);
+ gen_md5_update ((unsigned char *)buf, strlen (buf), ctx);
+ gen_md5_finish (ctx, raw);
+
+ p1 = raw;
+ p2 = res;
+ cnt = 16;
+ while (cnt--)
+ {
+ *p2++ = XDIGIT_TO_xchar (*p1 >> 4);
+ *p2++ = XDIGIT_TO_xchar (*p1 & 0xf);
+ ++p1;
+ }
+ *p2 = '\0';
+
+ return res;
+}
+#endif