wine_get_unix_file_name, GetShortPathNameA and GetLongPathNameA
Michael Wetherell
mike.wetherell at ntlworld.com
Wed Apr 24 15:41:39 CDT 2002
I forgot the changelog on the last post, and I also forgot to switch off
line breaks, so I thought I'd better post it again.
ChangeLog:
* files/dos_fs.c, files/drives.c
Mike Wetherell <mike.wetherell at ntlworld.com>
Fix handling of unix absolute paths in DOSFS_GetFullName and
GetShortPathNameA. Handle '..' in paths in DRIVE_FindDriveRoot.
Index: files/dos_fs.c
===================================================================
RCS file: /home/wine/wine/files/dos_fs.c,v
retrieving revision 1.103
diff -u -r1.103 dos_fs.c
--- files/dos_fs.c 2 Apr 2002 02:46:27 -0000 1.103
+++ files/dos_fs.c 21 Apr 2002 23:52:05 -0000
@@ -866,6 +866,7 @@
*/
BOOL DOSFS_GetFullName( LPCSTR name, BOOL check_last, DOS_FULL_NAME *full )
{
+ BOOL unixabsolute = *name == '/';
BOOL found;
UINT flags;
char *p_l, *p_s, *root;
@@ -893,7 +894,7 @@
{
while ((*name == '\\') || (*name == '/')) name++;
}
- else /* Relative path */
+ else if (!unixabsolute) /* Relative path */
{
lstrcpynA( root + 1, DRIVE_GetUnixCwd( full->drive ),
sizeof(full->long_name) - (root - full->long_name) - 1 );
@@ -1026,6 +1027,7 @@
DWORD sp = 0, lp = 0;
int tmplen, drive;
UINT flags;
+ BOOL unixabsolute = *longpath == '/';
TRACE("%s\n", debugstr_a(longpath));
@@ -1052,6 +1054,13 @@
if ( ( drive = DOSFS_GetPathDrive ( &longpath )) == -1 ) return 0;
flags = DRIVE_GetFlags ( drive );
+
+ if ( unixabsolute ) {
+ tmpshortpath[0] = drive + 'A';
+ tmpshortpath[1] = ':';
+ tmpshortpath[2] = '\\';
+ sp = 3;
+ }
while ( longpath[lp] ) {
Index: files/drive.c
===================================================================
RCS file: /home/wine/wine/files/drive.c,v
retrieving revision 1.67
diff -u -r1.67 drive.c
--- files/drive.c 9 Mar 2002 23:50:37 -0000 1.67
+++ files/drive.c 21 Apr 2002 23:52:15 -0000
@@ -364,53 +364,60 @@
*/
int DRIVE_FindDriveRoot( const char **path )
{
- /* idea: check at all '/' positions.
- * If the device and inode of that path is identical with the
- * device and inode of the current drive then we found a solution.
- * If there is another drive pointing to a deeper position in
- * the file tree, we want to find that one, not the earlier solution.
+ /* Starting with the full path, check if the device and inode match any of
+ * the wine 'drives'. If not then remove the last path component and try
+ * again. If the last component was a '..' then skip a normal component
+ * since it's a directory that's ascended back out of.
*/
- int drive, rootdrive = -1;
+ int drive, level, len;
char buffer[MAX_PATHNAME_LEN];
- char *next = buffer;
- const char *p = *path;
+ char *p;
struct stat st;
- strcpy( buffer, "/" );
- for (;;)
- {
- if (stat( buffer, &st ) || !S_ISDIR( st.st_mode )) break;
+ strcpy( buffer, *path );
+ while ((p = strchr( buffer, '\\' )) != NULL)
+ *p = '/';
+ len = strlen(buffer);
+ while (len > 0)
+ {
/* Find the drive */
-
- for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
+ if (stat( buffer, &st ) == 0 && S_ISDIR( st.st_mode ))
{
- if (!DOSDrives[drive].root ||
- (DOSDrives[drive].flags & DRIVE_DISABLED)) continue;
-
- if ((DOSDrives[drive].dev == st.st_dev) &&
- (DOSDrives[drive].ino == st.st_ino))
- {
- rootdrive = drive;
- *path = p;
- break;
- }
+ for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
+ {
+ if (!DOSDrives[drive].root ||
+ (DOSDrives[drive].flags & DRIVE_DISABLED))
+ continue;
+
+ if ((DOSDrives[drive].dev == st.st_dev) &&
+ (DOSDrives[drive].ino == st.st_ino))
+ {
+ TRACE( "%s -> drive %c:, root='%s', name='%s'\n",
+ *path, 'A' + drive, buffer, *path + len);
+ *path += len;
+ return drive;
+ }
+ }
}
- /* Get the next path component */
-
- *next++ = '/';
- while ((*p == '/') || (*p == '\\')) p++;
- if (!*p) break;
- while (!IS_END_OF_NAME(*p)) *next++ = *p++;
- *next = 0;
+ level = 0;
+ while (len > 0 && level < 1)
+ {
+ /* strip off a trailing slash */
+ while (len > 0 && buffer[len - 1] == '/')
+ buffer[--len] = 0;
+ /* find start of the last path component */
+ while (len > 0 && buffer[len - 1] != '/')
+ --len;
+ /* does removing it take us up a level? */
+ if (strcmp( buffer + len, "." ) != 0)
+ level += strcmp( buffer + len, ".." ) ? 1 : -1;
+ buffer[len] = 0;
+ }
}
- *next = 0;
- if (rootdrive != -1)
- TRACE("%s -> drive %c:, root='%s', name='%s'\n",
- buffer, 'A' + rootdrive, DOSDrives[rootdrive].root, *path );
- return rootdrive;
+ return -1;
}
More information about the wine-patches
mailing list