ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/MacOSX/extfs_macosx.cpp
Revision: 1.4
Committed: 2008-06-20T00:47:25Z (16 years, 5 months ago) by asvitkine
Branch: MAIN
CVS Tags: HEAD
Changes since 1.3: +1 -1 lines
Log Message:
[patch from Kelvin Delbarre] Typo fix.

File Contents

# Content
1 /*
2 * extfs_macosx.cpp - MacOS file system for access native file system access, MacOS X specific stuff
3 *
4 * Basilisk II (C) 1997-2008 Christian Bauer
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <sys/attr.h>
24 #include <sys/syscall.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <dirent.h>
29 #include <errno.h>
30
31 #include "sysdeps.h"
32 #include "prefs.h"
33 #include "extfs.h"
34 #include "extfs_defs.h"
35
36 // XXX: don't clobber with native definitions
37 #define noErr native_noErr
38 #define Point native_Point
39 #define Rect native_Rect
40 #define ProcPtr native_ProcPtr
41 # include <CoreFoundation/CFString.h>
42 #undef ProcPtr
43 #undef Rect
44 #undef Point
45 #undef noErr
46
47 #define DEBUG 0
48 #include "debug.h"
49
50
51 // Default Finder flags
52 const uint16 DEFAULT_FINDER_FLAGS = kHasBeenInited;
53
54
55 /*
56 * Extended attributes (Tiger+)
57 */
58
59 #define USE_XATTRS g_use_xattrs
60 static bool g_use_xattrs = false;
61
62 #define XATTR_TEST "org.BasiliskII.TestAttr"
63 #define XATTR_FINFO "org.BasiliskII.FinderInfo"
64 #define XATTR_FXINFO "org.BasiliskII.ExtendedFinderInfo"
65
66 static bool get_xattr(const char *path, const char *name, void *value, uint32 size)
67 {
68 return syscall(SYS_getxattr, path, name, value, size, 0, 0) == size;
69 }
70
71 static bool set_xattr(const char *path, const char *name, const void *value, uint32 size)
72 {
73 return syscall(SYS_setxattr, path, name, value, size, 0, 0) == 0;
74 }
75
76 static bool remove_xattr(const char *path, const char *name)
77 {
78 return syscall(SYS_removexattr, path, name, 0) == 0;
79 }
80
81 static bool check_xattr(void)
82 {
83 const char *path = PrefsFindString("extfs");
84 if (path == NULL)
85 return false;
86 const uint32 sentinel = 0xdeadbeef;
87 if (!set_xattr(path, XATTR_TEST, &sentinel, sizeof(sentinel)))
88 return false;
89 uint32 v;
90 if (!get_xattr(path, XATTR_TEST, &v, sizeof(v)))
91 return false;
92 if (!remove_xattr(path, XATTR_TEST))
93 return false;
94 return v == sentinel;
95 }
96
97
98 /*
99 * Initialization
100 */
101
102 void extfs_init(void)
103 {
104 g_use_xattrs = check_xattr();
105 }
106
107
108 /*
109 * Deinitialization
110 */
111
112 void extfs_exit(void)
113 {
114 }
115
116
117 /*
118 * Add component to path name
119 */
120
121 void add_path_component(char *path, const char *component)
122 {
123 int l = strlen(path);
124 if (l < MAX_PATH_LENGTH-1 && path[l-1] != '/') {
125 path[l] = '/';
126 path[l+1] = 0;
127 }
128 strncat(path, component, MAX_PATH_LENGTH-1);
129 }
130
131
132 /*
133 * Finder info manipulation helpers
134 */
135
136 typedef uint8 FinderInfo[SIZEOF_FInfo];
137
138 struct FinderInfoAttrBuf {
139 uint32 length;
140 FinderInfo finderInfo;
141 FinderInfo extendedFinderInfo;
142 };
143
144 static const FinderInfo kNativeFInfoMask = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00};
145 static const FinderInfo kNativeFXInfoMask = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00};
146 static const FinderInfo kNativeDInfoMask = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00};
147 static const FinderInfo kNativeDXInfoMask = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00}; /* XXX: keep frScroll? */
148
149 static void finfo_merge(FinderInfo dst, const FinderInfo emu, const FinderInfo nat, const FinderInfo mask)
150 {
151 for (int i = 0; i < SIZEOF_FInfo; i++)
152 dst[i] = (emu[i] & ~mask[i]) | (nat[i] & mask[i]);
153 }
154
155 static void finfo_split(FinderInfo dst, const FinderInfo emu, const FinderInfo mask)
156 {
157 for (int i = 0; i < SIZEOF_FInfo; i++)
158 dst[i] = emu[i] & mask[i];
159 }
160
161
162 /*
163 * Finder info are kept in helper files (on anything below Tiger)
164 *
165 * Finder info:
166 * /path/.finf/file
167 *
168 * The .finf files store a FInfo/DInfo, followed by a FXInfo/DXInfo
169 * (16+16 bytes)
170 */
171
172 static void make_finf_path(const char *src, char *dest, bool only_dir = false)
173 {
174 dest[0] = 0;
175
176 // Get pointer to last component of path
177 const char *last_part = strrchr(src, '/');
178 if (last_part)
179 last_part++;
180 else
181 last_part = src;
182
183 // Copy everything before
184 strncpy(dest, src, last_part-src);
185 dest[last_part-src] = 0;
186
187 // Add additional component
188 strncat(dest, ".finf/", MAX_PATH_LENGTH-1);
189
190 // Add last component
191 if (!only_dir)
192 strncat(dest, last_part, MAX_PATH_LENGTH-1);
193 }
194
195 static int create_finf_dir(const char *path)
196 {
197 char finf_dir[MAX_PATH_LENGTH];
198 make_finf_path(path, finf_dir, true);
199 if (finf_dir[strlen(finf_dir) - 1] == '/') // Remove trailing "/"
200 finf_dir[strlen(finf_dir) - 1] = 0;
201 return mkdir(finf_dir, 0777);
202 }
203
204 static int open_finf(const char *path, int flag)
205 {
206 char finf_path[MAX_PATH_LENGTH];
207 make_finf_path(path, finf_path);
208
209 if ((flag & O_ACCMODE) == O_RDWR || (flag & O_ACCMODE) == O_WRONLY)
210 flag |= O_CREAT;
211 int fd = open(finf_path, flag, 0666);
212 if (fd < 0) {
213 if (errno == ENOENT && (flag & O_CREAT)) {
214 // One path component was missing, probably the finf
215 // directory. Try to create it and re-open the file.
216 int ret = create_finf_dir(path);
217 if (ret < 0)
218 return ret;
219 fd = open(finf_path, flag, 0666);
220 }
221 }
222 return fd;
223 }
224
225
226 /*
227 * Resource forks are kept into their native location
228 *
229 * Resource fork:
230 * /path/file/..namedfork/rsrc
231 */
232
233 static void make_rsrc_path(const char *src, char *dest)
234 {
235 int l = strlen(src);
236 if (l + 1 + 16 + 1 <= MAX_PATH_LENGTH)
237 memcpy(dest, src, l + 1);
238 else {
239 // The rsrc component is copied as is, if there is not enough
240 // space to add it. In that case, open() will fail gracefully
241 // and this is what we want.
242 dest[0] = '.';
243 dest[1] = '\0';
244 }
245
246 add_path_component(dest, "..namedfork/rsrc");
247 }
248
249 static int open_rsrc(const char *path, int flag)
250 {
251 char rsrc_path[MAX_PATH_LENGTH];
252 make_rsrc_path(path, rsrc_path);
253
254 return open(rsrc_path, flag);
255 }
256
257
258 /*
259 * Get/set finder info for file/directory specified by full path
260 */
261
262 struct ext2type {
263 const char *ext;
264 uint32 type;
265 uint32 creator;
266 };
267
268 static const ext2type e2t_translation[] = {
269 {".Z", FOURCC('Z','I','V','M'), FOURCC('L','Z','I','V')},
270 {".gz", FOURCC('G','z','i','p'), FOURCC('G','z','i','p')},
271 {".hqx", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')},
272 {".bin", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')},
273 {".pdf", FOURCC('P','D','F',' '), FOURCC('C','A','R','O')},
274 {".ps", FOURCC('T','E','X','T'), FOURCC('t','t','x','t')},
275 {".sit", FOURCC('S','I','T','!'), FOURCC('S','I','T','x')},
276 {".tar", FOURCC('T','A','R','F'), FOURCC('T','A','R',' ')},
277 {".uu", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')},
278 {".uue", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')},
279 {".zip", FOURCC('Z','I','P',' '), FOURCC('Z','I','P',' ')},
280 {".8svx", FOURCC('8','S','V','X'), FOURCC('S','N','D','M')},
281 {".aifc", FOURCC('A','I','F','C'), FOURCC('T','V','O','D')},
282 {".aiff", FOURCC('A','I','F','F'), FOURCC('T','V','O','D')},
283 {".au", FOURCC('U','L','A','W'), FOURCC('T','V','O','D')},
284 {".mid", FOURCC('M','I','D','I'), FOURCC('T','V','O','D')},
285 {".midi", FOURCC('M','I','D','I'), FOURCC('T','V','O','D')},
286 {".mp2", FOURCC('M','P','G',' '), FOURCC('T','V','O','D')},
287 {".mp3", FOURCC('M','P','G',' '), FOURCC('T','V','O','D')},
288 {".wav", FOURCC('W','A','V','E'), FOURCC('T','V','O','D')},
289 {".bmp", FOURCC('B','M','P','f'), FOURCC('o','g','l','e')},
290 {".gif", FOURCC('G','I','F','f'), FOURCC('o','g','l','e')},
291 {".lbm", FOURCC('I','L','B','M'), FOURCC('G','K','O','N')},
292 {".ilbm", FOURCC('I','L','B','M'), FOURCC('G','K','O','N')},
293 {".jpg", FOURCC('J','P','E','G'), FOURCC('o','g','l','e')},
294 {".jpeg", FOURCC('J','P','E','G'), FOURCC('o','g','l','e')},
295 {".pict", FOURCC('P','I','C','T'), FOURCC('o','g','l','e')},
296 {".png", FOURCC('P','N','G','f'), FOURCC('o','g','l','e')},
297 {".sgi", FOURCC('.','S','G','I'), FOURCC('o','g','l','e')},
298 {".tga", FOURCC('T','P','I','C'), FOURCC('o','g','l','e')},
299 {".tif", FOURCC('T','I','F','F'), FOURCC('o','g','l','e')},
300 {".tiff", FOURCC('T','I','F','F'), FOURCC('o','g','l','e')},
301 {".htm", FOURCC('T','E','X','T'), FOURCC('M','O','S','S')},
302 {".html", FOURCC('T','E','X','T'), FOURCC('M','O','S','S')},
303 {".txt", FOURCC('T','E','X','T'), FOURCC('t','t','x','t')},
304 {".rtf", FOURCC('T','E','X','T'), FOURCC('M','S','W','D')},
305 {".c", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
306 {".C", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
307 {".cc", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
308 {".cpp", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
309 {".cxx", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
310 {".h", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
311 {".hh", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
312 {".hpp", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
313 {".hxx", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
314 {".s", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
315 {".S", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
316 {".i", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
317 {".mpg", FOURCC('M','P','E','G'), FOURCC('T','V','O','D')},
318 {".mpeg", FOURCC('M','P','E','G'), FOURCC('T','V','O','D')},
319 {".mov", FOURCC('M','o','o','V'), FOURCC('T','V','O','D')},
320 {".fli", FOURCC('F','L','I',' '), FOURCC('T','V','O','D')},
321 {".avi", FOURCC('V','f','W',' '), FOURCC('T','V','O','D')},
322 {".qxd", FOURCC('X','D','O','C'), FOURCC('X','P','R','3')},
323 {".hfv", FOURCC('D','D','i','m'), FOURCC('d','d','s','k')},
324 {".dsk", FOURCC('D','D','i','m'), FOURCC('d','d','s','k')},
325 {".img", FOURCC('r','o','h','d'), FOURCC('d','d','s','k')},
326 {NULL, 0, 0} // End marker
327 };
328
329 // Get emulated Finder info from metadata (Tiger+)
330 static bool get_finfo_from_xattr(const char *path, uint8 *finfo, uint8 *fxinfo)
331 {
332 if (!get_xattr(path, XATTR_FINFO, finfo, SIZEOF_FInfo))
333 return false;
334 if (fxinfo && !get_xattr(path, XATTR_FXINFO, fxinfo, SIZEOF_FXInfo))
335 return false;
336 return true;
337 }
338
339 // Get emulated Finder info from helper file
340 static bool get_finfo_from_helper(const char *path, uint8 *finfo, uint8 *fxinfo)
341 {
342 int fd = open_finf(path, O_RDONLY);
343 if (fd < 0)
344 return false;
345
346 ssize_t actual = read(fd, finfo, SIZEOF_FInfo);
347 if (fxinfo)
348 actual += read(fd, fxinfo, SIZEOF_FXInfo);
349 close(fd);
350 return actual == (SIZEOF_FInfo + (fxinfo ? SIZEOF_FXInfo : 0));
351 }
352
353 // Get native Finder info
354 static bool get_finfo_from_native(const char *path, uint8 *finfo, uint8 *fxinfo)
355 {
356 struct attrlist attrList;
357 memset(&attrList, 0, sizeof(attrList));
358 attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
359 attrList.commonattr = ATTR_CMN_FNDRINFO;
360
361 FinderInfoAttrBuf attrBuf;
362 if (getattrlist(path, &attrList, &attrBuf, sizeof(attrBuf), 0) < 0)
363 return false;
364
365 memcpy(finfo, attrBuf.finderInfo, SIZEOF_FInfo);
366 if (fxinfo)
367 memcpy(fxinfo, attrBuf.extendedFinderInfo, SIZEOF_FXInfo);
368 return true;
369 }
370
371 static bool do_get_finfo(const char *path, bool has_fxinfo,
372 FinderInfo emu_finfo, FinderInfo emu_fxinfo,
373 FinderInfo nat_finfo, FinderInfo nat_fxinfo)
374 {
375 memset(emu_finfo, 0, SIZEOF_FInfo);
376 if (has_fxinfo)
377 memset(emu_fxinfo, 0, SIZEOF_FXInfo);
378 *((uint16 *)(emu_finfo + fdFlags)) = htonl(DEFAULT_FINDER_FLAGS);
379 *((uint32 *)(emu_finfo + fdLocation)) = htonl((uint32)-1);
380
381 if (USE_XATTRS)
382 get_finfo_from_xattr(path, emu_finfo, has_fxinfo ? emu_fxinfo : NULL);
383 else
384 get_finfo_from_helper(path, emu_finfo, has_fxinfo ? emu_fxinfo : NULL);
385
386 if (!get_finfo_from_native(path, nat_finfo, has_fxinfo ? nat_fxinfo : NULL))
387 return false;
388 return true;
389 }
390
391 void get_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir)
392 {
393 // Set default finder info
394 Mac_memset(finfo, 0, SIZEOF_FInfo);
395 if (fxinfo)
396 Mac_memset(fxinfo, 0, SIZEOF_FXInfo);
397 WriteMacInt16(finfo + fdFlags, DEFAULT_FINDER_FLAGS);
398 WriteMacInt32(finfo + fdLocation, (uint32)-1);
399
400 // Merge emulated and native Finder info
401 FinderInfo emu_finfo, emu_fxinfo;
402 FinderInfo nat_finfo, nat_fxinfo;
403 if (do_get_finfo(path, fxinfo, emu_finfo, emu_fxinfo, nat_finfo, nat_fxinfo)) {
404 if (!is_dir) {
405 finfo_merge(Mac2HostAddr(finfo), emu_finfo, nat_finfo, kNativeFInfoMask);
406 if (fxinfo)
407 finfo_merge(Mac2HostAddr(fxinfo), emu_fxinfo, nat_fxinfo, kNativeFXInfoMask);
408 if (ReadMacInt32(finfo + fdType) != 0 && ReadMacInt32(finfo + fdCreator) != 0)
409 return;
410 }
411 else {
412 finfo_merge(Mac2HostAddr(finfo), emu_finfo, nat_finfo, kNativeDInfoMask);
413 if (fxinfo)
414 finfo_merge(Mac2HostAddr(fxinfo), emu_fxinfo, nat_fxinfo, kNativeDXInfoMask);
415 return;
416 }
417 }
418
419 // No native Finder info, translate file name extension to MacOS type/creator
420 if (!is_dir) {
421 int path_len = strlen(path);
422 for (int i=0; e2t_translation[i].ext; i++) {
423 int ext_len = strlen(e2t_translation[i].ext);
424 if (path_len < ext_len)
425 continue;
426 if (!strcmp(path + path_len - ext_len, e2t_translation[i].ext)) {
427 WriteMacInt32(finfo + fdType, e2t_translation[i].type);
428 WriteMacInt32(finfo + fdCreator, e2t_translation[i].creator);
429 break;
430 }
431 }
432 }
433 }
434
435 // Set emulated Finder info into metada (Tiger+)
436 static bool set_finfo_to_xattr(const char *path, const uint8 *finfo, const uint8 *fxinfo)
437 {
438 if (!set_xattr(path, XATTR_FINFO, finfo, SIZEOF_FInfo))
439 return false;
440 if (fxinfo && !set_xattr(path, XATTR_FXINFO, fxinfo, SIZEOF_FXInfo))
441 return false;
442 return true;
443 }
444
445 // Set emulated Finder info into helper file
446 static bool set_finfo_to_helper(const char *path, const uint8 *finfo, const uint8 *fxinfo)
447 {
448 int fd = open_finf(path, O_RDWR);
449 if (fd < 0)
450 return false;
451
452 ssize_t actual = write(fd, finfo, SIZEOF_FInfo);
453 if (fxinfo)
454 actual += write(fd, fxinfo, SIZEOF_FXInfo);
455 close(fd);
456 return actual == (SIZEOF_FInfo + (fxinfo ? SIZEOF_FXInfo : 0));
457 }
458
459 // Set native Finder info
460 static bool set_finfo_to_native(const char *path, const uint8 *finfo, const uint8 *fxinfo, bool is_dir)
461 {
462 struct attrlist attrList;
463 memset(&attrList, 0, sizeof(attrList));
464 attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
465 attrList.commonattr = ATTR_CMN_FNDRINFO;
466
467 FinderInfoAttrBuf attrBuf;
468 if (getattrlist(path, &attrList, &attrBuf, sizeof(attrBuf), 0) < 0)
469 return false;
470
471 finfo_merge(attrBuf.finderInfo, attrBuf.finderInfo, finfo, is_dir ? kNativeDInfoMask : kNativeFInfoMask);
472 if (fxinfo)
473 finfo_merge(attrBuf.extendedFinderInfo, attrBuf.extendedFinderInfo, fxinfo, is_dir ? kNativeDXInfoMask : kNativeFXInfoMask);
474
475 attrList.commonattr = ATTR_CMN_FNDRINFO;
476 if (setattrlist(path, &attrList, attrBuf.finderInfo, 2 * SIZEOF_FInfo, 0) < 0)
477 return false;
478 return true;
479 }
480
481 void set_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir)
482 {
483 // Extract native Finder info flags
484 FinderInfo nat_finfo, nat_fxinfo;
485 const uint8 *emu_finfo = Mac2HostAddr(finfo);
486 const uint8 *emu_fxinfo = fxinfo ? Mac2HostAddr(fxinfo) : NULL;
487 finfo_split(nat_finfo, emu_finfo, is_dir ? kNativeDInfoMask : kNativeFInfoMask);
488 if (fxinfo)
489 finfo_split(nat_fxinfo, emu_fxinfo, is_dir ? kNativeDXInfoMask : kNativeFXInfoMask);
490
491 // Update Finder info file (all flags)
492 if (USE_XATTRS)
493 set_finfo_to_xattr(path, emu_finfo, emu_fxinfo);
494 else
495 set_finfo_to_helper(path, emu_finfo, emu_fxinfo);
496
497 // Update native Finder info flags
498 set_finfo_to_native(path, nat_finfo, nat_fxinfo, is_dir);
499 }
500
501
502 /*
503 * Resource fork emulation functions
504 */
505
506 uint32 get_rfork_size(const char *path)
507 {
508 // Open resource file
509 int fd = open_rsrc(path, O_RDONLY);
510 if (fd < 0)
511 return 0;
512
513 // Get size
514 off_t size = lseek(fd, 0, SEEK_END);
515
516 // Close file and return size
517 close(fd);
518 return size < 0 ? 0 : size;
519 }
520
521 int open_rfork(const char *path, int flag)
522 {
523 return open_rsrc(path, flag);
524 }
525
526 void close_rfork(const char *path, int fd)
527 {
528 close(fd);
529 }
530
531
532 /*
533 * Read "length" bytes from file to "buffer",
534 * returns number of bytes read (or -1 on error)
535 */
536
537 ssize_t extfs_read(int fd, void *buffer, size_t length)
538 {
539 return read(fd, buffer, length);
540 }
541
542
543 /*
544 * Write "length" bytes from "buffer" to file,
545 * returns number of bytes written (or -1 on error)
546 */
547
548 ssize_t extfs_write(int fd, void *buffer, size_t length)
549 {
550 return write(fd, buffer, length);
551 }
552
553
554 /*
555 * Remove file/directory (and associated helper files),
556 * returns false on error (and sets errno)
557 */
558
559 bool extfs_remove(const char *path)
560 {
561 // Remove helpers first, don't complain if this fails
562 char helper_path[MAX_PATH_LENGTH];
563 make_finf_path(path, helper_path, false);
564 remove(helper_path);
565 make_rsrc_path(path, helper_path);
566 remove(helper_path);
567
568 // Now remove file or directory (and helper directories in the directory)
569 if (remove(path) < 0) {
570 if (errno == EISDIR || errno == ENOTEMPTY) {
571 helper_path[0] = 0;
572 strncpy(helper_path, path, MAX_PATH_LENGTH-1);
573 add_path_component(helper_path, ".finf");
574 rmdir(helper_path);
575 return rmdir(path) == 0;
576 } else
577 return false;
578 }
579 return true;
580 }
581
582
583 /*
584 * Rename/move file/directory (and associated helper files),
585 * returns false on error (and sets errno)
586 */
587
588 bool extfs_rename(const char *old_path, const char *new_path)
589 {
590 // Rename helpers first, don't complain if this fails
591 char old_helper_path[MAX_PATH_LENGTH], new_helper_path[MAX_PATH_LENGTH];
592 make_finf_path(old_path, old_helper_path, false);
593 make_finf_path(new_path, new_helper_path, false);
594 create_finf_dir(new_path);
595 rename(old_helper_path, new_helper_path);
596 make_rsrc_path(old_path, old_helper_path);
597 make_rsrc_path(new_path, new_helper_path);
598 rename(old_helper_path, new_helper_path);
599
600 // Now rename file
601 return rename(old_path, new_path) == 0;
602 }
603
604
605 /*
606 * Strings (filenames) conversion
607 */
608
609 // Convert string in the specified source and target encodings
610 const char *convert_string(const char *str, CFStringEncoding from, CFStringEncoding to)
611 {
612 const char *ostr = str;
613 CFStringRef cfstr = CFStringCreateWithCString(NULL, str, from);
614 if (cfstr) {
615 static char buffer[MAX_PATH_LENGTH];
616 memset(buffer, 0, sizeof(buffer));
617 if (CFStringGetCString(cfstr, buffer, sizeof(buffer), to))
618 ostr = buffer;
619 CFRelease(cfstr);
620 }
621 return ostr;
622 }
623
624 // Convert from the host OS filename encoding to MacRoman
625 const char *host_encoding_to_macroman(const char *filename)
626 {
627 return convert_string(filename, kCFStringEncodingUTF8, kCFStringEncodingMacRoman);
628 }
629
630 // Convert from MacRoman to host OS filename encoding
631 const char *macroman_to_host_encoding(const char *filename)
632 {
633 return convert_string(filename, kCFStringEncodingMacRoman, kCFStringEncodingUTF8);
634 }