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