2 * DOS drive handling functions
4 * Copyright 1993 Erik Bos
5 * Copyright 1996 Alexandre Julliard
23 char *root
; /* root dir in Unix format without trailing '/' */
24 char *dos_cwd
; /* cwd in DOS format without leading or trailing '\' */
25 char *unix_cwd
; /* cwd in Unix format without leading or trailing '/' */
26 char label
[12]; /* drive label */
27 DWORD serial
; /* drive serial number */
28 WORD type
; /* drive type */
29 BYTE disabled
; /* disabled flag */
32 static DOSDRIVE DOSDrives
[MAX_DOS_DRIVES
];
33 static int DRIVE_CurDrive
= 0;
35 static HTASK DRIVE_LastTask
= 0;
37 /***********************************************************************
44 char path
[MAX_PATHNAME_LEN
];
47 for (i
= 0; i
< MAX_DOS_DRIVES
; i
++, drive
[0]++)
49 GetPrivateProfileString( "drives", drive
, "",
50 path
, sizeof(path
)-1, WineIniFileName() );
53 p
= path
+ strlen(path
) - 1;
54 while ((p
> path
) && ((*p
== '/') || (*p
== '\\'))) *p
-- = '\0';
55 DOSDrives
[i
].root
= xstrdup( path
);
56 DOSDrives
[i
].dos_cwd
= xstrdup( "" );
57 DOSDrives
[i
].unix_cwd
= xstrdup( "" );
58 sprintf( DOSDrives
[i
].label
, "DRIVE-%c ", drive
[0] );
59 DOSDrives
[i
].serial
= 0x12345678;
60 DOSDrives
[i
].type
= (i
< 2) ? DRIVE_REMOVABLE
: DRIVE_FIXED
;
61 DOSDrives
[i
].disabled
= 0;
64 dprintf_dosfs( stddeb
, "Drive %c -> %s\n", 'A' + i
,
65 path
[0] ? path
: "** None **" );
70 fprintf( stderr
, "Warning: no valid DOS drive found\n" );
71 /* Create a C drive pointing to Unix root dir */
72 DOSDrives
[i
].root
= xstrdup( "/" );
73 DOSDrives
[i
].dos_cwd
= xstrdup( "" );
74 DOSDrives
[i
].unix_cwd
= xstrdup( "" );
75 sprintf( DOSDrives
[i
].label
, "DRIVE-%c ", drive
[0] );
76 DOSDrives
[i
].serial
= 0x12345678;
77 DOSDrives
[i
].type
= DRIVE_FIXED
;
78 DOSDrives
[i
].disabled
= 0;
81 /* Make the first hard disk the current drive */
82 for (i
= 0; i
< MAX_DOS_DRIVES
; i
++, drive
[0]++)
84 if (DOSDrives
[i
].root
&& !DOSDrives
[i
].disabled
&&
85 DOSDrives
[i
].type
!= DRIVE_REMOVABLE
)
95 /***********************************************************************
98 int DRIVE_IsValid( int drive
)
100 if ((drive
< 0) || (drive
>= MAX_DOS_DRIVES
)) return 0;
101 return (DOSDrives
[drive
].root
&& !DOSDrives
[drive
].disabled
);
105 /***********************************************************************
106 * DRIVE_GetCurrentDrive
108 int DRIVE_GetCurrentDrive(void)
110 TDB
*pTask
= (TDB
*)GlobalLock( GetCurrentTask() );
111 if (pTask
&& (pTask
->curdrive
& 0x80)) return pTask
->curdrive
& ~0x80;
112 return DRIVE_CurDrive
;
116 /***********************************************************************
117 * DRIVE_SetCurrentDrive
119 int DRIVE_SetCurrentDrive( int drive
)
121 TDB
*pTask
= (TDB
*)GlobalLock( GetCurrentTask() );
122 if (!DRIVE_IsValid( drive
))
124 DOS_ERROR( ER_InvalidDrive
, EC_MediaError
, SA_Abort
, EL_Disk
);
127 dprintf_dosfs( stddeb
, "DRIVE_SetCurrentDrive: %c:\n", 'A' + drive
);
128 DRIVE_CurDrive
= drive
;
129 if (pTask
) pTask
->curdrive
= drive
| 0x80;
134 /***********************************************************************
135 * DRIVE_FindDriveRoot
137 * Find a drive for which the root matches the begginning of the given path.
138 * This can be used to translate a Unix path into a drive + DOS path.
139 * Return value is the drive, or -1 on error. On success, path is modified
140 * to point to the beginning of the DOS path.
141 * FIXME: this only does a textual comparison of the path names, and won't
142 * work well in the presence of symbolic links.
144 int DRIVE_FindDriveRoot( const char **path
)
149 dprintf_dosfs( stddeb
, "DRIVE_FindDriveRoot: searching '%s'\n", *path
);
150 for (drive
= 0; drive
< MAX_DOS_DRIVES
; drive
++)
152 if (!DOSDrives
[drive
].root
|| DOSDrives
[drive
].disabled
) continue;
154 p2
= DOSDrives
[drive
].root
;
155 dprintf_dosfs( stddeb
, "DRIVE_FindDriveRoot: checking %c: '%s'\n",
159 while ((*p1
== '\\') || (*p1
== '/')) p1
++;
160 while (*p2
== '/') p2
++;
161 while ((*p1
== *p2
) && (*p2
) && (*p2
!= '/')) p1
++, p2
++;
164 if (IS_END_OF_NAME(*p1
)) /* OK, found it */
172 if (IS_END_OF_NAME(*p1
))
173 continue; /* Go to next path element */
175 break; /* No match, go to next drive */
182 /***********************************************************************
185 const char * DRIVE_GetRoot( int drive
)
187 if (!DRIVE_IsValid( drive
)) return NULL
;
188 return DOSDrives
[drive
].root
;
192 /***********************************************************************
195 const char * DRIVE_GetDosCwd( int drive
)
197 TDB
*pTask
= (TDB
*)GlobalLock( GetCurrentTask() );
198 if (!DRIVE_IsValid( drive
)) return NULL
;
200 /* Check if we need to change the directory to the new task. */
201 if (pTask
&& (pTask
->curdrive
& 0x80) && /* The task drive is valid */
202 ((pTask
->curdrive
& ~0x80) == drive
) && /* and it's the one we want */
203 (DRIVE_LastTask
!= GetCurrentTask())) /* and the task changed */
205 /* Perform the task-switch */
206 if (!DRIVE_Chdir( drive
, pTask
->curdir
)) DRIVE_Chdir( drive
, "\\" );
207 DRIVE_LastTask
= GetCurrentTask();
209 return DOSDrives
[drive
].dos_cwd
;
213 /***********************************************************************
216 const char * DRIVE_GetUnixCwd( int drive
)
218 TDB
*pTask
= (TDB
*)GlobalLock( GetCurrentTask() );
219 if (!DRIVE_IsValid( drive
)) return NULL
;
221 /* Check if we need to change the directory to the new task. */
222 if (pTask
&& (pTask
->curdrive
& 0x80) && /* The task drive is valid */
223 ((pTask
->curdrive
& ~0x80) == drive
) && /* and it's the one we want */
224 (DRIVE_LastTask
!= GetCurrentTask())) /* and the task changed */
226 /* Perform the task-switch */
227 if (!DRIVE_Chdir( drive
, pTask
->curdir
)) DRIVE_Chdir( drive
, "\\" );
228 DRIVE_LastTask
= GetCurrentTask();
230 return DOSDrives
[drive
].unix_cwd
;
234 /***********************************************************************
237 const char * DRIVE_GetLabel( int drive
)
239 if (!DRIVE_IsValid( drive
)) return NULL
;
240 return DOSDrives
[drive
].label
;
244 /***********************************************************************
245 * DRIVE_GetSerialNumber
247 DWORD
DRIVE_GetSerialNumber( int drive
)
249 if (!DRIVE_IsValid( drive
)) return 0;
250 return DOSDrives
[drive
].serial
;
254 /***********************************************************************
255 * DRIVE_SetSerialNumber
257 int DRIVE_SetSerialNumber( int drive
, DWORD serial
)
259 if (!DRIVE_IsValid( drive
)) return 0;
260 DOSDrives
[drive
].serial
= serial
;
265 /***********************************************************************
268 int DRIVE_Chdir( int drive
, const char *path
)
270 char buffer
[MAX_PATHNAME_LEN
];
271 const char *unix_cwd
, *dos_cwd
;
273 TDB
*pTask
= (TDB
*)GlobalLock( GetCurrentTask() );
275 dprintf_dosfs( stddeb
, "DRIVE_Chdir(%c:,%s)\n", 'A' + drive
, path
);
276 strcpy( buffer
, "A:" );
278 lstrcpyn( buffer
+ 2, path
, sizeof(buffer
) - 2 );
280 if (!(unix_cwd
= DOSFS_GetUnixFileName( buffer
, TRUE
))) return 0;
281 if (!FILE_Stat( unix_cwd
, &attr
, NULL
, NULL
, NULL
)) return 0;
282 if (!(attr
& FA_DIRECTORY
))
284 DOS_ERROR( ER_FileNotFound
, EC_NotFound
, SA_Abort
, EL_Disk
);
287 unix_cwd
+= strlen( DOSDrives
[drive
].root
);
288 while (*unix_cwd
== '/') unix_cwd
++;
290 lstrcpyn( buffer
+ 3, unix_cwd
, sizeof(buffer
) - 3 );
291 if (!(dos_cwd
= DOSFS_GetDosTrueName( buffer
, TRUE
))) return 0;
293 dprintf_dosfs( stddeb
, "DRIVE_Chdir(%c:): unix_cwd=%s dos_cwd=%s\n",
294 'A' + drive
, unix_cwd
, dos_cwd
+ 3 );
296 free( DOSDrives
[drive
].dos_cwd
);
297 free( DOSDrives
[drive
].unix_cwd
);
298 DOSDrives
[drive
].dos_cwd
= xstrdup( dos_cwd
+ 3 );
299 DOSDrives
[drive
].unix_cwd
= xstrdup( unix_cwd
);
301 if (pTask
&& (pTask
->curdrive
& 0x80) &&
302 ((pTask
->curdrive
& ~0x80) == drive
))
304 lstrcpyn( pTask
->curdir
, dos_cwd
+ 2, sizeof(pTask
->curdir
) );
305 DRIVE_LastTask
= GetCurrentTask();
311 /***********************************************************************
314 int DRIVE_Disable( int drive
)
316 if ((drive
< 0) || (drive
>= MAX_DOS_DRIVES
) || !DOSDrives
[drive
].root
)
318 DOS_ERROR( ER_InvalidDrive
, EC_MediaError
, SA_Abort
, EL_Disk
);
321 DOSDrives
[drive
].disabled
= 1;
326 /***********************************************************************
329 int DRIVE_Enable( int drive
)
331 if ((drive
< 0) || (drive
>= MAX_DOS_DRIVES
) || !DOSDrives
[drive
].root
)
333 DOS_ERROR( ER_InvalidDrive
, EC_MediaError
, SA_Abort
, EL_Disk
);
336 DOSDrives
[drive
].disabled
= 0;
341 /***********************************************************************
342 * GetDriveType (KERNEL.136)
344 WORD
GetDriveType( INT drive
)
346 dprintf_dosfs( stddeb
, "GetDriveType(%c:)\n", 'A' + drive
);
347 if (!DRIVE_IsValid(drive
)) return 0;
348 return DOSDrives
[drive
].type
;