]> arthur.barton.de Git - netatalk.git/blobdiff - libatalk/adouble/ad_open.c
Start adouble documentation in Doxygen style
[netatalk.git] / libatalk / adouble / ad_open.c
index 5f7ca0f1864762fcaf9d9987052baeeace4d1984..5b3f93c483b4dd3dbfad88969d2b3a5188194c4b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ad_open.c,v 1.57 2009-11-07 01:18:50 didg Exp $
+ * $Id: ad_open.c,v 1.61 2010-01-04 13:49:48 franklahm Exp $
  *
  * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu)
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  *  +1-313-763-0525
  *  netatalk@itd.umich.edu
  *
- * NOTE: I don't use inline because a good compiler should be
- * able to optimize all the static below. Didier
+ */
+
+/*!
+ * @file
+ * Part of Netatalk's AppleDouble implementatation
+ * @note We don't use inlines because a good compiler should be
+ *       able to optimize all the static funcs below.
+ * @sa include/atalk/adouble.h
  */
 
 #ifdef HAVE_CONFIG_H
@@ -1178,23 +1184,69 @@ static struct adouble_fops ad_adouble = {
 
 void ad_init(struct adouble *ad, int flags, int options)
 {
-    memset( ad, 0, sizeof( struct adouble ) );
+    ad->ad_inited = 0;
     ad->ad_flags = flags;
     if (flags == AD_VERSION2_OSX) {
         ad->ad_ops = &ad_osx;
+        ad->ad_md = &ad->ad_resource_fork;
     }
     else if (flags == AD_VERSION1_SFM) {
         ad->ad_ops = &ad_sfm;
+        ad->ad_md = &ad->ad_metadata_fork;
     }
     else {
         ad->ad_ops = &ad_adouble;
+        ad->ad_md = &ad->ad_resource_fork;
     }
     ad->ad_options = options;
+
+    ad_data_fileno(ad) = -1;
+    ad_reso_fileno(ad) = -1;
+    ad_meta_fileno(ad) = -1;
+    /* following can be read even if there's no
+     * meda data.
+     */
+    memset(ad->ad_eid, 0, sizeof( ad->ad_eid ));
+    ad->ad_rlen = 0;
 }
 
-/* -------------------
- * It's not possible to open the header file O_RDONLY -- the read
- * will fail and return an error. this refcounts things now.
+/*!
+ * Open data-, metadata(header)- or ressource fork
+ *
+ * You must call ad_init() before ad_open, usually you'll just call it like this: \n
+ * @code
+ *      struct adoube ad;
+ *      ad_init(&ad, vol->v_adouble, vol->v_ad_options);
+ * @endcode
+ *
+ * @param path    Path to file or directory
+ *
+ * @param adflags ADFLAGS_DF: open data file/fork\n
+ *                ADFLAGS_HF: open header (metadata) file\n
+ *                ADFLAGS_RF: open ressource fork *** FIXME: not used ?! *** \n
+ *                ADFLAGS_CREATE: indicate creation\n
+ *                ADFLAGS_NOHF: it's not an error if header file couldn't be created\n
+ *                ADFLAGS_DIR: if path is a directory you MUST or ADFLAGS_DIR to adflags\n
+ *                ADFLAGS_NOADOUBLE: dont create adouble files if not necessary\n
+ *                ADFLAGS_RDONLY: open read only\n
+ *                ADFLAGS_OPENFORKS: check for open forks from other processes\n
+ *                ADFLAGS_MD: alias for ADFLAGS_HF\n
+ *                ADFLAGS_V1COMPAT: obsolete
+ *
+ * @param oflags  flags passed through to open syscall: \n
+ *                O_RDONLY: *** FIXME *** \n
+ *                O_RDWR: *** FIXME *** \n
+ *                O_CREAT: create fork\n
+ *                O_EXCL: fail if exists with O_CREAT
+ *
+ * @param mode    passed to open with O_CREAT
+ *
+ * @param ad      pointer to struct adouble
+ *
+ * @returns 0 on success
+ *
+ * @note It's not possible to open the header file O_RDONLY -- the read
+ *       will fail and return an error. this refcounts things now.
  */
 int ad_open( const char *path, int adflags, int oflags, int mode, struct adouble  *ad)
 {
@@ -1207,22 +1259,12 @@ int ad_open( const char *path, int adflags, int oflags, int mode, struct adouble
     int                 open_df = 0;
 
     if (ad->ad_inited != AD_INITED) {
-        ad_data_fileno(ad) = -1;
-        ad_reso_fileno(ad) = -1;
-        adf_lock_init(&ad->ad_data_fork);
-        adf_lock_init(&ad->ad_resource_fork);
-        if (ad->ad_flags != AD_VERSION1_SFM) {
-            ad->ad_md = &ad->ad_resource_fork;
-        }
-        else {
-            adf_lock_init(&ad->ad_metadata_fork);
-            ad->ad_md = &ad->ad_metadata_fork;
-            ad_meta_fileno(ad) = -1;
-        }
         ad->ad_inited = AD_INITED;
         ad->ad_refcount = 1;
         ad->ad_open_forks = 0;
         ad->ad_adflags = adflags;
+        ad->ad_resource_fork.adf_refcount = 0;
+        ad->ad_data_fork.adf_refcount = 0;
     }
     else {
         ad->ad_open_forks = ((ad->ad_data_fork.adf_refcount > 0) ? ATTRBIT_DOPEN : 0);
@@ -1257,6 +1299,7 @@ int ad_open( const char *path, int adflags, int oflags, int mode, struct adouble
                 /* just created, set owner if admin (root) */
                 ad_chown(path, &st_dir);
             }
+            adf_lock_init(&ad->ad_data_fork);
         }
         else {
             /* the file is already open... but */
@@ -1298,6 +1341,8 @@ int ad_open( const char *path, int adflags, int oflags, int mode, struct adouble
         goto sfm;
     }
 
+    memset(ad->ad_eid, 0, sizeof( ad->ad_eid ));
+    ad->ad_rlen = 0;
     ad_p = ad->ad_ops->ad_path( path, adflags );
 
     hoflags = oflags & ~(O_CREAT | O_EXCL);
@@ -1366,8 +1411,8 @@ int ad_open( const char *path, int adflags, int oflags, int mode, struct adouble
     }
     AD_SET(ad->ad_md->adf_off);
 
-    memset(ad->ad_eid, 0, sizeof( ad->ad_eid ));
-    ad->ad_md->adf_refcount++;
+    ad->ad_md->adf_refcount = 1;
+    adf_lock_init(ad->ad_md);
     if ((ad->ad_md->adf_flags & ( O_TRUNC | O_CREAT ))) {
         /*
          * This is a new adouble header file. Initialize the structure,
@@ -1422,8 +1467,6 @@ sfm:
 
     ad_p = ad->ad_ops->ad_path( path, ADFLAGS_RF );
 
-    hoflags = (oflags & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
-    ad->ad_resource_fork.adf_fd = open( ad_p, hoflags, admode );
     admode = mode;
     st_invalid = ad_mode_st(ad_p, &admode, &st_dir);
 
@@ -1431,6 +1474,9 @@ sfm:
         admode = mode;
     }
 
+    hoflags = (oflags & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
+    ad->ad_resource_fork.adf_fd = open( ad_p, hoflags, admode );
+
     if (ad->ad_resource_fork.adf_fd < 0 ) {
         if ((errno == EACCES || errno == EROFS) && !(oflags & O_RDWR)) {
             hoflags = oflags;
@@ -1445,7 +1491,7 @@ sfm:
         errno = err;
         return -1;
     }
-
+    adf_lock_init(&ad->ad_resource_fork);
     AD_SET(ad->ad_resource_fork.adf_off);
     ad->ad_resource_fork.adf_flags = hoflags;
     if ((oflags & O_CREAT) && !st_invalid) {
@@ -1466,10 +1512,15 @@ int ad_metadata(const char *name, int flags, struct adouble *adp)
     uid_t uid;
     int   ret, err;
     int   dir = flags & ADFLAGS_DIR;
-
+    int   adouble = 0;
+    
+    if (!(flags & ADFLAGS_NOADOUBLE)) {
+      adouble = O_CREAT;
+    }
+    
     /* Open with O_CREAT, thus enumarating a dir will create missing adouble files, see: */
     /* http://marc.info/?l=netatalk-devel&m=124039156832408&w=2 */
-    if ((ret = ad_open(name, ADFLAGS_HF | dir, O_RDWR | O_CREAT, 0666, adp)) < 0 && errno == EACCES) {
+    if ((ret = ad_open(name, ADFLAGS_HF | dir, O_RDWR | adouble, 0666, adp)) < 0 && errno == EACCES) {
         uid = geteuid();
         if (seteuid(0)) {
             LOG(log_error, logtype_default, "ad_metadata(%s): seteuid failed %s", name, strerror(errno));