Release 960114
[wine/gsoc-2012-control.git] / files / drive.c
blobae2558d6af737a2eee1c51ab32db731468726266
1 /*
2 * DOS drive handling functions
4 * Copyright 1993 Erik Bos
5 * Copyright 1996 Alexandre Julliard
6 */
8 #include <string.h>
9 #include <stdlib.h>
11 #include "windows.h"
12 #include "dos_fs.h"
13 #include "drive.h"
14 #include "file.h"
15 #include "msdos.h"
16 #include "task.h"
17 #include "xmalloc.h"
18 #include "stddebug.h"
19 #include "debug.h"
21 typedef struct
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 */
30 } DOSDRIVE;
32 static DOSDRIVE DOSDrives[MAX_DOS_DRIVES];
33 static int DRIVE_CurDrive = 0;
35 static HTASK DRIVE_LastTask = 0;
37 /***********************************************************************
38 * DRIVE_Init
40 int DRIVE_Init(void)
42 int i, count = 0;
43 char drive[2] = "A";
44 char path[MAX_PATHNAME_LEN];
45 char *p;
47 for (i = 0; i < MAX_DOS_DRIVES; i++, drive[0]++)
49 GetPrivateProfileString( "drives", drive, "",
50 path, sizeof(path)-1, WineIniFileName() );
51 if (path[0])
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;
62 count++;
64 dprintf_dosfs( stddeb, "Drive %c -> %s\n", 'A' + i,
65 path[0] ? path : "** None **" );
68 if (!count)
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)
87 DRIVE_CurDrive = i;
88 break;
91 return 1;
95 /***********************************************************************
96 * DRIVE_IsValid
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 );
125 return 0;
127 dprintf_dosfs( stddeb, "DRIVE_SetCurrentDrive: %c:\n", 'A' + drive );
128 DRIVE_CurDrive = drive;
129 if (pTask) pTask->curdrive = drive | 0x80;
130 return 1;
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 )
146 int drive;
147 const char *p1, *p2;
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;
153 p1 = *path;
154 p2 = DOSDrives[drive].root;
155 dprintf_dosfs( stddeb, "DRIVE_FindDriveRoot: checking %c: '%s'\n",
156 'A' + drive, p2 );
157 for (;;)
159 while ((*p1 == '\\') || (*p1 == '/')) p1++;
160 while (*p2 == '/') p2++;
161 while ((*p1 == *p2) && (*p2) && (*p2 != '/')) p1++, p2++;
162 if (!*p2)
164 if (IS_END_OF_NAME(*p1)) /* OK, found it */
166 *path = p1;
167 return drive;
170 else if (*p2 == '/')
172 if (IS_END_OF_NAME(*p1))
173 continue; /* Go to next path element */
175 break; /* No match, go to next drive */
178 return -1;
182 /***********************************************************************
183 * DRIVE_GetRoot
185 const char * DRIVE_GetRoot( int drive )
187 if (!DRIVE_IsValid( drive )) return NULL;
188 return DOSDrives[drive].root;
192 /***********************************************************************
193 * DRIVE_GetDosCwd
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 /***********************************************************************
214 * DRIVE_GetUnixCwd
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 /***********************************************************************
235 * DRIVE_GetLabel
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;
261 return 1;
265 /***********************************************************************
266 * DRIVE_Chdir
268 int DRIVE_Chdir( int drive, const char *path )
270 char buffer[MAX_PATHNAME_LEN];
271 const char *unix_cwd, *dos_cwd;
272 BYTE attr;
273 TDB *pTask = (TDB *)GlobalLock( GetCurrentTask() );
275 dprintf_dosfs( stddeb, "DRIVE_Chdir(%c:,%s)\n", 'A' + drive, path );
276 strcpy( buffer, "A:" );
277 buffer[0] += drive;
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 );
285 return 0;
287 unix_cwd += strlen( DOSDrives[drive].root );
288 while (*unix_cwd == '/') unix_cwd++;
289 buffer[2] = '/';
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();
307 return 1;
311 /***********************************************************************
312 * DRIVE_Disable
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 );
319 return 0;
321 DOSDrives[drive].disabled = 1;
322 return 1;
326 /***********************************************************************
327 * DRIVE_Enable
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 );
334 return 0;
336 DOSDrives[drive].disabled = 0;
337 return 1;
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;