ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Windows/posix_emu.cpp
Revision: 1.2
Committed: 2008-01-01T09:40:33Z (16 years, 10 months ago) by gbeauche
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +1 -1 lines
Log Message:
Happy New Year!

File Contents

# User Rev Content
1 gbeauche 1.1 /*
2     * posix_emu.cpp -- posix and virtual desktop
3     *
4 gbeauche 1.2 * Basilisk II (C) 1997-2008 Christian Bauer
5 gbeauche 1.1 *
6     * Windows platform specific code copyright (C) Lauri Pesonen
7     *
8     * This program is free software; you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License as published by
10     * the Free Software Foundation; either version 2 of the License, or
11     * (at your option) any later version.
12     *
13     * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17     *
18     * You should have received a copy of the GNU General Public License
19     * along with this program; if not, write to the Free Software
20     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21     */
22    
23     // TODO: UNC names. Customizable "Virtual Desktop" location.
24    
25     #include "sysdeps.h"
26     #define NO_POSIX_API_HOOK
27     #include "posix_emu.h"
28     #include "user_strings.h"
29     #include "util_windows.h"
30     #include "main.h"
31     #include "extfs_defs.h"
32     #include "prefs.h"
33     #include <ctype.h>
34    
35    
36     #define DEBUG_EXTFS 0
37    
38     #if DEBUG_EXTFS
39    
40     // This must be always on.
41     #define DEBUG 1
42     #undef OutputDebugString
43     #define OutputDebugString extfs_log_write
44     extern void extfs_log_write( char *s );
45     #define EXTFS_LOG_FILE_NAME "extfs.log"
46     #include "debug.h"
47    
48     enum {
49     DB_EXTFS_NONE=0,
50     DB_EXTFS_NORMAL,
51     DB_EXTFS_LOUD
52     };
53     static int16 debug_extfs = DB_EXTFS_NONE;
54     static HANDLE extfs_log_file = INVALID_HANDLE_VALUE;
55    
56     static void extfs_log_open( char *path )
57     {
58     if(debug_extfs == DB_EXTFS_NONE) return;
59    
60     DeleteFile( path );
61     extfs_log_file = CreateFile(
62     path,
63     GENERIC_READ|GENERIC_WRITE,
64     FILE_SHARE_READ,
65     NULL,
66     CREATE_ALWAYS,
67     // FILE_FLAG_WRITE_THROUGH|FILE_FLAG_NO_BUFFERING,
68     FILE_FLAG_WRITE_THROUGH,
69     NULL
70     );
71     if( extfs_log_file == INVALID_HANDLE_VALUE ) {
72     ErrorAlert( "Could not create the EXTFS log file." );
73     }
74     }
75    
76     static void extfs_log_close( void )
77     {
78     if(debug_extfs == DB_EXTFS_NONE) return;
79    
80     if( extfs_log_file != INVALID_HANDLE_VALUE ) {
81     CloseHandle( extfs_log_file );
82     extfs_log_file = INVALID_HANDLE_VALUE;
83     }
84     }
85    
86     static void extfs_log_write( char *s )
87     {
88     DWORD bytes_written;
89    
90     // should have been checked already.
91     if(debug_extfs == DB_EXTFS_NONE) return;
92    
93     if( extfs_log_file != INVALID_HANDLE_VALUE ) {
94    
95     DWORD count = strlen(s);
96     if (0 == WriteFile(extfs_log_file, s, count, &bytes_written, NULL) ||
97     (int)bytes_written != count)
98     {
99     extfs_log_close();
100     ErrorAlert( "extfs log file write error (out of disk space?). Log closed." );
101     } else {
102     FlushFileBuffers( extfs_log_file );
103     }
104     }
105     }
106     #else
107    
108     #define DEBUG 0
109     #include "debug.h"
110    
111     #endif // DEBUG_EXTFS
112    
113     int my_errno = 0;
114    
115     #define VIRTUAL_ROOT_ID ((HANDLE)0xFFFFFFFE)
116    
117     static const char *desktop_name = "Virtual Desktop";
118     static const char *custom_icon_name = "Icon\r";
119     #define my_computer GetString(STR_EXTFS_VOLUME_NAME)
120    
121     static char lb1[MAX_PATH_LENGTH];
122     static char lb2[MAX_PATH_LENGTH];
123    
124     #define MRP(path) translate(path,lb1)
125     #define MRP2(path) translate(path,lb2)
126    
127     #define DISABLE_ERRORS UINT prevmode = SetErrorMode(SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS)
128     #define RESTORE_ERRORS SetErrorMode(prevmode);
129    
130     static char host_drive_list[512];
131     static char virtual_root[248]; // Not _MAX_PATH
132    
133     const uint8 my_comp_icon[2670] = {
134     0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0xD8, 0x00, 0x00, 0x08, 0xD8, 0x00, 0x00, 0x00, 0x96,
135     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
136     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
137     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
138     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
139     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
140     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
141     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
142     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
143     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
144     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
145     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
149     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
150     0x00, 0x00, 0x02, 0x00, 0x79, 0x79, 0x79, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xC0, 0xCC, 0xCC, 0xCC,
151     0xCC, 0xD7, 0x97, 0x97, 0x97, 0x97, 0x97, 0xC0, 0xC0, 0xC0, 0xC0, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
152     0xCD, 0xDB, 0xD9, 0x79, 0x79, 0x7E, 0x79, 0x0C, 0xDD, 0xCD, 0xDD, 0xCD, 0xCD, 0xDC, 0xDD, 0xCD,
153     0xCC, 0xED, 0xED, 0x97, 0x97, 0x97, 0x97, 0x0C, 0xE7, 0x78, 0x77, 0x97, 0x97, 0x97, 0x97, 0x97,
154     0xDC, 0xED, 0xDE, 0x79, 0x79, 0x79, 0x99, 0x0C, 0xD9, 0x7E, 0x5E, 0x65, 0x5E, 0x65, 0xD9, 0x79,
155     0xCD, 0xDE, 0xDD, 0x97, 0xE7, 0x9E, 0x77, 0xC0, 0x97, 0x9D, 0xCD, 0xCC, 0xC7, 0xCC, 0xE7, 0x97,
156     0xCC, 0xED, 0xEE, 0x79, 0x79, 0x79, 0x7E, 0xCC, 0x57, 0xD5, 0xD7, 0xD5, 0xDD, 0x5D, 0xD9, 0x7E,
157     0xCD, 0xDE, 0xDE, 0x79, 0x97, 0x97, 0x99, 0x0C, 0x87, 0xCD, 0x75, 0xC7, 0x5C, 0x7D, 0xD9, 0x79,
158     0xCD, 0xDD, 0xED, 0xE7, 0x7E, 0x79, 0x77, 0xCC, 0xE7, 0xB0, 0x00, 0xC0, 0x0C, 0xCD, 0xE7, 0x97,
159     0xDC, 0xED, 0xEE, 0x79, 0x97, 0x86, 0x79, 0xC0, 0xE7, 0xD0, 0x2C, 0xC1, 0xC2, 0xCD, 0xD9, 0x79,
160     0xCD, 0xDE, 0xDD, 0x97, 0x99, 0x79, 0x97, 0x0C, 0xE7, 0xB0, 0xD0, 0xDC, 0xCC, 0xCD, 0xD6, 0x87,
161     0xDD, 0xDE, 0xED, 0x79, 0x77, 0xE7, 0x79, 0x0C, 0x58, 0xDC, 0x0C, 0x0C, 0xCC, 0xCD, 0xE9, 0x79,
162     0xCD, 0xDD, 0xD5, 0x99, 0x97, 0x99, 0x79, 0xC0, 0x87, 0xD0, 0xC0, 0xC0, 0xC0, 0xCD, 0xD7, 0xE7,
163     0xDD, 0xDE, 0xD7, 0x97, 0x79, 0x77, 0xE7, 0x0C, 0xE7, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x79, 0x79,
164     0xCD, 0xDE, 0xD9, 0x79, 0x97, 0xE9, 0x79, 0x0C, 0x97, 0x79, 0x79, 0x79, 0x79, 0x79, 0x97, 0x97,
165     0xDC, 0xED, 0xE7, 0x97, 0x79, 0x97, 0x97, 0x0C, 0xCD, 0xD7, 0xD7, 0xD7, 0xE7, 0xE7, 0x7E, 0x79,
166     0xCD, 0xDE, 0x79, 0x79, 0x97, 0x7E, 0x79, 0xC0, 0xCC, 0xCC, 0x0C, 0xCC, 0x0D, 0xCC, 0xDC, 0xDC,
167     0xDC, 0xED, 0x97, 0x97, 0x77, 0x99, 0x79, 0xCC, 0xCC, 0xCC, 0xDC, 0xCC, 0xDC, 0xCC, 0xCC, 0x8D,
168     0xCD, 0xDE, 0x79, 0x79, 0x96, 0x77, 0x97, 0x97, 0x97, 0x90, 0xCC, 0xCD, 0xCD, 0xDD, 0xDD, 0xCC,
169     0xDD, 0xD9, 0x76, 0x87, 0x97, 0x99, 0x7E, 0x7C, 0x0C, 0xCC, 0xDD, 0xDD, 0xED, 0xDE, 0xDD, 0xEE,
170     0xDE, 0xD5, 0xBD, 0xDE, 0x79, 0x79, 0x9C, 0xC0, 0xCC, 0xDD, 0xDD, 0xDD, 0xDE, 0xDD, 0xED, 0xDE,
171     0xDE, 0xDD, 0xDE, 0xDE, 0x79, 0x79, 0x70, 0xCD, 0xCC, 0xCC, 0xCC, 0xCC, 0xDC, 0xDD, 0xDD, 0xDD,
172     0xDD, 0xDD, 0xED, 0xED, 0x97, 0x97, 0x90, 0xCC, 0x8D, 0xCC, 0xDC, 0xCD, 0xCC, 0xCC, 0xCC, 0xCC,
173     0xCC, 0xEE, 0xDE, 0xDE, 0x79, 0x7E, 0x70, 0xCC, 0x88, 0xDC, 0xCC, 0xCC, 0xCD, 0xDD, 0xDD, 0xDC,
174     0xCD, 0xDD, 0xED, 0xED, 0x97, 0x97, 0xEC, 0xCC, 0xCC, 0xCC, 0xDC, 0xCC, 0xCD, 0xDD, 0xED, 0xDD,
175     0xDC, 0xED, 0xED, 0xEE, 0x79, 0x79, 0xDC, 0x0D, 0xCC, 0xDC, 0xCC, 0xCD, 0xCC, 0xCC, 0xCC, 0x0C,
176     0xDC, 0xDE, 0xDE, 0xED, 0x97, 0xDC, 0xCC, 0xDC, 0xCD, 0xCC, 0xDC, 0xCD, 0xCC, 0xCC, 0xCD, 0xCC,
177     0xCC, 0xED, 0xED, 0x79, 0xDD, 0xC0, 0xCD, 0xCC, 0xDC, 0xCD, 0xCC, 0xDC, 0xCC, 0xDC, 0xDD, 0xCD,
178     0xCD, 0xED, 0x97, 0x97, 0xDD, 0xCC, 0xCC, 0x00, 0xC0, 0xDD, 0xCD, 0xCC, 0xCC, 0xCD, 0xD0, 0xDC,
179     0xDD, 0xF7, 0x99, 0x79, 0x97, 0x9D, 0xDD, 0xDD, 0xCC, 0xC0, 0xCC, 0x0C, 0xDC, 0xDC, 0xCD, 0xCD,
180     0xDF, 0x79, 0x77, 0x97, 0x79, 0x79, 0x79, 0x79, 0xDD, 0xDE, 0xDC, 0xCC, 0xCC, 0xC0, 0xC0, 0xDD,
181     0xE9, 0x79, 0x97, 0x99, 0x97, 0xE7, 0xE7, 0x97, 0x97, 0x9D, 0x79, 0xDD, 0xDD, 0xDD, 0xCD, 0xDE,
182     0x79, 0x79, 0x7E, 0x77, 0x00, 0x00, 0x04, 0x00, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0xF5,
183     0xF5, 0xF5, 0xF5, 0xF5, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B,
184     0x2B, 0x2B, 0xF9, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0xF6,
185     0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0xF7, 0xF7, 0xF7,
186     0xF7, 0xF8, 0x81, 0xFA, 0xFA, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B,
187     0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56,
188     0xF7, 0xF8, 0x81, 0x81, 0x81, 0xFA, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B,
189     0xA5, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2,
190     0xF8, 0xF8, 0x81, 0xFA, 0xFB, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B,
191     0xA5, 0xC2, 0xC2, 0xFB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xFB, 0xC2, 0xC2, 0xC2,
192     0xF7, 0xF8, 0x81, 0x81, 0xFB, 0x81, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF6, 0x2B,
193     0xA5, 0xC2, 0xC2, 0xFB, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x81, 0xC2, 0xC2, 0xC2,
194     0xF7, 0xF8, 0x81, 0x81, 0xFB, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF6, 0x2B,
195     0xA5, 0xC2, 0xF9, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xF9, 0xFB, 0xC2, 0xC2, 0xC2,
196     0xF7, 0xF8, 0x81, 0x81, 0xFB, 0x81, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B,
197     0xA5, 0xC2, 0xF9, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0xF9, 0x81, 0xC2, 0xC2, 0xC2,
198     0xF8, 0x56, 0xFA, 0x81, 0x81, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B,
199     0xA5, 0xC2, 0xF9, 0xF5, 0xF5, 0xF5, 0xF6, 0xF6, 0xF6, 0xF6, 0x2B, 0xF9, 0xFB, 0xC2, 0xC2, 0xC2,
200     0xF8, 0x56, 0x81, 0x81, 0xFB, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B,
201     0xA5, 0xC2, 0xF9, 0xF5, 0x0A, 0xF6, 0x2B, 0x0A, 0xF6, 0x0A, 0x2B, 0xF9, 0x81, 0xC2, 0xC2, 0xC2,
202     0xF8, 0x56, 0x81, 0x81, 0x81, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B,
203     0xA5, 0xC2, 0xF9, 0xF5, 0xF8, 0xF6, 0x56, 0xF7, 0xF7, 0xF8, 0x2B, 0xF9, 0x81, 0xC2, 0xC2, 0xC2,
204     0xF8, 0x56, 0x81, 0x81, 0xFB, 0x81, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B,
205     0xA5, 0xC2, 0xF9, 0xF5, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0x2B, 0x2B, 0xF9, 0xFB, 0xC2, 0xC2, 0xC2,
206     0xF8, 0x56, 0xFA, 0x81, 0x81, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B,
207     0xA5, 0xC2, 0xF9, 0xF6, 0xF6, 0xF5, 0xF6, 0xF6, 0xF6, 0xF6, 0x2B, 0xF9, 0x81, 0xC2, 0xC2, 0xC2,
208     0xF8, 0x56, 0x81, 0x81, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B,
209     0xA5, 0xC2, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xC2, 0xC2, 0xC2, 0xC2,
210     0xF8, 0x56, 0x81, 0x81, 0x81, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B,
211     0xA5, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2,
212     0xF8, 0x56, 0x81, 0x81, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B,
213     0xF7, 0x56, 0xF8, 0x7A, 0x7A, 0x9E, 0x9E, 0x9E, 0x9E, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2,
214     0xF8, 0x56, 0x81, 0xFA, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B,
215     0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0xF7, 0xF7, 0xF8, 0xF8,
216     0xF8, 0x56, 0x81, 0x81, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF7, 0xF7,
217     0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0x56, 0xB9, 0xF8,
218     0xF8, 0x56, 0x81, 0x81, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2,
219     0xC2, 0xC2, 0xC2, 0xF6, 0x2B, 0x2B, 0xF7, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0xF8,
220     0xF8, 0x56, 0x81, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF6,
221     0xF6, 0xF6, 0x2B, 0xF8, 0x56, 0xFA, 0xF9, 0x81, 0x81, 0x81, 0xFA, 0x81, 0x81, 0x81, 0xFB, 0x81,
222     0xFB, 0xFB, 0xFB, 0x81, 0xFA, 0xFA, 0xFA, 0x81, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF6, 0xF6, 0xF6,
223     0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFB,
224     0x81, 0xFB, 0xF9, 0xFA, 0xFA, 0xFB, 0x81, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B, 0xF7,
225     0xF8, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0xF8, 0xF8, 0x56, 0x56, 0xF9, 0xF9, 0xF9, 0xFA,
226     0xFA, 0xFA, 0xFA, 0x81, 0x81, 0xFB, 0x81, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B, 0xF7,
227     0x93, 0xA0, 0xF7, 0xF7, 0xF8, 0xF7, 0xF7, 0xF8, 0xF7, 0xF7, 0xF7, 0xF7, 0x2B, 0x2B, 0x2B, 0x2B,
228     0x2B, 0x2B, 0x81, 0xFB, 0x81, 0xFB, 0xFB, 0x81, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B, 0xF7,
229     0xA0, 0xA0, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0x56, 0x56, 0xF9, 0xF9, 0xF9, 0xF8, 0xF7,
230     0xF7, 0xF7, 0xFB, 0xFB, 0x81, 0xFB, 0x81, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF5, 0x2B, 0xF7,
231     0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF9, 0xF9, 0xFB, 0xFB, 0xFB, 0xF8, 0xF9,
232     0xF9, 0xF7, 0x81, 0xFB, 0xFB, 0x81, 0xFB, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xF8, 0x2B, 0x2B, 0x56,
233     0x2B, 0x2B, 0xF9, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0xF8,
234     0xF8, 0xF7, 0xFB, 0xFB, 0x81, 0xFB, 0x81, 0xFB, 0xC2, 0xC2, 0xF8, 0xF8, 0xF6, 0xF6, 0xF9, 0xF8,
235     0x2B, 0xF9, 0xF8, 0x2B, 0xF9, 0x2B, 0x2B, 0xF9, 0x2B, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7,
236     0xF7, 0xF7, 0x81, 0xFB, 0x81, 0xFB, 0xC2, 0xC2, 0xF9, 0xF8, 0xF6, 0xF6, 0xF7, 0xF9, 0xF8, 0x2B,
237     0xF9, 0xF8, 0xF6, 0xF9, 0xF8, 0xF6, 0xF9, 0xF8, 0xF6, 0x2B, 0xF9, 0x2B, 0xF9, 0x56, 0x2B, 0xF9,
238     0x2B, 0xF9, 0xAC, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xFA, 0xF9, 0xF8, 0x2B, 0x2B, 0x2B, 0xF5, 0xF5,
239     0xF5, 0xF5, 0xF9, 0xF8, 0xF6, 0xF9, 0xF8, 0xF6, 0x2B, 0xF8, 0x2B, 0xF9, 0x56, 0x2B, 0x56, 0x2B,
240     0x56, 0x81, 0xAC, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xFA, 0xFA, 0xFA, 0xF9, 0xF8,
241     0xF8, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0xF5, 0x2B, 0xF9, 0xF6, 0xF9, 0xF8, 0xF7, 0xF9, 0x2B, 0xF9,
242     0x81, 0xAC, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2,
243     0xFA, 0xFA, 0xFA, 0xFA, 0xF9, 0xF8, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0xF5, 0xF5, 0xF5, 0x56, 0x81,
244     0xAC, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2,
245     0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xFA, 0xF9, 0xFA, 0xFA, 0xF9, 0xF9, 0xF8, 0xF8, 0x81, 0x81,
246     0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0x00, 0x00, 0x01, 0x00, 0x03, 0xFF, 0xFF, 0xE0,
247     0x02, 0x00, 0x00, 0x38, 0x02, 0xFF, 0xFF, 0x3C, 0x02, 0xFF, 0xFF, 0x3C, 0x02, 0xFF, 0xFF, 0x3C,
248     0x02, 0xF0, 0x0F, 0x3C, 0x02, 0xFF, 0xFF, 0x3C, 0x02, 0xFF, 0xFF, 0x7C, 0x02, 0xE0, 0x1F, 0x7C,
249     0x02, 0xE0, 0x1F, 0x7C, 0x02, 0xE0, 0x1F, 0x7C, 0x02, 0xE0, 0x1F, 0x7C, 0x02, 0xE0, 0x1F, 0x78,
250     0x02, 0xFF, 0xFF, 0x78, 0x02, 0xFF, 0xFF, 0x78, 0x02, 0x1F, 0xFF, 0x70, 0x02, 0x00, 0x00, 0x70,
251     0x03, 0xFF, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x1F, 0xFF, 0xFF,
252     0x02, 0x00, 0x3F, 0xFF, 0x02, 0x40, 0x00, 0x3F, 0x02, 0xC0, 0x7C, 0x3F, 0x02, 0x00, 0x7D, 0xBF,
253     0x0F, 0x20, 0x00, 0x3F, 0x32, 0x49, 0x00, 0x3C, 0xC4, 0x92, 0x2D, 0x70, 0xE0, 0x24, 0x1A, 0xE0,
254     0x1F, 0x00, 0xA5, 0xC0, 0x00, 0xFC, 0x03, 0x80, 0x00, 0x03, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0xE0,
255     0x03, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xFC,
256     0x03, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xFC,
257     0x03, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xF8,
258     0x03, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0xF0,
259     0x03, 0xFF, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF,
260     0x07, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF,
261     0x0F, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xE0,
262     0x1F, 0xFF, 0xFF, 0xC0, 0x00, 0xFF, 0xFF, 0x80, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x40,
263     0x1F, 0xFC, 0x10, 0x06, 0x10, 0x06, 0x10, 0x06, 0x10, 0x06, 0x10, 0x06, 0x10, 0x06, 0x10, 0x04,
264     0x1F, 0xFC, 0x0F, 0xFE, 0x0F, 0xFF, 0x18, 0x67, 0x34, 0x06, 0x69, 0x64, 0x72, 0xC8, 0x3F, 0xF0,
265     0x1F, 0xFC, 0x1F, 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x1F, 0xFC,
266     0x1F, 0xFC, 0x07, 0xFF, 0x1F, 0xFF, 0x3F, 0xFF, 0x3F, 0xFF, 0x7F, 0xFE, 0xFF, 0xFC, 0x07, 0xF8,
267     0x00, 0x00, 0x00, 0x80, 0x79, 0x7C, 0x0C, 0x0C, 0xCC, 0xCC, 0xCD, 0x97, 0x97, 0x90, 0xE7, 0x97,
268     0x97, 0x97, 0xDD, 0xD9, 0x79, 0x7C, 0xE7, 0xD5, 0x5E, 0x58, 0xCE, 0xD7, 0x97, 0x9C, 0xDD, 0x5D,
269     0x7D, 0xB7, 0xDD, 0x59, 0x79, 0x7C, 0x9D, 0x10, 0x1D, 0xD9, 0xCE, 0xD7, 0x97, 0x9C, 0xDD, 0x0C,
270     0xCC, 0xE7, 0xDD, 0xD9, 0x79, 0x7C, 0xED, 0xDD, 0xDD, 0x79, 0xCE, 0xE7, 0xE7, 0x90, 0xE7, 0x77,
271     0x97, 0x97, 0xDD, 0x79, 0x79, 0x7C, 0xCC, 0xDC, 0xCD, 0xC8, 0xDD, 0x97, 0x97, 0x99, 0x7C, 0xDD,
272     0xDD, 0xDE, 0xDE, 0xDE, 0x7E, 0x7C, 0xCC, 0xCC, 0xCD, 0xCD, 0xDD, 0xDE, 0x99, 0x0C, 0x8C, 0xCC,
273     0xCC, 0xCC, 0xCD, 0xED, 0x77, 0xCC, 0xCC, 0xCD, 0xDD, 0xED, 0xCE, 0xDE, 0x9C, 0xCD, 0xCD, 0xCD,
274     0x0D, 0xCC, 0xCE, 0xE7, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xCC, 0xDE, 0x99, 0x97, 0x97, 0x9D, 0xDD,
275     0xDD, 0xDE, 0xE9, 0x77, 0x00, 0x00, 0x01, 0x00, 0xC2, 0xC2, 0xC2, 0xF5, 0xF5, 0xF5, 0xF6, 0xF6,
276     0xF6, 0x2B, 0x2B, 0x2B, 0xF7, 0xFA, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF6, 0xA5, 0xC2, 0xC2, 0xC2,
277     0xC2, 0xC2, 0xC2, 0xC2, 0xF8, 0x81, 0xFA, 0xC2, 0xC2, 0xC2, 0xC2, 0xF6, 0xA5, 0xC2, 0x81, 0xAA,
278     0xAA, 0xAA, 0xFB, 0xC2, 0xF8, 0x81, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xF6, 0xA5, 0xF9, 0x7F, 0x7F,
279     0x7F, 0x56, 0x81, 0xC2, 0xF8, 0x81, 0x81, 0xC2, 0xC2, 0xC2, 0xC2, 0xF6, 0xA5, 0xF9, 0x0A, 0xF6,
280     0x0A, 0x56, 0xFB, 0xC2, 0xF8, 0x81, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xF6, 0xA5, 0xF9, 0xF6, 0xF6,
281     0xF6, 0x56, 0x81, 0xC2, 0x56, 0x81, 0x81, 0xC2, 0xC2, 0xC2, 0xC2, 0xF6, 0xA5, 0xF9, 0xF9, 0xF9,
282     0xF9, 0xF9, 0xC2, 0xC2, 0xF8, 0x81, 0xFB, 0xC2, 0xC2, 0xC2, 0xC2, 0xF6, 0xA5, 0xC2, 0xC2, 0xC2,
283     0xC2, 0xC2, 0xC2, 0xC2, 0x56, 0xFA, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0x2B, 0x2B, 0x2B, 0xF7, 0xF7,
284     0xF7, 0xF7, 0xF7, 0xB9, 0x56, 0x81, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF6, 0x56, 0xF9,
285     0xFA, 0xFA, 0xFB, 0xFB, 0xFB, 0x81, 0xFA, 0x81, 0xC2, 0xC2, 0xC2, 0xF6, 0xF6, 0xF7, 0x2B, 0x2B,
286     0x2B, 0xF8, 0xF8, 0xF8, 0xF9, 0xFA, 0x81, 0xFB, 0xC2, 0xC2, 0xF5, 0xF7, 0x93, 0xF7, 0xF7, 0xF7,
287     0xF7, 0x2B, 0x2B, 0x2B, 0x2B, 0xFB, 0x81, 0xFB, 0xC2, 0xC2, 0xF5, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7,
288     0xF9, 0xFB, 0xFB, 0xF9, 0xF7, 0xFB, 0x81, 0xFB, 0xC2, 0xF6, 0xF8, 0xF9, 0x2B, 0xF9, 0x2B, 0xF9,
289     0xF6, 0xF8, 0x2B, 0xF8, 0xF7, 0xFB, 0xFB, 0xC2, 0xF9, 0xF7, 0xF9, 0xF7, 0xF9, 0xF7, 0xF9, 0x2B,
290     0xF9, 0x2B, 0xF8, 0x2B, 0x81, 0xAC, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xF9, 0xF9, 0xF9,
291     0xF9, 0xF9, 0xF9, 0x81, 0xAC, 0xC2, 0xC2, 0xC2, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0xD8,
292     0x00, 0x00, 0x08, 0xD8, 0x00, 0x00, 0x00, 0x96, 0x02, 0x1C, 0xC1, 0xC4, 0x18, 0x9C, 0x00, 0x00,
293     0x00, 0x1C, 0x00, 0x96, 0x00, 0x05, 0x69, 0x63, 0x6C, 0x34, 0x00, 0x00, 0x00, 0x32, 0x69, 0x63,
294     0x6C, 0x38, 0x00, 0x00, 0x00, 0x3E, 0x49, 0x43, 0x4E, 0x23, 0x00, 0x00, 0x00, 0x4A, 0x69, 0x63,
295     0x73, 0x23, 0x00, 0x00, 0x00, 0x56, 0x69, 0x63, 0x73, 0x34, 0x00, 0x00, 0x00, 0x62, 0x69, 0x63,
296     0x73, 0x38, 0x00, 0x00, 0x00, 0x6E, 0xBF, 0xB9, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1C,
297     0xE2, 0x10, 0xBF, 0xB9, 0xFF, 0xFF, 0x00, 0x00, 0x02, 0x04, 0x02, 0x1C, 0xE1, 0xAC, 0xBF, 0xB9,
298     0xFF, 0xFF, 0x00, 0x00, 0x06, 0x08, 0x02, 0x1C, 0xE1, 0xA4, 0xBF, 0xB9, 0xFF, 0xFF, 0x00, 0x00,
299     0x07, 0x0C, 0x02, 0x1C, 0xE1, 0xF8, 0xBF, 0xB9, 0xFF, 0xFF, 0x00, 0x00, 0x07, 0x50, 0x02, 0x1C,
300     0xE1, 0xDC, 0xBF, 0xB9, 0xFF, 0xFF, 0x00, 0x00, 0x07, 0xD4, 0x02, 0x1C, 0xE1, 0xD0
301     };
302    
303     static bool use_streams[ 'Z'-'A'+1 ];
304    
305     static bool is_ntfs_volume( char *rootdir )
306     {
307     bool ret = false;
308     char tst_file[_MAX_PATH], tst_stream[_MAX_PATH];
309     sprintf( tst_file, "%sb2query.tmp", rootdir );
310     sprintf( tst_stream, "%s:AFP_AfpInfo", tst_file );
311     if(!exists(tst_file)) {
312     if(create_file( tst_file, 0 )) {
313     if(create_file( tst_stream, 0 )) {
314     ret = true;
315     }
316     DeleteFile( tst_file );
317     }
318     }
319     return ret;
320     }
321    
322    
323     // !!UNC
324     void init_posix_emu(void)
325     {
326     if(!validate_stat_struct) {
327     ErrorAlert( "Invalid struct my_stat -- edit posix_emu.h" );
328     QuitEmulator();
329     }
330    
331     #if DEBUG_EXTFS
332     debug_extfs = PrefsFindInt16("debugextfs");
333    
334     debug_extfs = DB_EXTFS_LOUD;
335    
336     if(debug_extfs != DB_EXTFS_NONE) {
337     extfs_log_open( EXTFS_LOG_FILE_NAME );
338     }
339     #endif
340    
341     // We cannot use ExtFS "RootPath" because of the virtual desktop.
342     if(PrefsFindBool("enableextfs")) {
343     PrefsReplaceString("extfs", "");
344     } else {
345     PrefsRemoveItem("extfs");
346     D(bug("extfs disabled by user\n"));
347     #if DEBUG_EXTFS
348     extfs_log_close();
349     #endif
350     return;
351     }
352    
353     const char *extdrives = PrefsFindString("extdrives");
354    
355     // Set up drive list.
356     int outinx = 0;
357     for( char letter = 'A'; letter <= 'Z'; letter++ ) {
358     if(extdrives && !strchr(extdrives,letter)) continue;
359     int i = (int)( letter - 'A' );
360     char rootdir[20];
361     wsprintf( rootdir, "%c:\\", letter );
362     use_streams[ letter - 'A' ] = false;
363     switch(GetDriveType(rootdir)) {
364     case DRIVE_FIXED:
365     case DRIVE_REMOTE:
366     case DRIVE_RAMDISK:
367     // TODO: NTFS AFP?
368     // fall
369     case DRIVE_REMOVABLE:
370     case DRIVE_CDROM:
371     if(outinx < sizeof(host_drive_list)) {
372     host_drive_list[outinx] = letter;
373     outinx += 2;
374     }
375     }
376     }
377    
378     // Set up virtual desktop root.
379     // TODO: this should be customizable.
380     GetModuleFileName( NULL, virtual_root, sizeof(virtual_root) );
381     char *p = strrchr( virtual_root, '\\' );
382     if(p) {
383     *(++p) = 0;
384     strcat( virtual_root, desktop_name );
385     } else {
386     // should never happen
387     sprintf( virtual_root, "C:\\%s", desktop_name );
388     }
389     CreateDirectory( virtual_root, 0 );
390    
391     // Set up an icon looking like "My Computer"
392     // Can be overwritten just like any other folder custom icon.
393     if(my_access(custom_icon_name,0) != 0) {
394     int fd = my_creat( custom_icon_name, 0 );
395     if(fd >= 0) {
396     my_close(fd);
397     fd = open_rfork( custom_icon_name, O_RDWR|O_CREAT );
398     if(fd >= 0) {
399     my_write( fd, my_comp_icon, sizeof(my_comp_icon) );
400     my_close(fd);
401     static uint8 host_finfo[SIZEOF_FInfo];
402     uint32 finfo = Host2MacAddr(host_finfo);
403     get_finfo(custom_icon_name, finfo, 0, false);
404     WriteMacInt16(finfo + fdFlags, kIsInvisible);
405     set_finfo(custom_icon_name, finfo, 0, false);
406     get_finfo(my_computer, finfo, 0, true);
407     WriteMacInt16(finfo + fdFlags, ReadMacInt16(finfo + fdFlags) | kHasCustomIcon);
408     set_finfo(my_computer, finfo, 0, true);
409     } else {
410     my_remove(custom_icon_name);
411     }
412     }
413     }
414     }
415    
416     void final_posix_emu(void)
417     {
418     #if DEBUG_EXTFS
419     extfs_log_close();
420     #endif
421     }
422    
423     static void charset_host2mac( char *s )
424     {
425     int i, len=strlen(s), code;
426    
427     for( i=len-3; i>=0; i-- ) {
428     if( s[i] == '%' && isxdigit(s[i+1]) && isxdigit(s[i+2]) ) {
429     sscanf( &s[i], "%%%02X", &code );
430     memmove( &s[i], &s[i+2], strlen(&s[i+2])+1 );
431     s[i] = code;
432     }
433     }
434     }
435    
436     static void charset_mac2host( char *s )
437     {
438     int i, convert, len = strlen(s);
439    
440     D(bug("charset_mac2host(%s)...\n", s));
441    
442     for( i=len-1; i>=0; i-- ) {
443     convert = 0;
444     switch( (unsigned char)s[i] ) {
445     // case '\r': // handled by "default"
446     // case '\n':
447     // case '\t':
448     case '/':
449     // case '\\': // Backslash is tricky -- "s" is a full path!
450     // case ':':
451     case '*':
452     case '?':
453     case '"':
454     case '<':
455     case '>':
456     case '|':
457     case '%':
458     convert = 1;
459     break;
460     default:
461     if((unsigned char)s[i] < ' ') convert = 1;
462     break;
463     }
464     if(convert) {
465     char sml[10];
466     sprintf( sml, "%%%02X", s[i] );
467     memmove( &s[i+2], &s[i], strlen(&s[i])+1 );
468     memmove( &s[i], sml, 3 );
469     }
470     }
471     D(bug("charset_mac2host = %s\n", s));
472     }
473    
474     static void make_mask(
475     char *mask,
476     const char *dir,
477     const char *a1,
478     const char *a2
479     )
480     {
481     strcpy( mask, dir );
482    
483     int len = strlen(mask);
484     if( len && mask[len-1] != '\\' ) strcat( mask, "\\" );
485    
486     if( a1 ) strcat( mask, a1 );
487     if( a2 ) strcat( mask, a2 );
488     }
489    
490     // !!UNC
491     static char *translate( const char *path, char *buffer )
492     {
493     char *l = host_drive_list;
494     char *p = (char *)path;
495    
496     while(*l) {
497     if(toupper(p[1]) == toupper(*l)) break;
498     l += strlen(l) + 1;
499     }
500    
501     if(p[0] == '\\' && *l && (p[2] == 0 || p[2] == ':' || p[2] == '\\')) {
502     p += 2;
503     if(*p == ':') p++;
504     if(*p == '\\') p++;
505     sprintf( buffer, "%c:\\%s", *l, p );
506     } else {
507     if(*path == '\\') {
508     sprintf( buffer, "%s%s", virtual_root, path );
509     } else {
510     int len = strlen(path);
511     if(len == 0 || path[len-1] == '\\') {
512     make_mask( buffer, virtual_root, path, my_computer );
513     } else {
514     make_mask( buffer, virtual_root, path, 0 );
515     }
516     }
517     }
518     charset_mac2host( buffer );
519    
520     return buffer;
521     }
522    
523     // helpers
524     static void strip_trailing_bs( char *path )
525     {
526     int len = strlen(path);
527     if(len > 0 && path[len-1] == '\\') path[len-1] = 0;
528     }
529    
530     #if 0 /* defined is util_windows.cpp */
531     static int exists( const char *p )
532     {
533     WIN32_FIND_DATA fdata;
534    
535     int result = 0;
536    
537     HANDLE h = FindFirstFile( p, &fdata );
538     if(h != INVALID_HANDLE_VALUE) {
539     result = 1;
540     FindClose( h );
541     }
542    
543     D(bug("exists(%s) = %d\n", p, result));
544    
545     return result;
546     }
547     #endif
548    
549     static int is_dir( char *p )
550     {
551     WIN32_FIND_DATA fdata;
552    
553     int result = 0;
554    
555     HANDLE h = FindFirstFile( p, &fdata );
556     if(h != INVALID_HANDLE_VALUE) {
557     result = (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
558     FindClose( h );
559     }
560     return result;
561     }
562    
563     static int myRemoveDirectory( const char *source )
564     {
565     HANDLE fh;
566     WIN32_FIND_DATA FindFileData;
567     int ok, result = 1;
568     char mask[_MAX_PATH];
569    
570     D(bug("removing folder %s\n", source));
571    
572     make_mask( mask, source, "*.*", 0 );
573    
574     fh = FindFirstFile( mask, &FindFileData );
575     ok = fh != INVALID_HANDLE_VALUE;
576     while(ok) {
577     make_mask( mask, source, FindFileData.cFileName, 0 );
578     D(bug("removing item %s\n", mask));
579     int isdir = (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
580     if(isdir) {
581     // must delete ".finf", ".rsrc" but not ".", ".."
582     if(strcmp(FindFileData.cFileName,".") && strcmp(FindFileData.cFileName,"..")) {
583     result = myRemoveDirectory( mask );
584     if(!result) break;
585     }
586     } else {
587     D(bug("DeleteFile %s\n", mask));
588     result = DeleteFile( mask );
589     if(!result) break;
590     }
591     ok = FindNextFile( fh, &FindFileData );
592     }
593     if(fh != INVALID_HANDLE_VALUE) FindClose( fh );
594     if(result) {
595     D(bug("RemoveDirectory %s\n", source));
596     result = RemoveDirectory( source );
597     }
598     return result;
599     }
600    
601     static void make_folders( char *path )
602     {
603     char local_path[_MAX_PATH], *p;
604     strcpy( local_path, path );
605     p = strrchr( local_path, '\\' );
606     if(p) {
607     *p = 0;
608     if(strlen(local_path) > 3) {
609     make_folders(local_path);
610     mkdir(local_path);
611     }
612     }
613     }
614    
615     // !!UNC
616     static bool is_same_drive( char *p1, char *p2 )
617     {
618     return toupper(*p1) == toupper(*p2);
619     }
620    
621     // Used when the drives are known to be different.
622     // Can't use MoveFileEx() etc because of the Win9x limitations.
623     // It would simulate CopyFile*() -- DeleteFile*() anyway
624     int file_move_copy( char *src, char *dst, bool delete_old )
625     {
626     int result = 0;
627     my_errno = 0;
628    
629     D(bug("file_copy %s -> %s\n", src, dst));
630    
631     // Fail if exists -- it's up to MacOS to move things to Trash
632     if(CopyFile(src,dst,TRUE)) {
633     if(delete_old && !DeleteFile(src)) {
634     result = -1;
635     my_errno = EACCES;
636     }
637     } else {
638     result = -1;
639     if(exists(src))
640     my_errno = EACCES;
641     else
642     my_errno = ENOENT;
643     }
644     return result;
645     }
646    
647     int file_move( char *src, char *dst )
648     {
649     return file_move_copy( src, dst, true );
650     }
651    
652     int file_copy( char *src, char *dst )
653     {
654     return file_move_copy( src, dst, false );
655     }
656    
657     int folder_copy( char *folder_src, char *folder_dst )
658     {
659     HANDLE fh;
660     WIN32_FIND_DATA FindFileData;
661     int ok, result = 0;
662     char mask[_MAX_PATH];
663    
664     D(bug("copying folder %s -> \n", folder_src, folder_dst));
665    
666     my_errno = 0;
667    
668     if(!CreateDirectory( folder_dst, 0 )) {
669     my_errno = EACCES;
670     return -1;
671     }
672    
673     make_mask( mask, folder_src, "*.*", 0 );
674    
675     fh = FindFirstFile( mask, &FindFileData );
676     ok = fh != INVALID_HANDLE_VALUE;
677     while(ok) {
678     make_mask( mask, folder_src, FindFileData.cFileName, 0 );
679     int isdir = (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
680     char target[_MAX_PATH];
681     make_mask( target, folder_dst, FindFileData.cFileName, 0 );
682     D(bug("copying item %s -> %s\n", mask, target));
683     if(isdir) {
684     if(strcmp(FindFileData.cFileName,".") && strcmp(FindFileData.cFileName,"..")) {
685     result = folder_copy( mask, target );
686     if(result < 0) break;
687     }
688     } else {
689     result = file_copy( mask, target );
690     if(result < 0) break;
691     }
692     ok = FindNextFile( fh, &FindFileData );
693     }
694     if(fh != INVALID_HANDLE_VALUE) FindClose( fh );
695     return result;
696     }
697    
698     // dir enumeration
699     void closedir( struct DIR *d )
700     {
701     DISABLE_ERRORS;
702     if(d) {
703     if(d->h != INVALID_HANDLE_VALUE && d->h != VIRTUAL_ROOT_ID) {
704     FindClose( d->h );
705     }
706     delete d;
707     }
708     RESTORE_ERRORS;
709     }
710    
711     static int make_dentry( struct DIR *d )
712     {
713     int ok = 0;
714    
715     memset( &d->de, 0, sizeof(d->de) );
716     if(d->h != INVALID_HANDLE_VALUE) {
717     if( (d->FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0 &&
718     *d->FindFileData.cFileName == '.')
719     {
720     ok = 0;
721     } else {
722     strncpy( d->de.d_name, d->FindFileData.cFileName, sizeof(d->de.d_name)-1 );
723     d->de.d_name[sizeof(d->de.d_name)-1] = 0;
724     charset_host2mac( d->de.d_name );
725     ok = 1;
726     }
727     }
728     return ok;
729     }
730    
731     struct dirent *readdir( struct DIR *d )
732     {
733     DISABLE_ERRORS;
734    
735     dirent *de = 0;
736    
737     if(d) {
738     if(d->h != INVALID_HANDLE_VALUE) {
739     if(d->h == VIRTUAL_ROOT_ID) {
740     make_dentry(d);
741     de = &d->de;
742     d->vname_list += strlen(d->vname_list) + 1;
743     if(*d->vname_list) {
744     strcpy( d->FindFileData.cFileName, d->vname_list );
745     d->FindFileData.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
746     } else {
747     // Out of static drive entries. Continue with other stuff.
748     char mask[MAX_PATH_LENGTH];
749     make_mask( mask, virtual_root, "*.*", 0 );
750     d->h = FindFirstFile( mask, &d->FindFileData );
751     }
752     } else {
753     int done = 0;
754     do {
755     if(make_dentry(d)) {
756     de = &d->de;
757     done = 1;
758     }
759     if(!FindNextFile( d->h, &d->FindFileData )) {
760     FindClose( d->h );
761     d->h = INVALID_HANDLE_VALUE;
762     done = 1;
763     }
764     } while(!done);
765     }
766     }
767     }
768    
769     if(de) {
770     D(bug("readdir found %s\n", de->d_name));
771     }
772    
773     RESTORE_ERRORS;
774    
775     return de;
776     }
777    
778     struct DIR *opendir( const char *path )
779     {
780     DISABLE_ERRORS;
781     DIR *d = new DIR;
782     if(d) {
783     memset( d, 0, sizeof(DIR) );
784     if(*path == 0) {
785     d->vname_list = host_drive_list;
786     if(d->vname_list) {
787     d->h = VIRTUAL_ROOT_ID;
788     strcpy( d->FindFileData.cFileName, d->vname_list );
789     d->FindFileData.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
790     } else {
791     d->h = INVALID_HANDLE_VALUE;
792     }
793     } else {
794     char mask[MAX_PATH_LENGTH];
795     make_mask( mask, MRP(path), "*.*", 0 );
796    
797     D(bug("opendir path=%s, mask=%s\n", path, mask));
798    
799     d->h = FindFirstFile( mask, &d->FindFileData );
800     if(d->h == INVALID_HANDLE_VALUE) {
801     delete d;
802     d = 0;
803     }
804     }
805     }
806    
807     D(bug("opendir(%s,%s) = %08x\n", path, MRP(path), d));
808    
809     RESTORE_ERRORS;
810    
811     return d;
812     }
813    
814     static void dump_stat( const struct my_stat *st )
815     {
816     D(bug("stat: size = %ld, mode = %ld, a = %ld, m = %ld, c = %ld\n", st->st_size, st->st_mode, st->st_atime, st->st_mtime, st->st_ctime));
817     }
818    
819    
820    
821     // Exported hook functions
822     int my_stat( const char *path, struct my_stat *st )
823     {
824     DISABLE_ERRORS;
825    
826     int result;
827    
828     if(*path == 0) {
829     /// virtual root
830     memset( st, 0, sizeof(struct my_stat) );
831     st->st_mode = _S_IFDIR;
832     result = 0;
833     my_errno = 0;
834     } else {
835     result = stat( MRP(path), (struct stat *)st );
836     if(result < 0) {
837     my_errno = errno;
838     } else {
839     my_errno = 0;
840     }
841     }
842    
843     D(bug("stat(%s,%s) = %d\n", path, MRP(path), result));
844     if(result >= 0) dump_stat( st );
845     RESTORE_ERRORS;
846     return result;
847     }
848    
849     int my_fstat( int fd, struct my_stat *st )
850     {
851     DISABLE_ERRORS;
852     int result = fstat( fd, (struct stat *)st );
853     if(result < 0) {
854     my_errno = errno;
855     } else {
856     my_errno = 0;
857     }
858     D(bug("fstat(%d) = %d\n", fd, result));
859     if(result >= 0) dump_stat( st );
860     RESTORE_ERRORS;
861     return result;
862     }
863    
864     int my_open( const char *path, int mode, ... )
865     {
866     DISABLE_ERRORS;
867     int result;
868     char *p = MRP(path);
869    
870     // Windows "open" does not handle _O_CREAT and _O_BINARY as it should
871     if(mode & _O_CREAT) {
872     if(exists(p)) {
873     result = open( p, mode & ~_O_CREAT );
874     D(bug("open-nocreat(%s,%s,%d) = %d\n", path, p, mode, result));
875     } else {
876     result = creat( p, _S_IWRITE|_S_IREAD );
877     if(result < 0) {
878     make_folders(p);
879     result = creat( p, _S_IWRITE|_S_IREAD );
880     }
881     D(bug("open-creat(%s,%s,%d) = %d\n", path, p, mode, result));
882     }
883     } else {
884     result = open( p, mode );
885     D(bug("open(%s,%s,%d) = %d\n", path, p, mode, result));
886     }
887     if(result < 0) {
888     my_errno = errno;
889     } else {
890     setmode(result, _O_BINARY);
891     my_errno = 0;
892     }
893     RESTORE_ERRORS;
894     return result;
895     }
896    
897     int my_rename( const char *old_path, const char *new_path )
898     {
899     DISABLE_ERRORS;
900     int result = -1;
901     char *p_old = MRP(old_path);
902     char *p_new = MRP2(new_path);
903    
904     result = my_access(old_path,0);
905     if(result < 0) {
906     // my_errno already set
907     } else {
908     if(is_same_drive(p_old,p_new)) {
909     result = rename( p_old, p_new );
910     if(result != 0) { // by definition, rename may also return a positive value to indicate an error
911     my_errno = errno;
912     } else {
913     my_errno = 0;
914     }
915     } else {
916     if(is_dir(p_old)) {
917     result = folder_copy( p_old, p_new );
918     // my_errno already set
919     if(result >= 0) {
920     if(myRemoveDirectory( p_old )) {
921     my_errno = 0;
922     result = 0;
923     } else {
924     // there is no proper error code for this failure.
925     my_errno = EACCES;
926     result = -1;
927     }
928     }
929     } else {
930     result = file_move( p_old, p_new );
931     // my_errno already set
932     }
933     }
934     }
935     D(bug("rename(%s,%s,%s,%s) = %d\n", old_path, p_old, new_path, p_new, result));
936     RESTORE_ERRORS;
937     return result;
938     }
939    
940     int my_access( const char *path, int mode )
941     {
942     DISABLE_ERRORS;
943     char *p = MRP(path);
944     WIN32_FIND_DATA fdata;
945    
946     int result;
947    
948     if(is_dir(p)) {
949     // access does not work for folders.
950     HANDLE h = FindFirstFile( p, &fdata );
951     if(h != INVALID_HANDLE_VALUE) {
952     FindClose( h );
953     if(mode == W_OK) {
954     if( (fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0 ) {
955     result = 0;
956     my_errno = 0;
957     } else {
958     result = -1;
959     my_errno = EACCES;
960     }
961     } else {
962     result = 0;
963     my_errno = 0;
964     }
965     } else {
966     result = -1;
967     my_errno = ENOENT;
968     }
969     } else {
970     // W_OK, F_OK are ok.
971     result = access(p,mode);
972     if(result < 0) {
973     my_errno = errno;
974     } else {
975     my_errno = 0;
976     }
977     }
978    
979     D(bug("access(%s,%s,%d) = %d\n", path, MRP(path), mode, result));
980     RESTORE_ERRORS;
981     return result;
982     }
983    
984     int my_mkdir( const char *path, int mode )
985     {
986     DISABLE_ERRORS;
987     char *p = MRP(path);
988     strip_trailing_bs(p);
989     int result = mkdir( p );
990     if(result < 0) {
991     make_folders(p);
992     result = mkdir( p );
993     }
994     if(result < 0) {
995     my_errno = errno;
996     } else {
997     my_errno = 0;
998     }
999     D(bug("mkdir(%s,%s,%d) = %d\n", path, p, mode, result));
1000     RESTORE_ERRORS;
1001     return result;
1002     }
1003    
1004     int my_remove( const char *path )
1005     {
1006     DISABLE_ERRORS;
1007     char *p = MRP(path);
1008     strip_trailing_bs(p);
1009     int result;
1010     if(is_dir(p)) {
1011     result = myRemoveDirectory( p );
1012     } else {
1013     D(bug("DeleteFile %s\n", p));
1014     result = DeleteFile( p );
1015     }
1016     if(result) {
1017     result = 0;
1018     my_errno = 0;
1019     } else {
1020     result = -1;
1021     if(exists(p)) {
1022     my_errno = EACCES;
1023     } else {
1024     my_errno = ENOENT;
1025     }
1026     }
1027     D(bug("remove(%s,%s) = %d\n", path, p, result));
1028     RESTORE_ERRORS;
1029     return result;
1030     }
1031    
1032     int my_creat( const char *path, int mode )
1033     {
1034     DISABLE_ERRORS;
1035     char *p = MRP(path);
1036     int result = creat( p, _S_IWRITE|_S_IREAD ); // note mode
1037     if(result < 0) {
1038     make_folders(p);
1039     result = creat( p, _S_IWRITE|_S_IREAD ); // note mode
1040     }
1041     if(result < 0) {
1042     my_errno = errno;
1043     } else {
1044     setmode(result, _O_BINARY);
1045     my_errno = 0;
1046     }
1047     D(bug("creat(%s,%s,%d) = %d\n", path, p, mode,result));
1048     RESTORE_ERRORS;
1049     return result;
1050     }
1051    
1052     int my_chsize( int fd, size_t sz )
1053     {
1054     DISABLE_ERRORS;
1055     int result = chsize(fd,sz);
1056     if(result < 0) {
1057     my_errno = errno;
1058     } else {
1059     my_errno = 0;
1060     }
1061     RESTORE_ERRORS;
1062     return result;
1063     }
1064    
1065     int my_close( int fd )
1066     {
1067     DISABLE_ERRORS;
1068     int result = close(fd);
1069     if(result < 0) {
1070     my_errno = errno;
1071     } else {
1072     my_errno = 0;
1073     }
1074     RESTORE_ERRORS;
1075     D(bug("close(%d) = %d\n", fd, result));
1076     return result;
1077     }
1078    
1079     long my_lseek( int fd, long offset, int origin )
1080     {
1081     DISABLE_ERRORS;
1082     int result = lseek( fd, offset, origin );
1083     if(result < 0) {
1084     my_errno = errno;
1085     } else {
1086     my_errno = 0;
1087     }
1088     RESTORE_ERRORS;
1089     return result;
1090     }
1091    
1092     int my_read( int fd, void *buffer, unsigned int count )
1093     {
1094     DISABLE_ERRORS;
1095     int result = read( fd, buffer, count );
1096     if(result < 0) {
1097     my_errno = errno;
1098     } else {
1099     my_errno = 0;
1100     }
1101     RESTORE_ERRORS;
1102     D(bug("read(%ld,%08x,%ld) = %d\n", fd, buffer, count, result));
1103    
1104     return result;
1105     }
1106    
1107     int my_write( int fd, const void *buffer, unsigned int count )
1108     {
1109     DISABLE_ERRORS;
1110     int result = write( fd, buffer, count );
1111     if(result < 0) {
1112     my_errno = errno;
1113     } else {
1114     my_errno = 0;
1115     }
1116     RESTORE_ERRORS;
1117     D(bug("write(%ld,%08x,%ld) = %d\n", fd, buffer, count, result));
1118     return result;
1119     }