unison

Fork of Unison, a bi-directional file synchronization tool
git clone git://git.laack.co/unison.git
Log | Files | Refs | README | LICENSE

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 }