blob: be1ce29ba35e4a3219ae2d1f70d84fe3f506b354 [file] [log] [blame]
Jack Jansene9b2a052001-11-06 11:10:13 +00001/*
2 $Log$
Jack Jansen24aa3ce2001-11-06 12:06:39 +00003 Revision 1.2 2001/11/06 12:06:39 jackjansen
4 First couple of fixes to make it compile with Universal 3.3.2.
Jack Jansene9b2a052001-11-06 11:10:13 +00005
6 Revision 1.8 2001/10/03 17:29:01 ganatra
7 add parent method to FSRef class
8
9 Revision 1.7 2001/04/13 20:54:19 ganatra
10 More standard format for MacOSError exceptions
11
12 Revision 1.6 2001/04/11 04:07:40 ganatra
13 Add permissions constants and log header..
14
15*/
16
17
Jack Jansene9b2a052001-11-06 11:10:13 +000018#include "Python.h"
Jack Jansen24aa3ce2001-11-06 12:06:39 +000019#ifdef WITHOUT_FRAMEWORKS
20#include <Files.h>
21#else
22#include <CoreServices/CoreServices.h>
23#endif
Jack Jansene9b2a052001-11-06 11:10:13 +000024
25static PyObject *
26dict_from_cataloginfo(FSCatalogInfoBitmap bitmap, const FSCatalogInfo *info, HFSUniStr255 *uni);
27static
28PyObject *macos_error_for_call(OSErr err, const char *name, const char *item);
29static
30int insert_long(FSCatalogInfoBitmap bitmap, UInt32 bit, PyObject *dict, const char *symbol, UInt32 value);
31static
32int insert_slong(FSCatalogInfoBitmap bitmap, UInt32 bit, PyObject *dict, const char *symbol, long value);
33static
34int insert_int(PyObject *d, const char *symbol, int value);
35static
36Boolean fsref_isdirectory(const FSRef *ref);
37static
38PyObject *obj_to_hfsunistr(PyObject *in, HFSUniStr255 *uni);
39
40static
41int cataloginfo_from_dict(FSCatalogInfoBitmap bitmap, FSCatalogInfo *info, const PyObject *dict);
42
43
44static PyObject *ErrorObject;
45
46//__________________________________________________________________________________________________
47//_______________________________________ FORKREF OBJECT ___________________________________________
48//__________________________________________________________________________________________________
49
50typedef struct {
51 PyObject_HEAD
52 PyObject *x_attr;
53 short forkref;
54} forkRefObject;
55
56staticforward PyTypeObject forkRefObject_Type;
57
58#define forkRefObject_Check(v) ((v)->ob_type == &forkRefObject_Type)
59
60//__________________________________________________________________________________________________
61
62static
63forkRefObject *newForkRefObject(PyObject *arg, FSRef *ref, Boolean resourceFork, SInt8 permissions)
64{
65 OSErr err;
66 HFSUniStr255 forkName;
67
68 forkRefObject *self = PyObject_New(forkRefObject, &forkRefObject_Type);
69 if (self == NULL)
70 return NULL;
71
72 if (resourceFork)
73 (void) FSGetResourceForkName(&forkName);
74 else
75 (void) FSGetDataForkName(&forkName);
76
77 Py_BEGIN_ALLOW_THREADS
78 err = FSOpenFork(ref, forkName.length, forkName.unicode, permissions, &self->forkref);
79 Py_END_ALLOW_THREADS
80 if (err != noErr) {
81 Py_DECREF(self);
82 return (forkRefObject *) macos_error_for_call(err, "FSOpenFork", NULL);
83 }
84
85 return self;
86}
87
88//__________________________________________________________________________________________________
89// forkRefObject methods
90//
91static
92void forkRefObject_dealloc(forkRefObject *self)
93{
94 Py_BEGIN_ALLOW_THREADS
95 if (self->forkref != -1)
96 FSClose(self->forkref);
97 Py_END_ALLOW_THREADS
98 PyObject_Del(self);
99}
100
101//__________________________________________________________________________________________________
102static char forkRefObject_read__doc__[] =
103"read([bytecount[, posmode[, offset]]]) -> String\n\n\
104Read bytes from a fork, optionally passing number of\n\
105bytes (default: 128 bytes), posmode (below) and offset:\n\
106 0: ignore offset; write at current mark (default)\n\
107 1: offset relative to the start of fork\n\
108 2: offset relative to the end of fork\n\
109 3: offset relative to current fork position\n\
110\n\
111Returns a string containing the contents of the buffer";
112
113static
114PyObject *forkRefObject_read(forkRefObject *self, PyObject *args)
115{
116 OSErr err;
117 ByteCount request = 128, actual;
118 unsigned posmode = fsAtMark;
119 long tempoffset = 0;
120 SInt64 posoffset;
121 PyObject *buffer;
122
123 if (!PyArg_ParseTuple(args, "|lil:read", &request, &posmode, &tempoffset))
124 return NULL;
125
126 posoffset = tempoffset;
127 buffer = PyString_FromStringAndSize((char *)NULL, request);
128 if (buffer == NULL)
129 return NULL;
130
131 Py_BEGIN_ALLOW_THREADS
132 err = FSReadFork(self->forkref, posmode, posoffset, request, PyString_AsString(buffer), &actual);
133 Py_END_ALLOW_THREADS
134 if ((err != noErr) && (err != eofErr)) {
135 Py_DECREF(buffer);
136 return macos_error_for_call(err, "FSReadFork", NULL);
137 }
138
139 if (actual != request)
140 _PyString_Resize(&buffer, actual);
141
142 Py_INCREF(buffer);
143 return buffer;
144}
145
146//__________________________________________________________________________________________________
147static char forkRefObject_write__doc__[] =
148"write(buffer [bytecount[, posmode[, offset]]]) -> None\n\n\
149Write buffer to fork, optionally passing number of bytes, posmode (below) and offset:\n\
150 0: ignore offset; write at current mark (default)\n\
151 1: offset relative to the start of fork\n\
152 2: offset relative to the end of fork\n\
153 3: offset relative to current fork position";
154
155static
156PyObject *forkRefObject_write(forkRefObject *self, PyObject *args)
157{
158 OSErr err;
159 ByteCount request = -1, actual;
160 int size;
161 char *buffer;
162 unsigned posmode = fsAtMark;
163 long tempoffset = 0;
164 SInt64 posoffset;
165
166 if (!PyArg_ParseTuple(args, "s#|lil:write", &buffer, &size, &request, &posmode, &tempoffset))
167 return NULL;
168
169 posoffset = tempoffset;
170 if (request == -1)
171 request = size;
172
173 Py_BEGIN_ALLOW_THREADS
174 err = FSWriteFork(self->forkref, posmode, posoffset, request, buffer, &actual);
175 Py_END_ALLOW_THREADS
176 if (err)
177 return macos_error_for_call(err, "FSWriteFork", NULL);
178
179 Py_INCREF(Py_None);
180 return Py_None;
181}
182
183//__________________________________________________________________________________________________
184static char forkRefObject_close__doc__[] =
185"close() -> None\n\n\
186Close a reference to an open fork.";
187
188static
189PyObject *forkRefObject_close(forkRefObject *self, PyObject *args)
190{
191 OSErr err;
192
193 Py_BEGIN_ALLOW_THREADS
194 err = FSClose(self->forkref);
195 Py_END_ALLOW_THREADS
196 if (err)
197 return macos_error_for_call(err, "FSClose", NULL);
198
199 self->forkref = -1;
200
201 Py_INCREF(Py_None);
202 return Py_None;
203}
204
205//__________________________________________________________________________________________________
206static char forkRefObject_seek__doc__[] =
207"seek(offset [,posmode]) -> None\n\n\
208Set the current position in the fork with an optional posmode:\n\
209 1: offset relative to the start of fork (default)\n\
210 2: offset relative to the end of fork\n\
211 3: offset relative to current fork position";
212
213static
214PyObject *forkRefObject_seek(forkRefObject *self, PyObject *args)
215{
216 OSErr err;
217 unsigned posmode = fsFromStart;
218 long tempoffset = 0;
219 SInt64 posoffset;
220
221 if (!PyArg_ParseTuple(args, "l|l:seek", &tempoffset, &posmode))
222 return NULL;
223
224 posoffset = tempoffset;
225 Py_BEGIN_ALLOW_THREADS
226 err = FSSetForkPosition(self->forkref, posmode, posoffset);
227 Py_END_ALLOW_THREADS
228
229 if (err)
230 return macos_error_for_call(err, "FSSetForkPosition", NULL);
231
232 Py_INCREF(Py_None);
233 return Py_None;
234}
235
236//__________________________________________________________________________________________________
237static char forkRefObject_resize__doc__[] =
238"resize(offset [,posmode]) -> None\n\n\
239Set the fork size with an optional posmode:\n\
240 1: offset relative to the start of fork (default)\n\
241 2: offset relative to the end of fork\n\
242 3: offset relative to current fork position";
243
244static
245PyObject *forkRefObject_resize(forkRefObject *self, PyObject *args)
246{
247 OSErr err;
248 unsigned posmode = fsFromStart;
249 long tempoffset = 0;
250 SInt64 posoffset;
251
252 if (!PyArg_ParseTuple(args, "l|l:resize", &tempoffset, &posmode))
253 return NULL;
254
255 posoffset = tempoffset;
256 Py_BEGIN_ALLOW_THREADS
257 err = FSSetForkSize(self->forkref, posmode, posoffset);
258 Py_END_ALLOW_THREADS
259
260 if (err)
261 return macos_error_for_call(err, "FSSetForkSize", NULL);
262
263 Py_INCREF(Py_None);
264 return Py_None;
265}
266
267//__________________________________________________________________________________________________
268static char forkRefObject_tell__doc__[] =
269"tell() -> current position (Long)\n\n\
270Return the current position in the fork.";
271
272static
273PyObject *forkRefObject_tell(forkRefObject *self, PyObject *args)
274{
275 OSErr err;
276 SInt64 position;
277
278 Py_BEGIN_ALLOW_THREADS
279 err = FSGetForkPosition(self->forkref, &position);
280 Py_END_ALLOW_THREADS
281 if (err)
282 return macos_error_for_call(err, "FSGetForkPosition", NULL);
283
284 return PyLong_FromLongLong(position);
285}
286
287//__________________________________________________________________________________________________
288static char forkRefObject_length__doc__[] =
289"length() -> fork length (Long)\n\n\
290Return the logical length of the fork.";
291
292static
293PyObject *forkRefObject_length(forkRefObject *self, PyObject *args)
294{
295 OSErr err;
296 SInt64 size;
297
298 Py_BEGIN_ALLOW_THREADS
299 err = FSGetForkSize(self->forkref, &size);
300 Py_END_ALLOW_THREADS
301 if (err)
302 return macos_error_for_call(err, "FSGetForkSize", NULL);
303
304 return PyLong_FromLongLong(size);
305}
306
307//__________________________________________________________________________________________________
308
309static PyMethodDef forkRefObject_methods[] = {
310 {"read", (PyCFunction)forkRefObject_read,METH_VARARGS, forkRefObject_read__doc__},
311 {"write", (PyCFunction)forkRefObject_write,METH_VARARGS, forkRefObject_write__doc__},
312 {"close", (PyCFunction)forkRefObject_close,METH_VARARGS, forkRefObject_close__doc__},
313 {"seek", (PyCFunction)forkRefObject_seek,METH_VARARGS, forkRefObject_seek__doc__},
314 {"tell", (PyCFunction)forkRefObject_tell,METH_VARARGS, forkRefObject_tell__doc__},
315 {"length", (PyCFunction)forkRefObject_length,METH_VARARGS, forkRefObject_length__doc__},
316 {"resize", (PyCFunction)forkRefObject_resize,METH_VARARGS, forkRefObject_resize__doc__},
317 {NULL, NULL}
318};
319
320//__________________________________________________________________________________________________
321
322static
323PyObject *forkRefObject_getattr(forkRefObject *self, char *name)
324{
325 return Py_FindMethod(forkRefObject_methods, (PyObject *)self, name);
326}
327
328//__________________________________________________________________________________________________
329
330static int
331forkRefObject_print(forkRefObject *self, FILE *fp, int flags)
332{
333 fprintf(fp, "%d", self->forkref);
334 return 0;
335}
336
337//__________________________________________________________________________________________________
338
339statichere PyTypeObject forkRefObject_Type = {
340 /* The ob_type field must be initialized in the module init function
341 * to be portable to Windows without using C++. */
342 PyObject_HEAD_INIT(NULL)
343 0, /*ob_size*/
344 "openfile", /*tp_name*/
345 sizeof(forkRefObject), /*tp_basicsize*/
346 0, /*tp_itemsize*/
347 /* methods */
348 (destructor)forkRefObject_dealloc, /*tp_dealloc*/
349 (printfunc)forkRefObject_print, /*tp_print*/
350 (getattrfunc)forkRefObject_getattr, /*tp_getattr*/
351 0, /*tp_setattr*/
352 0, /*tp_compare*/
353 0, /*tp_repr*/
354 0, /*tp_as_number*/
355 0, /*tp_as_sequence*/
356 0, /*tp_as_mapping*/
357 0, /*tp_hash*/
358};
359
360
361
362//__________________________________________________________________________________________________
363//_______________________________________ ITERATOR OBJECT __________________________________________
364//__________________________________________________________________________________________________
365
366typedef struct {
367 PyObject_HEAD
368 PyObject *x_attr;
369 FSIterator iterator;
370} iteratorObject;
371
372staticforward PyTypeObject iteratorObject_Type;
373
374#define iteratorObject_Check(v) ((v)->ob_type == &iteratorObject_Type)
375
376static
377iteratorObject *newIteratorObject(PyObject *arg, FSRef *ref)
378{
379 OSErr err;
380 iteratorObject *self = PyObject_New(iteratorObject, &iteratorObject_Type);
381 if (self == NULL)
382 return NULL;
383
384 self->x_attr = NULL;
385 Py_BEGIN_ALLOW_THREADS
386 err = FSOpenIterator(ref, kFSIterateFlat, &self->iterator);
387 Py_END_ALLOW_THREADS
388 if (err != noErr) {
389 Py_DECREF(self);
390 return NULL;
391 }
392
393 return self;
394}
395
396//__________________________________________________________________________________________________
397// iteratorObject methods
398//
399static
400void iteratorObject_dealloc(iteratorObject *self)
401{
402 Py_XDECREF(self->x_attr);
403 FSCloseIterator(self->iterator);
404 PyObject_Del(self);
405}
406
407//__________________________________________________________________________________________________
408static char iteratorObject_listdir__doc__[] =
409"listdir([itemcount [, bitmap]]) -> Dict\n\n\
410Returns a dictionary of items and their attributes\n\
411for the given iterator and an optional bitmap describing\n\
412the attributes to be fetched (see CarbonCore/Files.h for\n\
413details of the bit definitions and key definitions).";
414
415static
416PyObject *iteratorObject_listdir(iteratorObject *self, PyObject *args)
417{
418 OSErr err;
419 int count = 500;
420 UInt32 actual;
421 FSCatalogInfoPtr infos;
422 HFSUniStr255 *unis;
423 PyObject *items;
424 unsigned i;
425 FSCatalogInfoBitmap bitmap = kFSCatInfoGettableInfo;
426
427 if (!PyArg_ParseTuple(args, "|il:listdir", &count, &bitmap))
428 return NULL;
429
430 items = PyList_New(0);
431 if (items == NULL)
432 return NULL;
433
434 infos = malloc(sizeof(FSCatalogInfo) * count);
435 if (infos == NULL)
436 return PyErr_NoMemory();
437
438 unis = malloc(sizeof(HFSUniStr255) * count);
439 if (unis == NULL) {
440 free(infos);
441 return PyErr_NoMemory();
442 }
443
444 err = FSGetCatalogInfoBulk(self->iterator, count, &actual, NULL, bitmap, infos, NULL, NULL, unis);
445
446 if (err == noErr || err == errFSNoMoreItems) {
447 for (i = 0; i < actual; i ++) {
448 PyObject *item;
449
450 item = dict_from_cataloginfo(bitmap, &infos[i], &unis[i]);
451 if (item == NULL)
452 continue;
453
454 if (PyList_Append(items, item) != 0) {
455 printf("ack! (PyList_Append)\n");
456 continue;
457 }
458 Py_DECREF(item);
459 }
460 }
461
462 free(infos);
463 free(unis);
464
465 Py_INCREF(items);
466 return items;
467}
468
469//__________________________________________________________________________________________________
470
471static PyMethodDef iteratorObject_methods[] = {
472 {"listdir", (PyCFunction)iteratorObject_listdir,METH_VARARGS, iteratorObject_listdir__doc__},
473 {NULL, NULL}
474};
475
476//__________________________________________________________________________________________________
477
478static
479PyObject *iteratorObject_getattr(iteratorObject *self, char *name)
480{
481 if (self->x_attr != NULL) {
482 PyObject *v = PyDict_GetItemString(self->x_attr, name);
483 if (v != NULL) {
484 Py_INCREF(v);
485 return v;
486 }
487 }
488 return Py_FindMethod(iteratorObject_methods, (PyObject *)self, name);
489}
490
491//__________________________________________________________________________________________________
492
493static
494int iteratorObject_setattr(iteratorObject *self, char *name, PyObject *v)
495{
496 if (self->x_attr == NULL) {
497 self->x_attr = PyDict_New();
498 if (self->x_attr == NULL)
499 return -1;
500 }
501 if (v == NULL) {
502 int rv = PyDict_DelItemString(self->x_attr, name);
503 if (rv < 0)
504 PyErr_SetString(PyExc_AttributeError, "delete non-existing iteratorObject attribute");
505 return rv;
506 }
507 else
508 return PyDict_SetItemString(self->x_attr, name, v);
509}
510
511//__________________________________________________________________________________________________
512
513statichere PyTypeObject iteratorObject_Type = {
514 /* The ob_type field must be initialized in the module init function
515 * to be portable to Windows without using C++. */
516 PyObject_HEAD_INIT(NULL)
517 0, /*ob_size*/
518 "iterator", /*tp_name*/
519 sizeof(iteratorObject), /*tp_basicsize*/
520 0, /*tp_itemsize*/
521 /* methods */
522 (destructor)iteratorObject_dealloc, /*tp_dealloc*/
523 0, /*tp_print*/
524 (getattrfunc)iteratorObject_getattr, /*tp_getattr*/
525 (setattrfunc)iteratorObject_setattr, /*tp_setattr*/
526 0, /*tp_compare*/
527 0, /*tp_repr*/
528 0, /*tp_as_number*/
529 0, /*tp_as_sequence*/
530 0, /*tp_as_mapping*/
531 0, /*tp_hash*/
532};
533
534
535//__________________________________________________________________________________________________
536//_________________________________________ FSREF OBJECT ___________________________________________
537//__________________________________________________________________________________________________
538
539typedef struct {
540 PyObject_HEAD
541 PyObject *x_attr;
542 FSRef ref;
543 int typeknown;
544 Boolean directory;
545} fsRefObject;
546
547staticforward PyTypeObject fsRefObject_Type;
548
549#define fsRefObject_Check(v) ((v)->ob_type == &fsRefObject_Type)
550
551static
552fsRefObject *newFSRefObject(PyObject *arg, FSRef *ref, Boolean typeknown, Boolean directory)
553{
554 fsRefObject *self = PyObject_New(fsRefObject, &fsRefObject_Type);
555 if (self == NULL)
556 return NULL;
557
558 self->x_attr = PyDict_New();
559 if (self->x_attr == NULL) {
560 Py_DECREF(self);
561 return NULL;
562 }
563
564 if (PyDict_SetItemString(self->x_attr, "directory", directory ? Py_True : Py_False) < 0) {
565 Py_XDECREF(self->x_attr);
566 Py_DECREF(self);
567 return NULL;
568 }
569
570 self->ref = *ref;
571 self->typeknown = typeknown;
572 self->directory = directory;
573 return self;
574}
575
576//__________________________________________________________________________________________________
577
578Boolean fsRefObject_isdir(fsRefObject *self)
579{
580 if (self->typeknown == false) {
581 self->directory = fsref_isdirectory(&self->ref);
582 self->typeknown = true;
583 }
584 return self->directory;
585}
586
587//__________________________________________________________________________________________________
588// fsRefObject methods
589//
590static
591void fsRefObject_dealloc(fsRefObject *self)
592{
593 Py_XDECREF(self->x_attr);
594 PyObject_Del(self);
595}
596
597//__________________________________________________________________________________________________
598static char fsRefObject_opendir__doc__[] =
599"opendir() -> iterator\n\n\
600Return an iterator";
601
602static
603PyObject *fsRefObject_opendir(fsRefObject *self, PyObject *args)
604{
605 iteratorObject *obj;
606
607 obj = newIteratorObject(args, &self->ref);
608 if (obj == NULL)
609 return NULL;
610 return (PyObject *) obj;
611}
612
613//__________________________________________________________________________________________________
614static char fsRefObject_namedfsref__doc__[] =
615"namedfsref(String) -> FSref\n\n\
616Return an FSRef for the named item in the container FSRef";
617
618static
619PyObject *fsRefObject_namedfsref(fsRefObject *self, PyObject *args)
620{
621 OSErr err;
622 fsRefObject *newObject;
623 FSRef newref;
624 HFSUniStr255 uni;
625 PyObject *namearg, *nameobj;
626
627 if (!PyArg_ParseTuple(args, "O|l:namedfsref", &namearg))
628 return NULL;
629
630 nameobj = obj_to_hfsunistr(namearg, &uni);
631 if (nameobj == NULL)
632 return NULL;
633 Py_DECREF(nameobj);
634
635 Py_BEGIN_ALLOW_THREADS
636 err = FSMakeFSRefUnicode(&self->ref, uni.length, uni.unicode, kTextEncodingUnknown, &newref);
637 Py_END_ALLOW_THREADS
638 if (err != noErr)
639 return macos_error_for_call(err, "FSMakeFSRefUnicode", NULL);
640
641 newObject = newFSRefObject(args, &newref, false, false);
642
643 Py_INCREF(newObject);
644 return (PyObject *) newObject;
645}
646
647//__________________________________________________________________________________________________
648static char fsRefObject_parent__doc__[] =
649"parent() -> FSref\n\n\
650Return an FSRef for the parent of this FSRef, or NULL (if this \n\
651is the root.)";
652
653static
654PyObject *fsRefObject_parent(fsRefObject *self, PyObject *args)
655{
656 OSErr err;
657 fsRefObject *newObject;
658 FSRef parentref;
659 FSCatalogInfo info;
660
661 Py_BEGIN_ALLOW_THREADS
662 err = FSGetCatalogInfo(&self->ref, kFSCatInfoParentDirID, &info, NULL, NULL, &parentref);
663 Py_END_ALLOW_THREADS
664 if (err != noErr)
665 return macos_error_for_call(err, "FSGetCatalogInfo", NULL);
666
667 if (info.parentDirID == fsRtParID)
668 return NULL;
669
670 newObject = newFSRefObject(args, &parentref, false, false);
671 Py_INCREF(newObject);
672 return (PyObject *) newObject;
673}
674
675//__________________________________________________________________________________________________
676static char fsRefObject_openfork__doc__[] =
677"openfork([resourcefork [,perms]]) -> forkRef\n\n\
678Return a forkRef object for reading/writing/etc. Optionally,\n\
679pass 1 for the resourcefork param to open the resource fork,\n\
680and permissions to open read-write or something else:\n\
6810: fsCurPerm\n\
6821: fsRdPerm (default)\n\
6832: fsWrPerm\n\
6843: fsRdWrPerm\n\
6854: fsRdWrShPerm";
686
687static
688PyObject *fsRefObject_openfork(fsRefObject *self, PyObject *args)
689{
690 forkRefObject *obj;
691 int resfork = 0, perms = fsRdPerm;
692
693 if (!PyArg_ParseTuple(args, "|ii:openfork", &resfork, &perms))
694 return NULL;
695
696 obj = newForkRefObject(args, &self->ref, resfork, perms);
697 if (obj == NULL)
698 return NULL;
699 return (PyObject *) obj;
700}
701
702//__________________________________________________________________________________________________
703
704static
705PyObject *fsRefObject_createcommon(Boolean createdir, fsRefObject *self, PyObject *args)
706{
707 OSErr err;
708 PyObject *nameobj, *namearg, *attrs = NULL;
709 FSRef newref;
710 fsRefObject *newObject;
711 HFSUniStr255 uni;
712 FSCatalogInfoBitmap bitmap = kFSCatInfoSettableInfo;
713 FSCatalogInfo info;
714
715 if (!PyArg_ParseTuple(args, "O|Ol", &namearg, &attrs, &bitmap))
716 return NULL;
717
718 nameobj = obj_to_hfsunistr(namearg, &uni);
719 if (nameobj == NULL)
720 return NULL;
721 Py_DECREF(nameobj);
722
723 if (attrs) {
724 if (!cataloginfo_from_dict(bitmap, &info, attrs))
725 return NULL;
726 } else {
727 bitmap = 0L;
728 }
729
730 if (createdir) {
731 Py_BEGIN_ALLOW_THREADS
732 err = FSCreateDirectoryUnicode(&self->ref, uni.length, uni.unicode, bitmap, &info, &newref, NULL, NULL);
733 Py_END_ALLOW_THREADS
734 if (err != noErr)
735 return macos_error_for_call(err, "FSCreateDirectoryUnicode", NULL);
736 } else {
737 Py_BEGIN_ALLOW_THREADS
738 err = FSCreateFileUnicode(&self->ref, uni.length, uni.unicode, bitmap, &info, &newref, NULL);
739 Py_END_ALLOW_THREADS
740 if (err != noErr)
741 return macos_error_for_call(err, "FSCreateFileUnicode", NULL);
742 }
743
744 newObject = newFSRefObject(args, &newref, true, createdir);
745 if (newObject == NULL)
746 return NULL;
747
748 Py_INCREF(newObject);
749 return (PyObject *) newObject;
750}
751
752//__________________________________________________________________________________________________
753static char fsRefObject_create__doc__[] =
754"create(name [,dict]) -> FSRef\n\n\
755Create a file in the specified directory with the given name\n\
756and return an FSRef object of the newly created item";
757
758static
759PyObject *fsRefObject_create(fsRefObject *self, PyObject *args)
760{
761 return fsRefObject_createcommon(false, self, args);
762}
763
764//__________________________________________________________________________________________________
765static char fsRefObject_mkdir__doc__[] =
766"mkdir(name [,dict]) -> FSRef\n\n\
767Create a directory in the specified directory with the given name\n\
768and return an FSRef object of the newly created item";
769
770static
771PyObject *fsRefObject_mkdir(fsRefObject *self, PyObject *args)
772{
773 return fsRefObject_createcommon(true, self, args);
774}
775
776//__________________________________________________________________________________________________
777static char fsRefObject_getcatinfo__doc__[] =
778"getcatinfo([bitmap]) -> Dict\n\n\
779Returns a dictionary of attributes for the given item\n\
780and an optional bitmap describing the attributes to be\n\
781fetched (see CarbonCore/Files.h for details of the bit\n\
782definitions and key definitions).";
783
784static
785PyObject *fsRefObject_getcatinfo(fsRefObject *self, PyObject *args)
786{
787 PyObject *dict;
788 OSErr err;
789 FSCatalogInfo info = {0};
790 HFSUniStr255 uni;
791 FSCatalogInfoBitmap bitmap = kFSCatInfoGettableInfo;
792
793 if (!PyArg_ParseTuple(args, "|l:getcatinfo", &bitmap))
794 return NULL;
795
796 Py_BEGIN_ALLOW_THREADS
797 err = FSGetCatalogInfo(&self->ref, bitmap, &info, &uni, NULL, NULL);
798 Py_END_ALLOW_THREADS
799 if (err != noErr)
800 return macos_error_for_call(err, "FSGetCatalogInfo", NULL);
801
802 dict = dict_from_cataloginfo(bitmap, &info, &uni);
803 if (dict == NULL)
804 return NULL;
805
806 Py_INCREF(dict);
807 return dict;
808}
809
810//__________________________________________________________________________________________________
811static char fsRefObject_setcatinfo__doc__[] =
812"setcatinfo(Dict [,bitmap]) -> None\n\n\
813Sets attributes for the given item. An optional\n\
814bitmap describing the attributes to be set can be\n\
815given as well (see CarbonCore/Files.h for details\n\
816of the bit definitions and key definitions).";
817
818static
819PyObject *fsRefObject_setcatinfo(fsRefObject *self, PyObject *args)
820{
821 PyObject *dict;
822 OSErr err;
823 FSCatalogInfo info = {0};
824 FSCatalogInfoBitmap bitmap = kFSCatInfoSettableInfo;
825
826 if (!PyArg_ParseTuple(args, "O|l:setcatinfo", &dict, &bitmap))
827 return NULL;
828
829 if (!cataloginfo_from_dict(bitmap, &info, dict)) return NULL;
830
831 Py_BEGIN_ALLOW_THREADS
832 err = FSSetCatalogInfo(&self->ref, bitmap, &info);
833 Py_END_ALLOW_THREADS
834 if (err != noErr)
835 return macos_error_for_call(err, "FSSetCatalogInfo", NULL);
836
837 Py_INCREF(Py_None);
838 return Py_None;
839}
840
841//__________________________________________________________________________________________________
842static char fsRefObject_delete__doc__[] =
843"delete() -> None\n\n\
844Delete the item";
845
846static
847PyObject *fsRefObject_delete(fsRefObject *self, PyObject *args)
848{
849 OSErr err;
850
851 Py_BEGIN_ALLOW_THREADS
852 err = FSDeleteObject(&self->ref);
853 Py_END_ALLOW_THREADS
854 if (err != noErr)
855 return macos_error_for_call(err, "FSDeleteObject", NULL);
856
857 Py_INCREF(Py_None);
858 return Py_None;
859}
860
861//__________________________________________________________________________________________________
862static char fsRefObject_exchange__doc__[] =
863"exchange(FSRef) -> None\n\n\
864Exchange this file with another.";
865
866static
867PyObject *fsRefObject_exchange(fsRefObject *self, PyObject *args)
868{
869 OSErr err;
870 fsRefObject *fsrefobj;
871
872 if (!PyArg_ParseTuple(args, "O|:exchange", &fsrefobj))
873 return NULL;
874
875 if (fsRefObject_Check(fsrefobj) == false)
876 return NULL;
877
878 Py_BEGIN_ALLOW_THREADS
879 err = FSExchangeObjects(&self->ref, &fsrefobj->ref);
880 Py_END_ALLOW_THREADS
881 if (err != noErr)
882 return macos_error_for_call(err, "FSExchangeObjects", NULL);
883
884 Py_INCREF(Py_None);
885 return Py_None;
886}
887
888//__________________________________________________________________________________________________
889static char fsRefObject_move__doc__[] =
890"move(FSRef) -> FSRef\n\n\
891Move the item to the container and return an FSRef to\n\
892the new item.";
893
894static
895PyObject *fsRefObject_move(fsRefObject *self, PyObject *args)
896{
897 OSErr err;
898 fsRefObject *newObject;
899 FSRef newref;
900 fsRefObject *fsrefobj;
901
902 if (!PyArg_ParseTuple(args, "O|:move", &fsrefobj))
903 return NULL;
904
905 if (fsRefObject_Check(fsrefobj) == false)
906 return NULL;
907
908 Py_BEGIN_ALLOW_THREADS
909 err = FSMoveObject(&self->ref, &fsrefobj->ref, &newref);
910 Py_END_ALLOW_THREADS
911 if (err != noErr)
912 return macos_error_for_call(err, "FSMoveObject", NULL);
913
914 newObject = newFSRefObject(args, &newref, false, false);
915 if (newObject == NULL)
916 return NULL;
917
918 Py_INCREF(newObject);
919 return (PyObject *) newObject;
920}
921
922//__________________________________________________________________________________________________
923static char fsRefObject_rename__doc__[] =
924"rename(String [,encoding]) -> FSRef\n\n\
925Rename the item to the new name and return an FSRef to\n\
926the new item.";
927
928static
929PyObject *fsRefObject_rename(fsRefObject *self, PyObject *args)
930{
931 OSErr err;
932 fsRefObject *newObject;
933 FSRef newref;
934 TextEncoding hint = kTextEncodingUnknown;
935 HFSUniStr255 uni;
936 PyObject *namearg, *nameobj;
937
938 if (!PyArg_ParseTuple(args, "O|l:rename", &namearg, &hint))
939 return NULL;
940
941 nameobj = obj_to_hfsunistr(namearg, &uni);
942 if (nameobj == NULL)
943 return NULL;
944 Py_DECREF(nameobj);
945
946 Py_BEGIN_ALLOW_THREADS
947 err = FSRenameUnicode(&self->ref, uni.length, uni.unicode, hint, &newref);
948 Py_END_ALLOW_THREADS
949 if (err != noErr)
950 return macos_error_for_call(err, "FSRenameUnicode", NULL);
951
952 newObject = newFSRefObject(args, &newref, false, false);
953 if (newObject == NULL)
954 return NULL;
955
956 Py_INCREF(newObject);
957 return (PyObject *) newObject;
958}
959
960
961//__________________________________________________________________________________________________
962
963static PyMethodDef fsRefObject_methods[] = {
964 {"getcatinfo", (PyCFunction)fsRefObject_getcatinfo,METH_VARARGS, fsRefObject_getcatinfo__doc__},
965 {"setcatinfo", (PyCFunction)fsRefObject_setcatinfo,METH_VARARGS, fsRefObject_setcatinfo__doc__},
966 {"create", (PyCFunction)fsRefObject_create, METH_VARARGS, fsRefObject_create__doc__},
967 {"mkdir", (PyCFunction)fsRefObject_mkdir, METH_VARARGS, fsRefObject_mkdir__doc__},
968 {"namedfsref", (PyCFunction)fsRefObject_namedfsref,METH_VARARGS, fsRefObject_namedfsref__doc__},
969 {"parent", (PyCFunction)fsRefObject_parent, METH_VARARGS, fsRefObject_parent__doc__},
970 {"delete", (PyCFunction)fsRefObject_delete, METH_VARARGS, fsRefObject_delete__doc__},
971 {"rename", (PyCFunction)fsRefObject_rename, METH_VARARGS, fsRefObject_rename__doc__},
972 {"move", (PyCFunction)fsRefObject_move, METH_VARARGS, fsRefObject_move__doc__},
973 {"exchange", (PyCFunction)fsRefObject_exchange, METH_VARARGS, fsRefObject_exchange__doc__},
974
975 {"opendir", (PyCFunction)fsRefObject_opendir, METH_VARARGS, fsRefObject_opendir__doc__},
976 {"openfork", (PyCFunction)fsRefObject_openfork, METH_VARARGS, fsRefObject_openfork__doc__},
977
978 {NULL, NULL}
979};
980
981//__________________________________________________________________________________________________
982
983static
984PyObject *fsRefObject_getattr(fsRefObject *self, char *name)
985{
986 if (self->x_attr != NULL) {
987 PyObject *v = PyDict_GetItemString(self->x_attr, name);
988 if (v != NULL) {
989 Py_INCREF(v);
990 return v;
991 }
992 }
993 return Py_FindMethod(fsRefObject_methods, (PyObject *)self, name);
994}
995
996//__________________________________________________________________________________________________
997
998static
999int fsRefObject_setattr(fsRefObject *self, char *name, PyObject *v)
1000{
1001 if (self->x_attr == NULL) {
1002 self->x_attr = PyDict_New();
1003 if (self->x_attr == NULL)
1004 return -1;
1005 }
1006 if (v == NULL) {
1007 int rv = PyDict_DelItemString(self->x_attr, name);
1008 if (rv < 0)
1009 PyErr_SetString(PyExc_AttributeError, "delete non-existing fsRefObject attribute");
1010 return rv;
1011 }
1012 else
1013 return PyDict_SetItemString(self->x_attr, name, v);
1014}
1015
1016//__________________________________________________________________________________________________
1017
1018statichere PyTypeObject fsRefObject_Type = {
1019 /* The ob_type field must be initialized in the module init function
1020 * to be portable to Windows without using C++. */
1021 PyObject_HEAD_INIT(NULL)
1022 0, /*ob_size*/
1023 "fsref", /*tp_name*/
1024 sizeof(fsRefObject), /*tp_basicsize*/
1025 0, /*tp_itemsize*/
1026 /* methods */
1027 (destructor)fsRefObject_dealloc, /*tp_dealloc*/
1028 0, /*tp_print*/
1029 (getattrfunc)fsRefObject_getattr, /*tp_getattr*/
1030 (setattrfunc)fsRefObject_setattr, /*tp_setattr*/
1031 0, /*tp_compare*/
1032 0, /*tp_repr*/
1033 0, /*tp_as_number*/
1034 0, /*tp_as_sequence*/
1035 0, /*tp_as_mapping*/
1036 0, /*tp_hash*/
1037};
1038
1039
1040
1041//__________________________________________________________________________________________________
1042//____________________________________ MODULE FUNCTIONS ____________________________________________
1043//__________________________________________________________________________________________________
1044static char fmgrmodule_getcatinfo__doc__[] =
1045"getcatinfo(path[,bitmap]) -> Dict\n\n\
1046Returns a dictionary of attributes for the given item\n\
1047and an optional bitmap describing the attributes to be\n\
1048fetched (see CarbonCore/Files.h for details of the bit\n\
1049definitions and key definitions).";
1050
1051static
1052PyObject *fmgrmodule_getcatinfo(PyObject *self, PyObject *args)
1053{
1054 char *path;
1055 PyObject *dict;
1056 FSRef ref;
1057 OSErr err;
1058 FSCatalogInfo info = {0};
1059 HFSUniStr255 uni;
1060 FSCatalogInfoBitmap bitmap = kFSCatInfoGettableInfo;
1061
1062 if (!PyArg_ParseTuple(args, "s|l", &path, &bitmap))
1063 return NULL;
1064
1065 Py_BEGIN_ALLOW_THREADS
Jack Jansen24aa3ce2001-11-06 12:06:39 +00001066 err = FSPathMakeRef((UInt8 *)path, &ref, NULL);
Jack Jansene9b2a052001-11-06 11:10:13 +00001067 Py_END_ALLOW_THREADS
1068 if (err != noErr)
1069 return macos_error_for_call(err, "FSPathMakeRef", path);
1070
1071 Py_BEGIN_ALLOW_THREADS
1072 err = FSGetCatalogInfo(&ref, bitmap, &info, &uni, NULL, NULL);
1073 Py_END_ALLOW_THREADS
1074 if (err != noErr)
1075 return macos_error_for_call(err, "FSGetCatalogInfo", path);
1076
1077 dict = dict_from_cataloginfo(bitmap, &info, &uni);
1078 if (dict == NULL)
1079 return NULL;
1080
1081 Py_INCREF(dict);
1082 return dict;
1083}
1084
1085//__________________________________________________________________________________________________
1086static char fmgrmodule_opendir__doc__[] =
1087"opendir(path) -> iterator\n\n\
1088Return an iterator for listdir.";
1089
1090static
1091PyObject *fmgrmodule_opendir(PyObject *self, PyObject *args)
1092{
1093 char *path;
1094 iteratorObject *rv;
1095 FSRef ref;
1096 OSErr err;
1097 Boolean isdir;
1098
1099 if (!PyArg_ParseTuple(args, "s", &path))
1100 return NULL;
1101
1102 Py_BEGIN_ALLOW_THREADS
Jack Jansen24aa3ce2001-11-06 12:06:39 +00001103 err = FSPathMakeRef((UInt8 *)path, &ref, &isdir);
Jack Jansene9b2a052001-11-06 11:10:13 +00001104 Py_END_ALLOW_THREADS
1105
1106 if (err != noErr)
1107 return macos_error_for_call(err, "FSPathMakeRef", path);
1108 else if (isdir == false)
1109 return PyErr_Format(PyExc_SyntaxError, "requires a directory");
1110
1111 rv = newIteratorObject(args, &ref);
1112 if (rv == NULL)
1113 return NULL;
1114 return (PyObject *) rv;
1115}
1116
1117//__________________________________________________________________________________________________
1118static char fmgrmodule_fsref__doc__[] =
1119"fsref(path) -> FSRef\n\n\
1120Return an FSRef object.";
1121
1122static
1123PyObject *fmgrmodule_fsref(PyObject *self, PyObject *args)
1124{
1125 char *path;
1126 fsRefObject *obj;
1127 FSRef ref;
1128 OSErr err;
1129 Boolean isdir;
1130
1131 if (!PyArg_ParseTuple(args, "s", &path))
1132 return NULL;
1133
1134 Py_BEGIN_ALLOW_THREADS
Jack Jansen24aa3ce2001-11-06 12:06:39 +00001135 err = FSPathMakeRef((UInt8 *)path, &ref, &isdir);
Jack Jansene9b2a052001-11-06 11:10:13 +00001136 Py_END_ALLOW_THREADS
1137
1138 if (err != noErr)
1139 return macos_error_for_call(err, "FSPathMakeRef", path);
1140
1141 obj = newFSRefObject(args, &ref, true, isdir);
1142 if (obj == NULL)
1143 return NULL;
1144 return (PyObject *) obj;
1145}
1146
1147//__________________________________________________________________________________________________
1148static char fmgrmodule_openfork__doc__[] =
1149"openfork(path[,resourcefork[,perms]]) -> forkRef\n\n\
1150Return a forkRef object for reading/writing/etc. Optionally,\n\
1151pass 1 for the resourcefork param to open the resource fork,\n\
1152and permissions to open read-write or something else:\n\
11530: fsCurPerm\n\
11541: fsRdPerm\n\
11552: fsWrPerm\n\
11563: fsRdWrPerm\n\
11574: fsRdWrShPerm";
1158
1159static
1160PyObject *fmgrmodule_openfork(PyObject *self, PyObject *args)
1161{
1162 char *path;
1163 forkRefObject *rv;
1164 FSRef ref;
1165 OSErr err;
1166 Boolean isdir;
1167 int resfork = 0, perms = fsRdPerm;
1168
1169 if (!PyArg_ParseTuple(args, "s|ii", &path, &resfork, &perms))
1170 return NULL;
1171
1172 Py_BEGIN_ALLOW_THREADS
Jack Jansen24aa3ce2001-11-06 12:06:39 +00001173 err = FSPathMakeRef((UInt8 *)path, &ref, &isdir);
Jack Jansene9b2a052001-11-06 11:10:13 +00001174 Py_END_ALLOW_THREADS
1175
1176 if (err != noErr) {
1177 return macos_error_for_call(err, "FSPathMakeRef", path);
1178 } else if (isdir == true) {
1179 return PyErr_Format(PyExc_SyntaxError, "requires a file");
1180 }
1181
1182 rv = newForkRefObject(args, &ref, resfork, perms);
1183 if (rv == NULL)
1184 return NULL;
1185 return (PyObject *) rv;
1186}
1187
1188//__________________________________________________________________________________________________
1189// List of functions defined in the module
1190//
1191static PyMethodDef fmgrmodule_methods[] = {
1192 {"getcatinfo", fmgrmodule_getcatinfo, METH_VARARGS, fmgrmodule_getcatinfo__doc__},
1193 {"opendir", fmgrmodule_opendir, METH_VARARGS, fmgrmodule_opendir__doc__},
1194 {"openfork", fmgrmodule_openfork, METH_VARARGS, fmgrmodule_openfork__doc__},
1195 {"fsref", fmgrmodule_fsref, METH_VARARGS, fmgrmodule_fsref__doc__},
1196 {NULL, NULL}
1197};
1198
1199//__________________________________________________________________________________________________
Jack Jansen24aa3ce2001-11-06 12:06:39 +00001200// Initialization function for the module (*must* be called inithfsplus)
Jack Jansene9b2a052001-11-06 11:10:13 +00001201//
1202DL_EXPORT(void)
Jack Jansen24aa3ce2001-11-06 12:06:39 +00001203inithfsplus(void)
Jack Jansene9b2a052001-11-06 11:10:13 +00001204{
1205 PyObject *m, *d;
1206
1207 /* Initialize the type of the new type object here; doing it here
1208 * is required for portability to Windows without requiring C++. */
1209 iteratorObject_Type.ob_type = &PyType_Type;
1210 forkRefObject_Type.ob_type = &PyType_Type;
1211 fsRefObject_Type.ob_type = &PyType_Type;
1212
1213 /* Create the module and add the functions */
1214 m = Py_InitModule("fmgr", fmgrmodule_methods);
1215
1216 /* Add some symbolic constants to the module */
1217 d = PyModule_GetDict(m);
1218 insert_int(d, "fsCurPerm", fsCurPerm);
1219 insert_int(d, "fsRdPerm", fsRdPerm);
1220 insert_int(d, "fsWrPerm", fsWrPerm);
1221 insert_int(d, "fsRdWrPerm", fsRdWrPerm);
1222 insert_int(d, "fsRdWrShPerm", fsRdWrShPerm);
1223 insert_int(d, "fsAtMark", fsAtMark);
1224 insert_int(d, "fsFromStart", fsFromStart);
1225 insert_int(d, "fsFromLEOF", fsFromLEOF);
1226 insert_int(d, "fsFromMark", fsFromMark);
1227 insert_int(d, "noCacheMask", noCacheMask);
1228 ErrorObject = PyErr_NewException("fmgr.error", NULL, NULL);
1229 PyDict_SetItemString(d, "error", ErrorObject);
1230}
1231
1232//__________________________________________________________________________________________________
1233//_________________________________________ UTILITIES ______________________________________________
1234//__________________________________________________________________________________________________
1235
1236static const char *_kFSCatInfoPrintableName = "pname";
1237static const char *_kFSCatInfoUnicodeName = "uname";
1238
1239static const char *_kFSCatInfoVolume = "volume";
1240static const char *_kFSCatInfoNodeID = "nodeid";
1241static const char *_kFSCatInfoParentDirID = "parid";
1242static const char *_kFSCatInfoTextEncoding = "encoding";
1243static const char *_kFSCatInfoNodeFlags = "flags";
1244
1245static const char *_kFSCatInfoDataLogical = "datalogicalsize";
1246static const char *_kFSCatInfoRsrcLogical = "rsrclogicalsize";
1247static const char *_kFSCatInfoDataPhysical = "dataphysicalsize";
1248static const char *_kFSCatInfoRsrcPhysical = "rsrcphysicalsize";
1249
1250static const char *_kFSCatInfoUserID = "uid";
1251static const char *_kFSCatInfoGroupID = "gid";
1252static const char *_kFSCatInfoUserAccess = "useraccess";
1253static const char *_kFSCatInfoMode = "mode";
1254
1255static const char *_kFSCatInfoFinderInfo = "finfo";
1256static const char *_kFSCatInfoFinderXInfo = "fxinfo";
1257
1258static const char *_kFSCatInfoCreateDate = "crdate";
1259static const char *_kFSCatInfoContentMod = "mddate";
1260static const char *_kFSCatInfoAttrMod = "amdate";
1261static const char *_kFSCatInfoAccessDate = "acdate";
1262static const char *_kFSCatInfoBackupDate = "bkdate";
1263
1264//__________________________________________________________________________________________________
1265
1266static
1267PyObject *macos_error_for_call(OSErr err, const char *name, const char *item)
1268{
1269 PyObject *v;
1270 char buffer[1024];
1271
1272 if (item)
1273 sprintf(buffer, "mac error calling %s on %s", name, item);
1274 else
1275 sprintf(buffer, "mac error calling %s", name);
1276
1277 v = Py_BuildValue("(is)", err, buffer);
1278 if (v != NULL) {
1279 PyErr_SetObject(PyExc_OSError, v);
1280 Py_DECREF(v);
1281 }
1282 return NULL;
1283}
1284//__________________________________________________________________________________________________
1285
1286static
1287int insert_slong(FSCatalogInfoBitmap bitmap, UInt32 bit, PyObject *d, const char *symbol, long value)
1288{
1289 if (bitmap & bit) {
1290 PyObject* v = PyLong_FromLong(value);
1291 if (!v || PyDict_SetItemString(d, (char *) symbol, v) < 0)
1292 return -1;
1293 Py_DECREF(v);
1294 }
1295 return 0;
1296}
1297
1298//__________________________________________________________________________________________________
1299
1300static
1301int insert_long(FSCatalogInfoBitmap bitmap, UInt32 bit, PyObject *d, const char *symbol, UInt32 value)
1302{
1303 if (bitmap & bit) {
1304 PyObject* v = PyLong_FromUnsignedLong(value);
1305 if (!v || PyDict_SetItemString(d, (char *) symbol, v) < 0)
1306 return -1;
1307 Py_DECREF(v);
1308 }
1309 return 0;
1310}
1311
1312//__________________________________________________________________________________________________
1313
1314static
1315int insert_int(PyObject *d, const char *symbol, int value)
1316{
1317 PyObject* v = PyInt_FromLong(value);
1318 if (!v || PyDict_SetItemString(d, (char *) symbol, v) < 0)
1319 return -1;
1320
1321 Py_DECREF(v);
1322 return 0;
1323}
1324
1325//__________________________________________________________________________________________________
1326
1327static
1328int insert_longlong(FSCatalogInfoBitmap bitmap, UInt32 bit, PyObject *d, const char *symbol, UInt64 value)
1329{
1330 if (bitmap & bit) {
1331 PyObject* v = PyLong_FromLongLong(value);
1332 if (!v || PyDict_SetItemString(d, (char *) symbol, v) < 0)
1333 return -1;
1334 Py_DECREF(v);
1335 }
1336 return 0;
1337}
1338
1339//__________________________________________________________________________________________________
1340
1341static
1342int insert_utcdatetime(FSCatalogInfoBitmap bitmap, UInt32 bit, PyObject *d, const char *symbol, const UTCDateTime *utc)
1343{
1344 if (bitmap & bit) {
1345 PyObject* tuple = Py_BuildValue("ili", utc->highSeconds, utc->lowSeconds, utc->fraction);
1346 if (!tuple || PyDict_SetItemString(d, (char *) symbol, tuple) < 0)
1347 return -1;
1348 Py_DECREF(tuple);
1349 }
1350 return 0;
1351}
1352
1353//__________________________________________________________________________________________________
1354
1355static
1356int fetch_long(FSCatalogInfoBitmap bitmap, UInt32 bit, const PyObject *d, const char *symbol, UInt32 *value)
1357{
1358 if (bitmap & bit) {
1359 PyObject* v = PyDict_GetItemString((PyObject *) d, (char *) symbol);
1360 if (v == NULL)
1361 return -1;
1362
1363 *value = PyLong_AsUnsignedLong(v);
1364 }
1365 return 0;
1366}
1367
1368//__________________________________________________________________________________________________
1369
1370static
1371int fetch_utcdatetime(FSCatalogInfoBitmap bitmap, UInt32 bit, const PyObject *d, const char *symbol, UTCDateTime *utc)
1372{
1373 if (bitmap & bit) {
1374 PyObject* tuple = PyDict_GetItemString((PyObject *) d, (char *) symbol);
1375 if (tuple == NULL)
1376 return -1;
1377
1378 if (!PyArg_ParseTuple(tuple, "ili", &utc->highSeconds, &utc->lowSeconds, &utc->fraction))
1379 return -1;
1380 }
1381
1382 return 0;
1383}
1384
1385//__________________________________________________________________________________________________
1386
1387static
1388void printableUniStr(const HFSUniStr255 *uni, char *buffer)
1389{
1390 int i;
1391 char localbuf[32];
1392
1393 buffer[0] = 0;
1394 for (i = 0; i < uni->length; i ++) {
1395 UniChar uch = uni->unicode[i];
1396
1397 if ((uch & 0x7f) == uch) {
1398 sprintf(localbuf, "%c", uch);
1399 } else {
1400 sprintf(localbuf, "\\u%04x", uch);
1401 }
1402 strcat(buffer, localbuf);
1403 }
1404}
1405
1406//__________________________________________________________________________________________________
1407
1408static
1409int cataloginfo_from_dict(FSCatalogInfoBitmap bitmap, FSCatalogInfo *info, const PyObject *dict)
1410{
1411 UInt32 storage;
Jack Jansen24aa3ce2001-11-06 12:06:39 +00001412#if UNIVERSAL_INTERFACES_VERSION > 0x0332
Jack Jansene9b2a052001-11-06 11:10:13 +00001413 FSPermissionInfo *permissions;
Jack Jansen24aa3ce2001-11-06 12:06:39 +00001414#endif
Jack Jansene9b2a052001-11-06 11:10:13 +00001415
1416 // Dates
1417 if (fetch_utcdatetime(bitmap, kFSCatInfoCreateDate, dict, _kFSCatInfoCreateDate, &info->createDate)) return NULL;
1418 if (fetch_utcdatetime(bitmap, kFSCatInfoContentMod, dict, _kFSCatInfoContentMod, &info->contentModDate)) return NULL;
1419 if (fetch_utcdatetime(bitmap, kFSCatInfoAttrMod, dict, _kFSCatInfoAttrMod, &info->attributeModDate)) return NULL;
1420 if (fetch_utcdatetime(bitmap, kFSCatInfoAccessDate, dict, _kFSCatInfoAccessDate, &info->accessDate)) return NULL;
1421 if (fetch_utcdatetime(bitmap, kFSCatInfoBackupDate, dict, _kFSCatInfoBackupDate, &info->backupDate)) return NULL;
1422
Jack Jansen24aa3ce2001-11-06 12:06:39 +00001423#if UNIVERSAL_INTERFACES_VERSION > 0x0332
Jack Jansene9b2a052001-11-06 11:10:13 +00001424 // Permissions
1425 permissions = (FSPermissionInfo *) info->permissions;
1426 if (fetch_long(bitmap, kFSCatInfoPermissions, dict, _kFSCatInfoUserID, &permissions->userID)) return NULL;
1427 if (fetch_long(bitmap, kFSCatInfoPermissions, dict, _kFSCatInfoGroupID, &permissions->groupID)) return NULL;
1428 if (fetch_long(bitmap, kFSCatInfoPermissions, dict, _kFSCatInfoMode, &storage)) return NULL;
1429 permissions->mode = (UInt16) storage;
1430 if (fetch_long(bitmap, kFSCatInfoPermissions, dict, _kFSCatInfoUserAccess, &storage)) return NULL;
1431 permissions->userAccess = (UInt8) storage;
Jack Jansen24aa3ce2001-11-06 12:06:39 +00001432#endif
Jack Jansene9b2a052001-11-06 11:10:13 +00001433 // IDs
1434 if (fetch_long(bitmap, kFSCatInfoTextEncoding, dict, _kFSCatInfoTextEncoding, &info->textEncodingHint)) return NULL;
1435 if (fetch_long(bitmap, kFSCatInfoNodeFlags, dict, _kFSCatInfoNodeFlags, &storage)) return NULL;
1436 info->nodeFlags = (UInt16) storage;
1437
1438 // FinderInfo
1439 if (bitmap & kFSCatInfoFinderInfo) {
1440 PyObject *obj = PyDict_GetItemString((PyObject *) dict, (char *) _kFSCatInfoFinderInfo);
1441 if (obj == NULL)
1442 return NULL;
1443 BlockMoveData(PyString_AsString(obj), info->finderInfo, sizeof(FInfo));
1444 }
1445
1446 if (bitmap & kFSCatInfoFinderXInfo) {
1447 PyObject *obj = PyDict_GetItemString((PyObject *) dict, (char *) _kFSCatInfoFinderXInfo);
1448 if (obj == NULL)
1449 return NULL;
1450 BlockMoveData(PyString_AsString(obj), info->extFinderInfo, sizeof(FXInfo));
1451 }
1452
1453 return 1;
1454}
1455
1456//__________________________________________________________________________________________________
1457
1458static
1459PyObject *dict_from_cataloginfo(FSCatalogInfoBitmap bitmap, const FSCatalogInfo *info, HFSUniStr255 *uni)
1460{
1461 PyObject *dict;
1462 PyObject *id;
Jack Jansen24aa3ce2001-11-06 12:06:39 +00001463#if UNIVERSAL_INTERFACES_VERSION > 0x0332
Jack Jansene9b2a052001-11-06 11:10:13 +00001464 FSPermissionInfo *permissions;
Jack Jansen24aa3ce2001-11-06 12:06:39 +00001465#endif
Jack Jansene9b2a052001-11-06 11:10:13 +00001466 char buffer[1024];
1467
1468 dict = PyDict_New();
1469 if (dict == NULL)
1470 return NULL;
1471
1472 // Name
1473 if (uni) {
1474 id = PyUnicode_FromUnicode(uni->unicode, uni->length);
1475 PyDict_SetItemString(dict, (char*) _kFSCatInfoUnicodeName, id); Py_XDECREF(id);
1476
1477 printableUniStr(uni, buffer);
1478 id = PyString_FromString(buffer);
1479 PyDict_SetItemString(dict, (char*) _kFSCatInfoPrintableName, id); Py_XDECREF(id);
1480 }
1481
1482 // IDs
1483 if (insert_slong(bitmap, kFSCatInfoVolume, dict, _kFSCatInfoVolume, info->volume)) return NULL;
1484 if (insert_long(bitmap, kFSCatInfoNodeID, dict, _kFSCatInfoNodeID, info->nodeID)) return NULL;
1485 if (insert_long(bitmap, kFSCatInfoParentDirID, dict, _kFSCatInfoParentDirID, info->parentDirID)) return NULL;
1486 if (insert_long(bitmap, kFSCatInfoTextEncoding, dict, _kFSCatInfoTextEncoding, info->textEncodingHint)) return NULL;
1487 if (insert_long(bitmap, kFSCatInfoNodeFlags, dict, _kFSCatInfoNodeFlags, info->nodeFlags)) return NULL;
1488
1489 // Sizes
1490 if (insert_longlong(bitmap, kFSCatInfoDataSizes, dict, _kFSCatInfoDataLogical, info->dataLogicalSize)) return NULL;
1491 if (insert_longlong(bitmap, kFSCatInfoDataSizes, dict, _kFSCatInfoDataPhysical, info->dataPhysicalSize)) return NULL;
1492 if (insert_longlong(bitmap, kFSCatInfoRsrcSizes, dict, _kFSCatInfoRsrcLogical, info->rsrcLogicalSize)) return NULL;
1493 if (insert_longlong(bitmap, kFSCatInfoRsrcSizes, dict, _kFSCatInfoRsrcPhysical, info->rsrcPhysicalSize)) return NULL;
1494
Jack Jansen24aa3ce2001-11-06 12:06:39 +00001495#if UNIVERSAL_INTERFACES_VERSION > 0x0332
Jack Jansene9b2a052001-11-06 11:10:13 +00001496 // Permissions
1497 permissions = (FSPermissionInfo *) info->permissions;
1498 if (insert_long(bitmap, kFSCatInfoPermissions, dict, _kFSCatInfoUserID, permissions->userID)) return NULL;
1499 if (insert_long(bitmap, kFSCatInfoPermissions, dict, _kFSCatInfoGroupID, permissions->groupID)) return NULL;
1500 if (insert_long(bitmap, kFSCatInfoPermissions, dict, _kFSCatInfoUserAccess, permissions->userAccess)) return NULL;
1501 if (insert_long(bitmap, kFSCatInfoPermissions, dict, _kFSCatInfoMode, permissions->mode)) return NULL;
Jack Jansen24aa3ce2001-11-06 12:06:39 +00001502#endif
Jack Jansene9b2a052001-11-06 11:10:13 +00001503
1504 // Dates
1505 if (insert_utcdatetime(bitmap, kFSCatInfoCreateDate, dict, _kFSCatInfoCreateDate, &info->createDate)) return NULL;
1506 if (insert_utcdatetime(bitmap, kFSCatInfoContentMod, dict, _kFSCatInfoContentMod, &info->contentModDate)) return NULL;
1507 if (insert_utcdatetime(bitmap, kFSCatInfoAttrMod, dict, _kFSCatInfoAttrMod, &info->attributeModDate)) return NULL;
1508 if (insert_utcdatetime(bitmap, kFSCatInfoAccessDate, dict, _kFSCatInfoAccessDate, &info->accessDate)) return NULL;
1509 if (insert_utcdatetime(bitmap, kFSCatInfoBackupDate, dict, _kFSCatInfoBackupDate, &info->backupDate)) return NULL;
1510
1511 // FinderInfo
1512 if (bitmap & kFSCatInfoFinderInfo) {
1513 id = Py_BuildValue("s#", (char *) info->finderInfo, sizeof(FInfo));
1514 PyDict_SetItemString(dict, (char*) _kFSCatInfoFinderInfo, id); Py_XDECREF(id);
1515 }
1516 if (bitmap & kFSCatInfoFinderXInfo) {
1517 id = Py_BuildValue("s#", (char *) info->extFinderInfo, sizeof(FXInfo));
1518 PyDict_SetItemString(dict, (char*) _kFSCatInfoFinderXInfo, id); Py_XDECREF(id);
1519 }
1520
1521 return dict;
1522}
1523
1524//__________________________________________________________________________________________________
1525
1526static
1527Boolean fsref_isdirectory(const FSRef *ref)
1528{
1529 Boolean isdir = false;
1530 OSErr err;
1531 FSCatalogInfo info;
1532
1533 err = FSGetCatalogInfo(ref, kFSCatInfoNodeFlags, &info, NULL, NULL, NULL);
1534
1535 if (err == noErr)
1536 isdir = (info.nodeFlags & kioFlAttribDirMask);
1537
1538 return isdir;
1539}
1540
1541//__________________________________________________________________________________________________
1542
1543static
1544PyObject *obj_to_hfsunistr(PyObject *in, HFSUniStr255 *uni)
1545{
1546 PyObject *out;
1547
1548 out = PyUnicode_FromObject(in);
1549 if (out == NULL)
1550 return NULL;
1551
1552 BlockMoveData(PyUnicode_AS_UNICODE(out), uni->unicode, PyUnicode_GET_DATA_SIZE(out));
1553 uni->length = PyUnicode_GET_SIZE(out);
1554
1555 return out;
1556}
1557
1558