]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/ofork.c
quotas: improve Linux quota behaviour
[netatalk.git] / etc / afpd / ofork.c
index fc91c03b18fa51f44f48be121d1672a2e6f5ab84..7c975c38f9ed581702e74827aaaf2c2d863e8ce7 100644 (file)
@@ -228,14 +228,14 @@ struct ofork *of_find(const uint16_t ofrefnum )
 }
 
 /* -------------------------- */
-int of_stat(struct path *path)
+int of_stat(const struct vol *vol, struct path *path)
 {
     int ret;
 
     path->st_errno = 0;
     path->st_valid = 1;
 
-    if ((ret = lstat(path->u_name, &path->st)) < 0) {
+    if ((ret = ostat(path->u_name, &path->st, vol_syml_opt(vol))) < 0) {
         LOG(log_debug, logtype_afpd, "of_stat('%s/%s': %s)",
             cfrombstr(curdir->d_fullpath), path->u_name, strerror(errno));
        path->st_errno = errno;
@@ -274,7 +274,7 @@ int of_statdir(struct vol *vol, struct path *path)
 
     if (*path->m_name) {
         /* not curdir */
-        return of_stat (path);
+        return of_stat(vol, path);
     }
     path->st_errno = 0;
     path->st_valid = 1;
@@ -286,7 +286,7 @@ int of_statdir(struct vol *vol, struct path *path)
 
     LOG(log_debug, logtype_afpd, "of_statdir: stating: '%s'", pathname);
 
-    if (!(ret = lstat(pathname, &path->st)))
+    if (!(ret = ostat(pathname, &path->st, vol_syml_opt(vol))))
         return 0;
 
     path->st_errno = errno;
@@ -297,7 +297,7 @@ int of_statdir(struct vol *vol, struct path *path)
            return -1;
        path->st_errno = 0;
 
-       if ((ret = lstat(cfrombstr(path->d_dir->d_u_name), &path->st)) < 0) 
+       if ((ret = ostat(cfrombstr(path->d_dir->d_u_name), &path->st, vol_syml_opt(vol))) < 0) 
            path->st_errno = errno;
     }
 
@@ -305,13 +305,13 @@ int of_statdir(struct vol *vol, struct path *path)
 }
 
 /* -------------------------- */
-struct ofork *of_findname(struct path *path)
+struct ofork *of_findname(const struct vol *vol, struct path *path)
 {
     struct ofork *of;
     struct file_key key;
 
     if (!path->st_valid) {
-        of_stat(path);
+        of_stat(vol, path);
     }
 
     if (path->st_errno)
@@ -364,7 +364,7 @@ struct ofork *of_findnameat(int dirfd, struct path *path)
 }
 #endif
 
-void of_dealloc( struct ofork *of)
+void of_dealloc(struct ofork *of)
 {
     if (!oforks)
         return;
@@ -378,15 +378,13 @@ void of_dealloc( struct ofork *of)
     if ( of->of_ad->ad_refcount <= 0) {
         free( of->of_ad->ad_name );
         free( of->of_ad);
-    } else {/* someone's still using it. just free this user's locks */
-        ad_unlock(of->of_ad, of->of_refnum, of->of_flags & AFPFORK_ERROR ? 0 : 1);
     }
 
     free( of );
 }
 
 /* --------------------------- */
-int of_closefork(struct ofork *ofork)
+int of_closefork(const AFPObj *obj, struct ofork *ofork)
 {
     struct timeval      tv;
     int         adflags = 0;
@@ -409,15 +407,34 @@ int of_closefork(struct ofork *ofork)
 
     /* Somone has used write_fork, we assume file was changed, register it to file change event api */
     if (ofork->of_flags & AFPFORK_MODIFIED) {
-        fce_register_file_modification(ofork);
+        struct dir *dir =  dirlookup(ofork->of_vol, ofork->of_did);
+        if (dir) {
+            bstring forkpath = bformat("%s/%s", bdata(dir->d_fullpath), of_name(ofork));
+            fce_register(FCE_FILE_MODIFY, bdata(forkpath), NULL, fce_file);
+            bdestroy(forkpath);
+        }
+    }
+
+    ad_unlock(ofork->of_ad, ofork->of_refnum, ofork->of_flags & AFPFORK_ERROR ? 0 : 1);
+
+#ifdef HAVE_FSHARE_T
+    if (obj->options.flags & OPTION_SHARE_RESERV) {
+        fshare_t shmd;
+        shmd.f_id = ofork->of_refnum;
+        if (AD_DATA_OPEN(ofork->of_ad))
+            fcntl(ad_data_fileno(ofork->of_ad), F_UNSHARE, &shmd);
+        if (AD_RSRC_OPEN(ofork->of_ad))
+            fcntl(ad_reso_fileno(ofork->of_ad), F_UNSHARE, &shmd);
     }
+#endif
 
     ret = 0;
     if ( ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD) < 0 ) {
         ret = -1;
     }
 
-    of_dealloc( ofork );
+    of_dealloc(ofork);
+
     return ret;
 }
 
@@ -429,7 +446,7 @@ struct adouble *of_ad(const struct vol *vol, struct path *path, struct adouble *
     struct ofork        *of;
     struct adouble      *adp;
 
-    if ((of = of_findname(path))) {
+    if ((of = of_findname(vol, path))) {
         adp = of->of_ad;
     } else {
         ad_init(ad, vol);
@@ -441,7 +458,7 @@ struct adouble *of_ad(const struct vol *vol, struct path *path, struct adouble *
 /* ----------------------
    close all forks for a volume
 */
-void of_closevol(const struct vol *vol)
+void of_closevol(const AFPObj *obj, const struct vol *vol)
 {
     int refnum;
 
@@ -450,7 +467,7 @@ void of_closevol(const struct vol *vol)
 
     for ( refnum = 0; refnum < nforks; refnum++ ) {
         if (oforks[ refnum ] != NULL && oforks[refnum]->of_vol == vol) {
-            if (of_closefork( oforks[ refnum ]) < 0 ) {
+            if (of_closefork(obj, oforks[ refnum ]) < 0 ) {
                 LOG(log_error, logtype_afpd, "of_closevol: %s", strerror(errno) );
             }
         }
@@ -461,7 +478,7 @@ void of_closevol(const struct vol *vol)
 /* ----------------------
    close all forks for a volume
 */
-void of_close_all_forks(void)
+void of_close_all_forks(const AFPObj *obj)
 {
     int refnum;
 
@@ -470,7 +487,7 @@ void of_close_all_forks(void)
 
     for ( refnum = 0; refnum < nforks; refnum++ ) {
         if (oforks[ refnum ] != NULL) {
-            if (of_closefork( oforks[ refnum ]) < 0 ) {
+            if (of_closefork(obj, oforks[ refnum ]) < 0 ) {
                 LOG(log_error, logtype_afpd, "of_close_all_forks: %s", strerror(errno) );
             }
         }