[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 3/3] make path_combine() especially for filenames, n
From: |
Michael Tokarev |
Subject: |
[Qemu-devel] [PATCH 3/3] make path_combine() especially for filenames, not URLs |
Date: |
Wed, 12 Jan 2011 13:57:02 +0300 |
Currently the two routines tries to "understand" and skip <protocol>:
prefix in path arguments are path_combine() and path_is_absolute()
(the latter isn't used anywhere but in the former). This is wrong,
since notion of absolute path is, at least, protocol-specific.
The implementation is more wrong on windows where even non-absolute
paths but with drive name (d:foo) should be treated as absolute, as
in, one can't combine, say, c:\bar with d:foo forming c:\foo as
path_combine() currently does.
Introduce isslash() macro that works correctly on both windows and
unix, use it in is_windows_drive_prefix() (since any form of slash
can be used in constructs like //./), remove path_is_absolute() and
hardcode the trivial (but right) condition in path_combine(), and
simplify path_combine() further by removing <protocol>: handling
and unifying shash searching.
Signed-off-by: Michael Tokarev <address@hidden>
---
block.c | 72 +++++++++++++++++++++-----------------------------------------
1 files changed, 25 insertions(+), 47 deletions(-)
diff --git a/block.c b/block.c
index 42d6ff1..31a821d 100644
--- a/block.c
+++ b/block.c
@@ -71,6 +71,9 @@ static BlockDriverState *bs_snapshots;
static int use_bdrv_whitelist;
#ifdef _WIN32
+
+#define isslash(c) ((c) == '/' || (c) == '\\')
+
static int is_windows_drive_prefix(const char *filename)
{
return (((filename[0] >= 'a' && filename[0] <= 'z') ||
@@ -83,11 +86,17 @@ int is_windows_drive(const char *filename)
if (is_windows_drive_prefix(filename) &&
filename[2] == '\0')
return 1;
- if (strstart(filename, "\\\\.\\", NULL) ||
- strstart(filename, "//./", NULL))
- return 1;
+ if (isslash(filename[0] && isslash(filename[1]) &&
+ filename[2] == '.' && isslash(filename[3]))
+ return 1; /* special case: windows device "//./" */
return 0;
}
+
+#else
+
+#define isslash(c) ((c) == '/')
+#define is_windows_drive_prefix(filename) (0)
+
#endif
/* check if the path starts with "<protocol>:"
@@ -115,61 +124,30 @@ static char *path_has_protocol(const char *path)
(char*)p : NULL;
}
-int path_is_absolute(const char *path)
-{
- const char *p;
-#ifdef _WIN32
- /* specific case for names like: "\\.\d:" */
- if (*path == '/' || *path == '\\')
- return 1;
-#endif
- p = strchr(path, ':');
- if (p)
- p++;
- else
- p = path;
-#ifdef _WIN32
- return (*p == '/' || *p == '\\');
-#else
- return (*p == '/');
-#endif
-}
-
/* if filename is absolute, just copy it to dest. Otherwise, build a
- path to it by considering it is relative to base_path. URL are
- supported. */
+ path to it by considering it is relative to base_path.
+ This is really about filenames not URLs - we don't support
+ <protocol>: prefix in filename since it makes no sense, especially
+ if the protocol in base_path is not the same as in filename.
+ */
void path_combine(char *dest, int dest_size,
const char *base_path,
const char *filename)
{
- const char *p, *p1;
+ const char *p;
int len;
if (dest_size <= 0)
return;
- if (path_is_absolute(filename)) {
+ /* on windows, d:filename should be treated as absolute too */
+ if (isslash(filename[0]) || is_windows_drive_prefix(filename)) {
pstrcpy(dest, dest_size, filename);
} else {
- p = strchr(base_path, ':');
- if (p)
- p++;
- else
- p = base_path;
- p1 = strrchr(base_path, '/');
-#ifdef _WIN32
- {
- const char *p2;
- p2 = strrchr(base_path, '\\');
- if (!p1 || p2 > p1)
- p1 = p2;
- }
-#endif
- if (p1)
- p1++;
- else
- p1 = base_path;
- if (p1 > p)
- p = p1;
+ /* find last slash */
+ p = base_path + strlen(base_path);
+ while(p >= base_path && !isslash(*p))
+ --p;
+ p++;
len = p - base_path;
if (len > dest_size - 1)
len = dest_size - 1;
--
1.7.2.3
- [Qemu-devel] [PATCH 3/3] make path_combine() especially for filenames, not URLs,
Michael Tokarev <=