1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
/* Unison file synchronizer: src/osxsupport.c */
/* $Id: $ */
/* Copyright 1999-2006 (see COPYING for details) */
#include <caml/mlvalues.h>
#include <caml/alloc.h>
#include <caml/memory.h>
#ifdef __APPLE__
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/attr.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#endif
#include <errno.h>
extern void unix_error (int errcode, char * cmdname, value arg) Noreturn;
extern void uerror (char * cmdname, value arg) Noreturn;
CAMLprim value isMacOSX (value nothing) {
#ifdef __APPLE__
return Val_true;
#else
return Val_false;
#endif
}
CAMLprim value getFileInfos (value path, value need_size) {
#ifdef __APPLE__
CAMLparam1(path);
CAMLlocal3(res, fInfo, length);
int retcode;
struct attrlist attrList;
unsigned long options = 0;
struct {
unsigned long length;
char finderInfo [32];
off_t rsrcLength;
} attrBuf;
attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
attrList.reserved = 0;
attrList.commonattr = ATTR_CMN_FNDRINFO;
attrList.volattr = 0; /* volume attribute group */
attrList.dirattr = 0; /* directory attribute group */
if (Bool_val (need_size))
attrList.fileattr = ATTR_FILE_RSRCLENGTH; /* file attribute group */
else
attrList.fileattr = 0;
attrList.forkattr = 0; /* fork attribute group */
retcode = getattrlist(String_val (path), &attrList, &attrBuf,
sizeof attrBuf, options);
if (retcode == -1) uerror("getattrlist", path);
fInfo = alloc_string (32);
memcpy (String_val (fInfo), attrBuf.finderInfo, 32);
if (Bool_val (need_size))
length = copy_int64 (attrBuf.rsrcLength);
else
length = copy_int64 (0);
res = alloc_small (2, 0);
Field (res, 0) = fInfo;
Field (res, 1) = length;
CAMLreturn (res);
#else
unix_error (ENOSYS, "getattrlist", path);
#endif
}
CAMLprim value setFileInfos (value path, value fInfo) {
#ifdef __APPLE__
CAMLparam2(path, fInfo);
int retcode;
struct attrlist attrList;
unsigned long options = 0;
struct {
unsigned long length;
char finderInfo [32];
} attrBuf;
attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
attrList.reserved = 0;
attrList.commonattr = ATTR_CMN_FNDRINFO;
attrList.volattr = 0; /* volume attribute group */
attrList.dirattr = 0; /* directory attribute group */
attrList.fileattr = 0; /* file attribute group */
attrList.forkattr = 0; /* fork attribute group */
memcpy (attrBuf.finderInfo, String_val (fInfo), 32);
retcode = setattrlist(String_val (path), &attrList, attrBuf.finderInfo,
sizeof attrBuf.finderInfo, options);
if (retcode == -1 && errno == EACCES) {
/* Unlike with normal Unix attributes, we cannot set OS X attributes
if file is read-only. Try making it writable temporarily. */
struct stat st;
int r = stat(String_val(path), &st);
if (r == -1) uerror("setattrlist", path);
r = chmod(String_val(path), st.st_mode | S_IWUSR);
if (r == -1) uerror("setattrlist", path);
/* Try again */
retcode = setattrlist(String_val (path), &attrList, attrBuf.finderInfo,
sizeof attrBuf.finderInfo, options);
/* Whether or not that worked, we should try to set the mode back. */
chmod(String_val(path), st.st_mode);
}
if (retcode == -1) uerror("setattrlist", path);
CAMLreturn (Val_unit);
#else
unix_error (ENOSYS, "setattrlist", path);
#endif
}
|