]> arthur.barton.de Git - netatalk.git/blob - contrib/patches/patch.afp_vfs
call readt with ONE_DELAY = 5 s
[netatalk.git] / contrib / patches / patch.afp_vfs
1 First try for a netatalk vfs layer
2
3 current schemes
4 adouble=v1,v2 classic adouble format
5 adouble=osx  ._<filename> OSX resource fork.
6 adouble=ads  NT like alternate data stream. 
7
8 Note for ads:
9 * cf. patch.vfs for samba ADS vfs layer and patch.samba.xx for samba tree patch.
10
11 * It's using Afp_AfpInfo name (MS SFM name) but it's not yet compatible with SFM.
12   from cdrecord source code Afp_AfpInfo is the raw HFS data, we are storing an appledouble file.
13
14 * Server side copy and Macintosh copy only deal with resource fork, other NT ADS are lost.
15   unfixable for Macintosh copy but doable for server side.
16
17 * It's ok for rename, delete, chown and chmod.
18
19 * Copy from a NT box should work.
20
21 * Last but not least : only on a new volume!
22
23 TODO
24 indirection for metadata, aka stored in EA, a different file, whatever.
25
26 diff -Nur -X .cvsignore -x CVS ../src.dev2/etc/afpd/Makefile.am ./etc/afpd/Makefile.am
27 --- ../src.dev2/etc/afpd/Makefile.am    Mon Feb  9 22:45:51 2004
28 +++ ./etc/afpd/Makefile.am      Fri Jun 18 19:15:47 2004
29 @@ -8,14 +8,14 @@
30          file.c enumerate.c desktop.c filedir.c fork.c appl.c gettok.c \
31          mangle.c status.c afp_options.c afp_asp.c afp_dsi.c messages.c  \
32          afp_config.c nfsquota.c quota.c uam.c afs.c uid.c afp_util.c \
33 -         catsearch.c afprun.c
34 +         catsearch.c afprun.c vfs_adouble.c
35  
36  afpd_LDADD =  $(top_builddir)/libatalk/cnid/libcnid.la $(top_builddir)/libatalk/libatalk.la
37  afpd_LDFLAGS = -export-dynamic
38  
39  noinst_HEADERS = auth.h afp_config.h desktop.h directory.h file.h \
40          filedir.h fork.h globals.h icon.h mangle.h misc.h status.h switch.h \
41 -        uam_auth.h uid.h unix.h volume.h
42 +        uam_auth.h uid.h unix.h volume.h afp_vfs.h
43  
44  LIBS = @LIBS@ @PAM_LIBS@ @QUOTA_LIBS@ @SLP_LIBS@
45  
46 diff -Nur -X .cvsignore -x CVS ../src.dev2/etc/afpd/afp_vfs.h ./etc/afpd/afp_vfs.h
47 --- ../src.dev2/etc/afpd/afp_vfs.h      Thu Jan  1 00:00:00 1970
48 +++ ./etc/afpd/afp_vfs.h        Wed Jun 23 03:56:15 2004
49 @@ -0,0 +1,49 @@
50 +/*
51 +   Copyright (c) 2004 Didier Gautheron
52
53 +   This program is free software; you can redistribute it and/or modify
54 +   it under the terms of the GNU General Public License as published by
55 +   the Free Software Foundation; either version 2 of the License, or
56 +   (at your option) any later version.
57
58 +   This program is distributed in the hope that it will be useful,
59 +   but WITHOUT ANY WARRANTY; without even the implied warranty of
60 +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
61 +   GNU General Public License for more details.
62
63 +   You should have received a copy of the GNU General Public License
64 +   along with this program; if not, write to the Free Software
65 +   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
66 +
67 +   vfs layer for afp
68 +*/
69 +
70 +#ifndef _AFP_VFS_H
71 +#define _AFP_VFS_H
72 +
73 +#include <atalk/adouble.h>
74 +struct vol;
75 +
76 +struct vfs_ops {
77 +    /* low level adouble fn */
78 +    char *(*ad_path)(const char *, int);
79 +
80 +    /* */
81 +    int (*validupath)(const struct vol *, const char *);
82 +    int (*rf_chown)(const struct vol *, const char *path, uid_t owner, gid_t group);
83 +    int (*rf_renamedir)(const struct vol *, const char *oldpath, const char *newpath);
84 +    int (*rf_deletecurdir)(const struct vol *);
85 +    int (*rf_setfilmode)(const struct vol *, const char * name, mode_t mode, struct stat *st);
86 +    int (*rf_setdirmode)(const struct vol *, const char * name, mode_t mode, struct stat *st);
87 +    int (*rf_setdirunixmode)(const struct vol *, const char * name, mode_t mode, struct stat *st);
88 +
89 +    int (*rf_setdirowner)(const struct vol *, const char *path, uid_t owner, gid_t group);
90 +
91 +    int (*rf_deletefile)(const struct vol *, const char * );
92 +    int (*rf_renamefile)(const struct vol *, const char *oldpath, const char *newpath);
93 +
94 +};
95 +
96 +void initvol_vfs(struct vol *vol);
97 +
98 +#endif
99 diff -Nur -X .cvsignore -x CVS ../src.dev2/etc/afpd/directory.c ./etc/afpd/directory.c
100 --- ../src.dev2/etc/afpd/directory.c    Mon Jul 12 08:46:03 2004
101 +++ ./etc/afpd/directory.c      Sat Jun 19 14:07:14 2004
102 @@ -610,7 +610,7 @@
103     system rmdir with afp error code.
104     ENOENT is not an error.
105   */
106 -static int netatalk_rmdir(const char *name)
107 +int netatalk_rmdir(const char *name)
108  {
109      if (rmdir(name) < 0) {
110          switch ( errno ) {
111 @@ -2075,15 +2075,11 @@
112          }
113      }
114  
115 -    if (vol->v_adouble == AD_VERSION2_OSX) {
116 -        /* We simply move the corresponding ad file as well */
117 -        char   tempbuf[258]="._";
118 -        rename(vol->ad_path(src,0),strcat(tempbuf,dst));
119 -    }
120 +    vol->vfs->rf_renamedir(vol, src, dst);
121  
122      len = strlen( newname );
123      /* rename() succeeded so we need to update our tree even if we can't open
124 -     * .Parent
125 +     * metadata
126      */
127      
128      ad_init(&ad, vol->v_adouble);
129 @@ -2132,12 +2128,9 @@
130      return( AFP_OK );
131  }
132  
133 -#define DOT_APPLEDOUBLE_LEN 13
134  /* delete an empty directory */
135 -int deletecurdir( vol, path, pathlen )
136 +int deletecurdir( vol)
137  const struct vol       *vol;
138 -char *path;
139 -int pathlen;
140  {
141      struct dirent *de;
142      struct stat st;
143 @@ -2162,42 +2155,9 @@
144              return  AFPERR_OLOCK;
145          }
146      }
147 -
148 -    if (vol->v_adouble == AD_VERSION2_OSX) {
149 -       
150 -        if ((err = netatalk_unlink(vol->ad_path(".",0) )) ) {
151 -            return err;
152 -        }
153 -    }
154 -    else {
155 -        /* delete stray .AppleDouble files. this happens to get .Parent files
156 -           as well. */
157 -        if ((dp = opendir(".AppleDouble"))) {
158 -            strcpy(path, ".AppleDouble/");
159 -            while ((de = readdir(dp))) {
160 -                /* skip this and previous directory */
161 -                if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
162 -                    continue;
163 -
164 -                /* bail if the file exists in the current directory.
165 -                 * note: this will not fail with dangling symlinks */
166 -                if (stat(de->d_name, &st) == 0) {
167 -                    closedir(dp);
168 -                    return AFPERR_DIRNEMPT;
169 -                }
170 -
171 -                strcpy(path + DOT_APPLEDOUBLE_LEN, de->d_name);
172 -                if ((err = netatalk_unlink(path))) {
173 -                    closedir(dp);
174 -                    return err;
175 -                }
176 -            }
177 -            closedir(dp);
178 -        }
179 -
180 -        if ( (err = netatalk_rmdir( ".AppleDouble" ))  ) {
181 -            return err;
182 -        }
183 +    err = vol->vfs->rf_deletecurdir(vol);
184 +    if (err) {
185 +        return err;
186      }
187  
188      /* now get rid of dangling symlinks */
189 diff -Nur -X .cvsignore -x CVS ../src.dev2/etc/afpd/directory.h ./etc/afpd/directory.h
190 --- ../src.dev2/etc/afpd/directory.h    Mon May 10 18:40:32 2004
191 +++ ./etc/afpd/directory.h      Sat Jun 19 03:23:18 2004
192 @@ -196,7 +196,7 @@
193  
194  extern struct dir       *dirinsert __P((struct vol *, struct dir *));
195  extern int              movecwd __P((const struct vol *, struct dir *));
196 -extern int              deletecurdir __P((const struct vol *, char *, int));
197 +extern int              deletecurdir __P((const struct vol *));
198  extern struct path      *cname __P((const struct vol *, struct dir *,
199                               char **));
200  extern mode_t           mtoumode __P((struct maccess *));
201 @@ -215,6 +215,7 @@
202  extern int  check_access __P((char *name , int mode));
203  extern int file_access   __P((struct path *path, int mode));
204  
205 +extern int netatalk_rmdir __P((const char *name));
206  extern int netatalk_unlink __P((const char *name));
207  
208  /* from enumerate.c */
209 diff -Nur -X .cvsignore -x CVS ../src.dev2/etc/afpd/enumerate.c ./etc/afpd/enumerate.c
210 --- ../src.dev2/etc/afpd/enumerate.c    Mon Jul 12 08:46:03 2004
211 +++ ./etc/afpd/enumerate.c      Thu Jun 24 04:26:35 2004
212 @@ -166,7 +166,7 @@
213      if (!strcmp(name, "..") || !strcmp(name, "."))
214          return NULL;
215  
216 -    if (!vol->validupath(vol, name))
217 +    if (!vol->vfs->validupath(vol, name))
218          return NULL;
219  
220      /* check for vetoed filenames */
221 diff -Nur -X .cvsignore -x CVS ../src.dev2/etc/afpd/file.c ./etc/afpd/file.c
222 --- ../src.dev2/etc/afpd/file.c Tue Jun 15 22:53:54 2004
223 +++ ./etc/afpd/file.c   Mon Jun 21 00:21:24 2004
224 @@ -901,7 +901,7 @@
225  
226      /* second try with adouble open 
227      */
228 -    if (ad_open( upath, vol_noadouble(vol) | ADFLAGS_HF,
229 +    if ( ad_open( upath, vol_noadouble(vol) | ADFLAGS_HF,
230                   O_RDWR|O_CREAT, 0666, adp) < 0) {
231          /* for some things, we don't need an adouble header */
232          if (f_bitmap & ~(1<<FILPBIT_MDATE)) {
233 @@ -1020,7 +1020,6 @@
234  char   *src, *dst, *newname;
235  struct adouble    *adp;
236  {
237 -    char       adsrc[ MAXPATHLEN + 1];
238      int                rc;
239  
240  #ifdef DEBUG
241 @@ -1055,38 +1054,10 @@
242          }
243      }
244  
245 -    strcpy( adsrc, vol->ad_path( src, 0 ));
246 -
247 -    if (unix_rename( adsrc, vol->ad_path( dst, 0 )) < 0 ) {
248 -        struct stat st;
249 +    if (vol->vfs->rf_renamefile(vol, src, dst) < 0 ) {
250          int err;
251          
252          err = errno;        
253 -       if (errno == ENOENT) {
254 -           struct adouble    ad;
255 -
256 -            if (stat(adsrc, &st)) /* source has no ressource fork, */
257 -                return AFP_OK;
258 -            
259 -            /* We are here  because :
260 -             * -there's no dest folder. 
261 -             * -there's no .AppleDouble in the dest folder.
262 -             * if we use the struct adouble passed in parameter it will not
263 -             * create .AppleDouble if the file is already opened, so we
264 -             * use a diff one, it's not a pb,ie it's not the same file, yet.
265 -             */
266 -            ad_init(&ad, vol->v_adouble); 
267 -            if (!ad_open(dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666, &ad)) {
268 -               ad_close(&ad, ADFLAGS_HF);
269 -               if (!unix_rename( adsrc, vol->ad_path( dst, 0 )) ) 
270 -                   err = 0;
271 -                else 
272 -                   err = errno;
273 -            }
274 -            else { /* it's something else, bail out */
275 -               err = errno;
276 -           }
277 -       }
278         /* try to undo the data fork rename,
279          * we know we are on the same device 
280         */
281 @@ -1436,6 +1407,7 @@
282      if (ret_err) {
283          deletefile(d_vol, dst, 0);
284      }
285 +    /* ADS here */
286  
287      /* set dest modification date to src date */
288      if (!stat(src, &st)) {
289 @@ -1562,14 +1534,12 @@
290      if (adp && ad_tmplock( &ad, ADEID_DFORK, ADLOCK_WR, 0, 0, 0 ) < 0) {
291          err = AFPERR_BUSY;
292      }
293 -    else if (!(err = netatalk_unlink( vol->ad_path( file, ADFLAGS_HF)) ) &&
294 -             !(err = netatalk_unlink( file )) ) {
295 +    else if (!(err = vol->vfs->rf_deletefile(vol, file)) && !(err = netatalk_unlink( file )) ) {
296          cnid_t id;
297          if (checkAttrib && (id = cnid_get(vol->v_cdb, curdir->d_did, file, strlen(file)))) 
298          {
299              cnid_delete(vol->v_cdb, id);
300          }
301 -
302      }
303      if (adp)
304          ad_close( &ad, adflags );  /* ad_close removes locks if any */
305 diff -Nur -X .cvsignore -x CVS ../src.dev2/etc/afpd/filedir.c ./etc/afpd/filedir.c
306 --- ../src.dev2/etc/afpd/filedir.c      Mon May 10 18:40:32 2004
307 +++ ./etc/afpd/filedir.c        Sat Jun 19 15:09:08 2004
308 @@ -73,7 +73,7 @@
309          return AFPERR_NOOBJ ;
310      }
311  
312 -    adpath = vol->ad_path( upath, ADFLAGS_HF );
313 +    adpath = vol->vfs->ad_path( upath, ADFLAGS_HF );
314      /* FIXME dirsearch doesn't move cwd to did ! */
315      if (( dir = dirlookup( vol, did )) == NULL ) {
316          LOG(log_error, logtype_afpd, "matchfile2dirperms: Unable to get directory info.");
317 @@ -313,7 +313,7 @@
318      if ((vol->v_flags & AFPVOL_NOHEX) && strchr(name, '/'))
319          return AFPERR_PARAM;
320  
321 -    if (!vol->validupath(vol, name))
322 +    if (!vol->vfs->validupath(vol, name))
323          return AFPERR_EXIST;
324  
325      /* check for vetoed filenames */
326 @@ -582,7 +582,7 @@
327             rc = AFPERR_ACCESS;
328         }
329         else {
330 -            rc = deletecurdir( vol, obj->oldtmp, AFPOBJ_TMPSIZ);
331 +            rc = deletecurdir( vol);
332          }
333      } else if (of_findname(s_path)) {
334          rc = AFPERR_BUSY;
335 @@ -764,7 +764,7 @@
336                  int  admode = ad_mode("", 0777);
337  
338                  setfilmode(upath, admode, NULL);
339 -                setfilmode(vol->ad_path( upath, ADFLAGS_HF ), ad_hf_mode(admode), NULL);
340 +                vol->vfs->rf_setfilmode(vol, upath, admode, NULL);
341              }
342          setvoltime(obj, vol );
343      }
344 diff -Nur -X .cvsignore -x CVS ../src.dev2/etc/afpd/unix.c ./etc/afpd/unix.c
345 --- ../src.dev2/etc/afpd/unix.c Tue Jun 15 22:53:55 2004
346 +++ ./etc/afpd/unix.c   Wed Jun 23 04:04:01 2004
347 @@ -260,8 +260,8 @@
348     rwx-wx-wx or rwx-wx-- 
349     rwx----wx (is not asked by a Mac with OS >= 8.0 ?)
350  */
351 -static int stickydirmode(name, mode, dropbox)
352 -char * name;
353 +int stickydirmode(name, mode, dropbox)
354 +const char * name;
355  const mode_t mode;
356  const int dropbox;
357  {
358 @@ -405,12 +405,12 @@
359      if (setfilmode( path->u_name, mode, &path->st) < 0)
360          return -1;
361      /* we need to set write perm if read set for resource fork */
362 -    return setfilmode(vol->ad_path( path->u_name, ADFLAGS_HF ), ad_hf_mode(mode), &path->st);
363 +    return vol->vfs->rf_setfilmode(vol, path->u_name, mode, &path->st);
364  }
365  
366  /* --------------------- */
367  int setfilmode(name, mode, st)
368 -char * name;
369 +const char * name;
370  mode_t mode;
371  struct stat *st;
372  {
373 @@ -436,29 +436,18 @@
374  const char       *name;
375  const mode_t     mode;
376  {
377 -char *adouble = vol->ad_path( name, ADFLAGS_DIR );
378  
379      int dropbox = (vol->v_flags & AFPVOL_DROPBOX);
380  
381      if (dir_rx_set(mode)) {
382 -       /* extending right? dir first then .AppleDouble */
383 +       /* extending right? dir first then .AppleDouble in rf_setdirmode */
384         if ( stickydirmode(name, DIRBITS | mode, dropbox) < 0 )
385                 return -1;
386 -       if (vol->v_adouble != AD_VERSION2_OSX) {
387 -            if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol)) {
388 -                return  -1 ;
389 -            }
390 -        }
391      }
392 -    if (setfilmode(adouble, ad_hf_mode(mode), NULL) < 0 && !vol_noadouble(vol)) {
393 +    if (vol->vfs->rf_setdirunixmode(vol, name, mode, NULL) < 0 && !vol_noadouble(vol)) {
394          return  -1 ;
395      }
396      if (!dir_rx_set(mode)) {
397 -       if (vol->v_adouble != AD_VERSION2_OSX) {
398 -            if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol)) {
399 -                return  -1 ;
400 -            }
401 -        }
402         if ( stickydirmode(name, DIRBITS | mode, dropbox) < 0 )
403              return -1;
404      }
405 @@ -471,26 +460,17 @@
406  const char       *name;
407  const mode_t mode;
408  {
409 -    char               buf[ MAXPATHLEN + 1];
410      struct stat                st;
411 -    char               *m;
412      struct dirent      *dirp;
413      DIR                        *dir;
414      int                 osx = vol->v_adouble == AD_VERSION2_OSX;
415      int                 hf_mode = ad_hf_mode(mode);
416      int                 dropbox = (vol->v_flags & AFPVOL_DROPBOX);
417 -    char                *adouble = vol->ad_path( name, ADFLAGS_DIR );
418 -    char                *adouble_p = ad_dir(adouble);
419      
420      if (dir_rx_set(mode)) {
421 -       /* extending right? dir first then .AppleDouble */
422 +       /* extending right? dir first */
423         if ( stickydirmode(name, DIRBITS | mode, dropbox) < 0 )
424                 return -1;
425 -       if (!osx) {
426 -            if (stickydirmode(adouble_p, DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol)) {
427 -                return  -1 ;
428 -            }
429 -        }
430      }
431      
432      if (( dir = opendir( name )) == NULL ) {
433 @@ -516,61 +496,13 @@
434                  return -1;
435             }
436          }
437 -#if 0
438 -        /* Don't change subdir perm */
439 -        else if (S_ISDIR(st.st_mode)) {
440 -                if (stickydirmode(dirp->d_name, DIRBITS | mode, dropbox) < 0)
441 -                    return (-1);
442 -            } else if (stickydirmode(dirp->d_name, mode, dropbox) < 0)
443 -                return (-1);
444 -        }
445 -#endif
446      }
447      closedir( dir );
448      
449 -    if (osx) {
450 -        goto setdirmode_noadouble;
451 -    }
452 -    
453 -    /* change perm of .AppleDouble's files
454 -    */
455 -    if (( dir = opendir( adouble_p )) == NULL ) {
456 -        if (vol_noadouble(vol))
457 -            goto setdirmode_noadouble;
458 -        LOG(log_error, logtype_afpd, "setdirmode: opendir %s: %s", fullpathname(".AppleDouble"),strerror(errno) );
459 -        return( -1 );
460 -    }
461 -    strcpy( buf, adouble_p);
462 -    strcat( buf, "/" );
463 -    m = strchr( buf, '\0' );
464 -    for ( dirp = readdir( dir ); dirp != NULL; dirp = readdir( dir )) {
465 -        if ( strcmp( dirp->d_name, "." ) == 0 ||
466 -                strcmp( dirp->d_name, ".." ) == 0 ) {
467 -            continue;
468 -        }
469 -        *m = '\0';
470 -        strcat( buf, dirp->d_name );
471 -
472 -        if ( stat( buf, &st ) < 0 ) {
473 -            LOG(log_error, logtype_afpd, "setdirmode: stat %s: %s", buf, strerror(errno) );
474 -            continue;
475 -        }
476 -        if (!S_ISDIR(st.st_mode)) {
477 -           if (setfilmode(buf, hf_mode , &st) < 0) {
478 -               /* FIXME what do we do then? */
479 -           }
480 -        }
481 -    } /* end for */
482 -    closedir( dir );
483 -
484 -    if (!dir_rx_set(mode)) {
485 -        /* XXX: need to preserve special modes */
486 -        if (stickydirmode(adouble_p, DIRBITS | mode, dropbox) < 0 ) {
487 -                return  -1 ;
488 -        }
489 +    if (vol->vfs->rf_setdirmode(vol, name, mode, NULL) < 0 && !vol_noadouble(vol)) {
490 +        return  -1 ;
491      }
492  
493 -setdirmode_noadouble:
494      if (!dir_rx_set(mode)) {
495         if ( stickydirmode(name, DIRBITS | mode, dropbox) < 0 )
496                 return -1;
497 @@ -578,6 +510,7 @@
498      return( 0 );
499  }
500  
501 +/* ----------------------------- */
502  int setdeskowner( uid, gid )
503  const uid_t    uid;
504  const gid_t    gid;
505 @@ -648,8 +581,6 @@
506  const gid_t    gid;
507  struct path* path;
508  {
509 -    struct stat st;
510 -    char  *ad_p;
511  
512      if (!path->st_valid) {
513          of_stat(path);
514 @@ -665,22 +596,15 @@
515         return -1;
516      }
517  
518 -    ad_p = vol->ad_path( path->u_name, ADFLAGS_HF );
519 -
520 -    if ( stat( ad_p, &st ) < 0 ) {
521 -       /* ignore */
522 -        return 0;
523 -    }
524 -    if ( chown( ad_p, uid, gid ) < 0 &&
525 -            errno != EPERM ) {
526 -        LOG(log_debug, logtype_afpd, "setfilowner: chown %d/%d %s: %s",
527 -            uid, gid, ad_p, strerror(errno) );
528 +    if (vol->vfs->rf_chown(vol, path->u_name, uid, gid ) < 0 && errno != EPERM) {
529 +        LOG(log_debug, logtype_afpd, "setfilowner: rf_chown %d/%d %s: %s",
530 +            uid, gid, path->u_name, strerror(errno) );
531          return -1;
532      }
533 +
534      return 0;
535  }
536  
537 -
538  /* --------------------------------- 
539   * uid/gid == 0 need to be handled as special cases. they really mean
540   * that user/group should inherit from other, but that doesn't fit
541 @@ -692,15 +616,10 @@
542  const uid_t    uid;
543  const gid_t    gid;
544  {
545 -    char               buf[ MAXPATHLEN + 1];
546      struct stat                st;
547 -    char               *m;
548      struct dirent      *dirp;
549      DIR                        *dir;
550      int                 osx = vol->v_adouble == AD_VERSION2_OSX;
551 -    int                 noadouble = vol_noadouble(vol);
552 -    char                *adouble; 
553 -    char                *adouble_p;
554  
555      if (( dir = opendir( name )) == NULL ) {
556          return( -1 );
557 @@ -723,56 +642,15 @@
558          }
559      }
560      closedir( dir );
561 -    
562 -    if (osx) {
563 -       goto setdirowner_noadouble;
564 -    }
565  
566 -    adouble = vol->ad_path( name, ADFLAGS_DIR );
567 -    adouble_p = ad_dir(adouble);
568 -    if (( dir = opendir( adouble_p )) == NULL ) {
569 -        if (noadouble)
570 -            goto setdirowner_noadouble;
571 -        return( -1 );
572 -    }
573 -    strcpy( buf, adouble_p );
574 -    strcat( buf, "/" );
575 -    m = strchr( buf, '\0' );
576 -    for ( dirp = readdir( dir ); dirp != NULL; dirp = readdir( dir )) {
577 -        if ( strcmp( dirp->d_name, "." ) == 0 ||
578 -                strcmp( dirp->d_name, ".." ) == 0 ) {
579 -            continue;
580 -        }
581 -        *m = '\0';
582 -        strcat( buf, dirp->d_name );
583 -        if ( chown( buf, uid, gid ) < 0 && errno != EPERM ) {
584 -            LOG(log_debug, logtype_afpd, "setdirowner: chown %d/%d %s: %s",
585 -                uid, gid, fullpathname(buf), strerror(errno) );
586 -            /* return ( -1 ); Sometimes this is okay */
587 -        }
588 -    }
589 -    closedir( dir );
590 -
591 -    /*
592 -     * We cheat: we know that chown doesn't do anything.
593 -     */
594 -    if ( stat( ".AppleDouble", &st ) < 0 ) {
595 -        LOG(log_error, logtype_afpd, "setdirowner: stat %s: %s", fullpathname(".AppleDouble"), strerror(errno) );
596 -        return( -1 );
597 -    }
598 -    if ( gid && gid != st.st_gid && chown( ".AppleDouble", uid, gid ) < 0 &&
599 -            errno != EPERM ) {
600 -        LOG(log_debug, logtype_afpd, "setdirowner: chown %d/%d %s: %s",
601 -            uid, gid,fullpathname(".AppleDouble"), strerror(errno) );
602 -        /* return ( -1 ); Sometimes this is okay */
603 +    if (vol->vfs->rf_setdirowner(vol, name, uid, gid) < 0) {
604 +        return -1;
605      }
606 -
607 -setdirowner_noadouble:
608 +    
609      if ( stat( ".", &st ) < 0 ) {
610          return( -1 );
611      }
612 -    if ( gid && gid != st.st_gid && chown( ".", uid, gid ) < 0 &&
613 -            errno != EPERM ) {
614 +    if ( gid && gid != st.st_gid && chown( ".", uid, gid ) < 0 && errno != EPERM ) {
615          LOG(log_debug, logtype_afpd, "setdirowner: chown %d/%d %s: %s",
616              uid, gid, fullpathname("."), strerror(errno) );
617      }
618 diff -Nur -X .cvsignore -x CVS ../src.dev2/etc/afpd/unix.h ./etc/afpd/unix.h
619 --- ../src.dev2/etc/afpd/unix.h Mon May 10 18:40:33 2004
620 +++ ./etc/afpd/unix.h   Wed Jun 23 03:43:28 2004
621 @@ -221,11 +221,12 @@
622  extern int setdirmode       __P((const struct vol *, const char *, const mode_t));
623  extern int setdeskowner     __P((const uid_t, const gid_t));
624  extern int setdirowner      __P((const struct vol *, const char *, const uid_t, const gid_t));
625 -extern int setfilmode       __P((char *, mode_t , struct stat *));
626 +extern int setfilmode       __P((const char *, mode_t , struct stat *));
627  extern int setfilunixmode   __P((const struct vol *, struct path*, const mode_t));
628  extern int setfilowner      __P((const struct vol *, const uid_t, const gid_t, struct path*));
629  extern int unix_rename      __P((const char *oldpath, const char *newpath));
630  extern int dir_rx_set       __P((mode_t mode));
631 +extern int stickydirmode    __P((const char * name, const mode_t mode, const int dropbox));
632  
633  extern void accessmode      __P((char *, struct maccess *, struct dir *, struct stat *));
634  extern char *fullpathname   __P((const char *));
635 diff -Nur -X .cvsignore -x CVS ../src.dev2/etc/afpd/vfs_adouble.c ./etc/afpd/vfs_adouble.c
636 --- ../src.dev2/etc/afpd/vfs_adouble.c  Thu Jan  1 00:00:00 1970
637 +++ ./etc/afpd/vfs_adouble.c    Wed Jun 30 19:31:49 2004
638 @@ -0,0 +1,749 @@
639 +/*
640 +    Copyright (c) 2004 Didier Gautheron
641
642 +   This program is free software; you can redistribute it and/or modify
643 +   it under the terms of the GNU General Public License as published by
644 +   the Free Software Foundation; either version 2 of the License, or
645 +   (at your option) any later version.
646
647 +   This program is distributed in the hope that it will be useful,
648 +   but WITHOUT ANY WARRANTY; without even the implied warranty of
649 +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
650 +   GNU General Public License for more details.
651
652 +   You should have received a copy of the GNU General Public License
653 +   along with this program; if not, write to the Free Software
654 +   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
655
656 +*/
657 +#ifdef HAVE_CONFIG_H
658 +#include "config.h"
659 +#endif /* HAVE_CONFIG_H */
660 +
661 +#ifdef STDC_HEADERS
662 +#include <string.h>
663 +#endif
664 +
665 +#include <stdio.h>
666 +    
667 +#include <atalk/adouble.h>
668 +#include <atalk/logger.h>
669 +#include <atalk/util.h>
670 +
671 +#include "directory.h"
672 +#include "volume.h"
673 +#include "unix.h"
674 +
675 +struct perm {
676 +    uid_t uid;
677 +    gid_t gid;
678 +};
679 +
680 +typedef int (*rf_loop)(struct dirent *, char *, void *, int );
681 +
682 +/* ----------------------------- */
683 +static int 
684 +for_each_adouble(const char *from, const char *name, rf_loop fn, void *data, int flag)
685 +{
686 +    char            buf[ MAXPATHLEN + 1];
687 +    char            *m;
688 +    DIR             *dp;
689 +    struct dirent   *de;
690 +    int             ret;
691 +    
692 +
693 +    if (NULL == ( dp = opendir( name)) ) {
694 +        if (!flag) {
695 +            LOG(log_error, logtype_afpd, "%s: opendir %s: %s", from, fullpathname(name),strerror(errno) );
696 +            return -1;
697 +        }
698 +        return 0;
699 +    }
700 +    strlcpy( buf, name, sizeof(buf));
701 +    strlcat( buf, "/", sizeof(buf) );
702 +    m = strchr( buf, '\0' );
703 +    ret = 0;
704 +    while ((de = readdir(dp))) {
705 +        if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
706 +                continue;
707 +        }
708 +        
709 +        strlcat(buf, de->d_name, sizeof(buf));
710 +        if (fn && (ret = fn(de, buf, data, flag))) {
711 +           closedir(dp);
712 +           return ret;
713 +        }
714 +        *m = 0;
715 +    }
716 +    closedir(dp);
717 +    return ret;
718 +}
719 +
720 +/* ------------------------------ */
721 +static int ads_chown_loop(struct dirent *de, char *name, void *data, int flag)
722 +{
723 +    struct perm   *owner  = data;
724 +    
725 +    if (chown( name , owner->uid, owner->gid ) < 0) {
726 +        return -1;
727 +    }
728 +    return 0;
729 +}
730 +
731 +static int RF_chown_ads(const struct vol *vol, const char *path, uid_t uid, gid_t gid)
732 +
733 +{
734 +    struct        stat st;
735 +    char          *ad_p;
736 +    struct perm   owner;
737 +    
738 +    owner.uid = uid;
739 +    owner.gid = gid;
740 +
741 +
742 +    ad_p = ad_dir(vol->vfs->ad_path(path, ADFLAGS_HF ));
743 +
744 +    if ( stat( ad_p, &st ) < 0 ) {
745 +       /* ignore */
746 +        return 0;
747 +    }
748 +    
749 +    if (chown( ad_p, uid, gid ) < 0) {
750 +       return -1;
751 +    }
752 +    return for_each_adouble("chown_ads", ad_p, ads_chown_loop, &owner, 1);
753 +}
754 +
755 +/* --------------------------------- */
756 +static int deletecurdir_ads1_loop(struct dirent *de, char *name, void *data, int flag)
757 +{
758 +    return netatalk_unlink(name);
759 +}
760 +
761 +static int ads_delete_rf(char *name) 
762 +{
763 +    int err;
764 +
765 +    if ((err = for_each_adouble("deletecurdir", name, deletecurdir_ads1_loop, NULL, 1))) 
766 +        return err;
767 +    return netatalk_rmdir(name);
768 +}
769 +
770 +static int deletecurdir_ads_loop(struct dirent *de, char *name, void *data, int flag)
771 +{
772 +    struct stat st;
773 +    
774 +    /* bail if the file exists in the current directory.
775 +     * note: this will not fail with dangling symlinks */
776 +    
777 +    if (stat(de->d_name, &st) == 0) {
778 +        return AFPERR_DIRNEMPT;
779 +    }
780 +    return ads_delete_rf(name);
781 +}
782 +
783 +static int RF_deletecurdir_ads(const struct vol *vol)
784 +{
785 +    int err;
786 +    
787 +    /* delete stray .AppleDouble files. this happens to get .Parent files as well. */
788 +    if ((err = for_each_adouble("deletecurdir", ".AppleDouble", deletecurdir_ads_loop, NULL, 1))) 
789 +        return err;
790 +    return netatalk_rmdir( ".AppleDouble" );
791 +}
792 +
793 +/* ------------------- */
794 +struct set_mode {
795 +    mode_t mode;
796 +    struct stat *st;
797 +};
798 +
799 +static int ads_setfilmode_loop(struct dirent *de, char *name, void *data, int flag)
800 +{
801 +    struct set_mode *param = data;
802 +
803 +    return setfilmode(name, param->mode, param->st);
804 +}
805 +
806 +static int ads_setfilmode(const char * name, mode_t mode, struct stat *st)
807 +{
808 +    mode_t dir_mode = mode;
809 +    mode_t file_mode = ad_hf_mode(mode);
810 +    struct set_mode param;
811 +
812 +    if ((dir_mode & (S_IRUSR | S_IWUSR )))
813 +        dir_mode |= S_IXUSR;
814 +    if ((dir_mode & (S_IRGRP | S_IWGRP )))
815 +        dir_mode |= S_IXGRP;
816 +    if ((dir_mode & (S_IROTH | S_IWOTH )))
817 +        dir_mode |= S_IXOTH;   
818 +    
819 +       /* change folder */
820 +       dir_mode |= DIRBITS;
821 +    if (dir_rx_set(dir_mode)) {
822 +        if (chmod( name,  dir_mode ) < 0)
823 +            return -1;
824 +    }
825 +    param.st = st;
826 +    param.mode = file_mode;
827 +    if (for_each_adouble("setfilmode_ads", name, ads_setfilmode_loop, &param, 0) < 0)
828 +        return -1;
829 +
830 +    if (!dir_rx_set(dir_mode)) {
831 +        if (chmod( name,  dir_mode ) < 0)
832 +            return -1;
833 +    }
834 +
835 +    return 0;
836 +}
837 +
838 +static int RF_setfilmode_ads(const struct vol *vol, const char * name, mode_t mode, struct stat *st)
839 +{
840 +    return ads_setfilmode(ad_dir(vol->vfs->ad_path( name, ADFLAGS_HF )), mode, st);
841 +}
842 +
843 +/* ------------------- */
844 +static int RF_setdirunixmode_ads(const struct vol *vol, const char * name, mode_t mode, struct stat *st)
845 +{
846 +    char *adouble = vol->vfs->ad_path( name, ADFLAGS_DIR );
847 +    char   ad_p[ MAXPATHLEN + 1];
848 +    int dropbox = (vol->v_flags & AFPVOL_DROPBOX);
849 +
850 +    strlcpy(ad_p,ad_dir(adouble), MAXPATHLEN + 1);
851 +
852 +    if (dir_rx_set(mode)) {
853 +
854 +        /* .AppleDouble */
855 +        if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol)) 
856 +            return -1;
857 +
858 +        /* .AppleDouble/.Parent */
859 +        if (stickydirmode(ad_p, DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol)) 
860 +            return -1;
861 +    }
862 +
863 +    if (ads_setfilmode(ad_dir(vol->vfs->ad_path( name, ADFLAGS_DIR)), mode, st) < 0)
864 +        return -1;
865 +
866 +    if (!dir_rx_set(mode)) {
867 +        if (stickydirmode(ad_p, DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol)) 
868 +            return  -1 ;
869 +        if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol)) 
870 +            return -1;
871 +    }
872 +    return 0;
873 +}
874 +
875 +/* ------------------- */
876 +struct dir_mode {
877 +    mode_t mode;
878 +    int    dropbox;
879 +};
880 +
881 +static int setdirmode_ads_loop(struct dirent *de, char *name, void *data, int flag)
882 +{
883 +
884 +    struct dir_mode *param = data;
885 +    int    ret = 0; /* 0 ignore error, -1 */
886 +
887 +    if (dir_rx_set(param->mode)) {
888 +        if (stickydirmode(name, DIRBITS | param->mode, param->dropbox) < 0) {
889 +            if (flag) {
890 +                return 0;
891 +            }
892 +            return ret;
893 +        }
894 +    }
895 +    if (ads_setfilmode(name, param->mode, NULL) < 0)
896 +        return ret;
897 +
898 +    if (!dir_rx_set(param->mode)) {
899 +        if (stickydirmode(name, DIRBITS | param->mode, param->dropbox) < 0) {
900 +            if (flag) {
901 +                return 0;
902 +            }
903 +            return ret;
904 +        }
905 +    }
906 +    return 0;
907 +}
908 +
909 +static int RF_setdirmode_ads(const struct vol *vol, const char * name, mode_t mode, struct stat *st)
910 +{
911 +    char *adouble = vol->vfs->ad_path( name, ADFLAGS_DIR );
912 +    char   ad_p[ MAXPATHLEN + 1];
913 +    struct dir_mode param;
914 +
915 +    param.mode = mode;
916 +    param.dropbox = (vol->v_flags & AFPVOL_DROPBOX);
917 +
918 +    strlcpy(ad_p,ad_dir(adouble), sizeof(ad_p));
919 +
920 +    if (dir_rx_set(mode)) {
921 +        /* .AppleDouble */
922 +        if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, param.dropbox) < 0 && !vol_noadouble(vol)) 
923 +            return -1;
924 +    }
925 +
926 +    if (for_each_adouble("setdirmode_ads", ad_dir(ad_p), setdirmode_ads_loop, &param, vol_noadouble(vol)))
927 +        return -1;
928 +
929 +    if (!dir_rx_set(mode)) {
930 +        if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, param.dropbox) < 0 && !vol_noadouble(vol)) 
931 +            return -1;
932 +    }
933 +    return 0;
934 +}
935 +
936 +/* ------------------- */
937 +static int setdirowner_ads1_loop(struct dirent *de, char *name, void *data, int flag)
938 +{
939 +    struct perm   *owner  = data;
940 +
941 +    if ( chown( name, owner->uid, owner->gid ) < 0 && errno != EPERM ) {
942 +         LOG(log_debug, logtype_afpd, "setdirowner: chown %d/%d %s: %s",
943 +                owner->uid, owner->gid, fullpathname(name), strerror(errno) );
944 +         /* return ( -1 ); Sometimes this is okay */
945 +    }
946 +    return 0;
947 +}
948 +
949 +static int setdirowner_ads_loop(struct dirent *de, char *name, void *data, int flag)
950 +{
951 +    struct perm   *owner  = data;
952 +
953 +    if (for_each_adouble("setdirowner", name, setdirowner_ads1_loop, data, flag) < 0)
954 +        return -1;
955 +
956 +    if ( chown( name, owner->uid, owner->gid ) < 0 && errno != EPERM ) {
957 +         LOG(log_debug, logtype_afpd, "setdirowner: chown %d/%d %s: %s",
958 +                owner->uid, owner->gid, fullpathname(name), strerror(errno) );
959 +         /* return ( -1 ); Sometimes this is okay */
960 +    }
961 +    return 0;
962 +}
963 +
964 +static int RF_setdirowner_ads(const struct vol *vol, const char *name, uid_t uid, gid_t gid)
965 +{
966 +    int           noadouble = vol_noadouble(vol);
967 +    char          adouble_p[ MAXPATHLEN + 1];
968 +    struct stat   st;
969 +    struct perm   owner;
970 +    
971 +    owner.uid = uid;
972 +    owner.gid = gid;
973 +
974 +    strlcpy(adouble_p, ad_dir(vol->vfs->ad_path( name, ADFLAGS_DIR )), sizeof(adouble_p));
975 +
976 +    if (for_each_adouble("setdirowner", ad_dir(adouble_p), setdirowner_ads_loop, &owner, noadouble)) 
977 +        return -1;
978 +
979 +    /*
980 +     * We cheat: we know that chown doesn't do anything.
981 +     */
982 +    if ( stat( ".AppleDouble", &st ) < 0) {
983 +        if (errno == ENOENT && noadouble)
984 +            return 0;
985 +        LOG(log_error, logtype_afpd, "setdirowner: stat %s: %s", fullpathname(".AppleDouble"), strerror(errno) );
986 +        return -1;
987 +    }
988 +    if ( gid && gid != st.st_gid && chown( ".AppleDouble", uid, gid ) < 0 && errno != EPERM ) {
989 +        LOG(log_debug, logtype_afpd, "setdirowner: chown %d/%d %s: %s",
990 +            uid, gid,fullpathname(".AppleDouble"), strerror(errno) );
991 +        /* return ( -1 ); Sometimes this is okay */
992 +    }
993 +    return 0;
994 +}
995 +
996 +/* ------------------- */
997 +static int RF_deletefile_ads(const struct vol *vol, const char *file )
998 +{
999 +    char *ad_p = ad_dir(vol->vfs->ad_path(file, ADFLAGS_HF ));
1000 +
1001 +    return ads_delete_rf(ad_p);
1002 +}
1003 +
1004 +/* --------------------------- */
1005 +int RF_renamefile_ads(const struct vol *vol, const char *src, const char *dst)
1006 +{
1007 +    char  adsrc[ MAXPATHLEN + 1];
1008 +    int   err = 0;
1009 +
1010 +    strcpy( adsrc, ad_dir(vol->vfs->ad_path( src, 0 )));
1011 +    if (unix_rename( adsrc, ad_dir(vol->vfs->ad_path( dst, 0 ))) < 0) {
1012 +        struct stat st;
1013 +
1014 +        err = errno;
1015 +        if (errno == ENOENT) {
1016 +               struct adouble    ad;
1017 +
1018 +            if (stat(adsrc, &st)) /* source has no ressource fork, */
1019 +                return AFP_OK;
1020 +            
1021 +            /* We are here  because :
1022 +             * -there's no dest folder. 
1023 +             * -there's no .AppleDouble in the dest folder.
1024 +             * if we use the struct adouble passed in parameter it will not
1025 +             * create .AppleDouble if the file is already opened, so we
1026 +             * use a diff one, it's not a pb,ie it's not the same file, yet.
1027 +             */
1028 +            ad_init(&ad, vol->v_adouble); 
1029 +            if (!ad_open(dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666, &ad)) {
1030 +               ad_close(&ad, ADFLAGS_HF);
1031 +
1032 +               /* We must delete it */
1033 +               RF_deletefile_ads(vol, dst );
1034 +               if (!unix_rename( adsrc, ad_dir(vol->vfs->ad_path( dst, 0 ))) ) 
1035 +                   err = 0;
1036 +                else 
1037 +                   err = errno;
1038 +            }
1039 +            else { /* it's something else, bail out */
1040 +                   err = errno;
1041 +               }
1042 +           }
1043 +       }
1044 +       if (err) {
1045 +               errno = err;
1046 +               return -1;
1047 +       }
1048 +       return 0;
1049 +}
1050 +
1051 +/* ===================================================
1052 + classic adouble format 
1053 +*/
1054 +
1055 +static int validupath_adouble(const struct vol *vol, const char *name) 
1056 +{
1057 +    return (vol->v_flags & AFPVOL_USEDOTS) ? strncasecmp(name,".Apple", 6) && strcasecmp(name, ".Parent")
1058 +                                           : name[0] != '.';
1059 +}
1060 +
1061 +/* ----------------- */
1062 +static int RF_chown_adouble(const struct vol *vol, const char *path, uid_t uid, gid_t gid)
1063 +
1064 +{
1065 +    struct stat st;
1066 +    char        *ad_p;
1067 +
1068 +    ad_p = vol->vfs->ad_path(path, ADFLAGS_HF );
1069 +
1070 +    if ( stat( ad_p, &st ) < 0 )
1071 +        return 0; /* ignore */
1072 +
1073 +    return chown( ad_p, uid, gid );
1074 +}
1075 +
1076 +/* ----------------- */
1077 +int RF_renamedir_adouble(const struct vol *vol, const char *oldpath, const char *newpath)
1078 +{
1079 +    return 0;
1080 +}
1081 +
1082 +/* ----------------- */
1083 +static int deletecurdir_adouble_loop(struct dirent *de, char *name, void *data, int flag)
1084 +{
1085 +    struct stat st;
1086 +    int         err;
1087 +    
1088 +    /* bail if the file exists in the current directory.
1089 +     * note: this will not fail with dangling symlinks */
1090 +    
1091 +    if (stat(de->d_name, &st) == 0)
1092 +        return AFPERR_DIRNEMPT;
1093 +
1094 +    if ((err = netatalk_unlink(name)))
1095 +        return err;
1096 +
1097 +    return 0;
1098 +}
1099 +
1100 +static int RF_deletecurdir_adouble(const struct vol *vol)
1101 +{
1102 +    int err;
1103 +
1104 +    /* delete stray .AppleDouble files. this happens to get .Parent files
1105 +       as well. */
1106 +    if ((err = for_each_adouble("deletecurdir", ".AppleDouble", deletecurdir_adouble_loop, NULL, 1))) 
1107 +        return err;
1108 +    return netatalk_rmdir( ".AppleDouble" );
1109 +}
1110 +
1111 +/* ----------------- */
1112 +static int adouble_setfilmode(const char * name, mode_t mode, struct stat *st)
1113 +{
1114 +    return setfilmode(name, ad_hf_mode(mode), st);
1115 +}
1116 +
1117 +static int RF_setfilmode_adouble(const struct vol *vol, const char * name, mode_t mode, struct stat *st)
1118 +{
1119 +    return adouble_setfilmode(vol->vfs->ad_path( name, ADFLAGS_HF ), mode, st);
1120 +}
1121 +
1122 +/* ----------------- */
1123 +static int RF_setdirunixmode_adouble(const struct vol *vol, const char * name, mode_t mode, struct stat *st)
1124 +{
1125 +    char *adouble = vol->vfs->ad_path( name, ADFLAGS_DIR );
1126 +    int  dropbox = (vol->v_flags & AFPVOL_DROPBOX);
1127 +
1128 +    if (dir_rx_set(mode)) {
1129 +        if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol)) 
1130 +            return -1;
1131 +    }
1132 +
1133 +    if (adouble_setfilmode(vol->vfs->ad_path( name, ADFLAGS_DIR ), mode, st) < 0) 
1134 +        return -1;
1135 +
1136 +    if (!dir_rx_set(mode)) {
1137 +        if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol)) 
1138 +            return  -1 ;
1139 +    }
1140 +    return 0;
1141 +}
1142 +
1143 +/* ----------------- */
1144 +static int setdirmode_adouble_loop(struct dirent *de, char *name, void *data, int flag)
1145 +{
1146 +    int         hf_mode = *(int *)data;
1147 +    struct stat st;
1148 +
1149 +    if ( stat( name, &st ) < 0 ) {
1150 +        if (flag)
1151 +            return 0;
1152 +        LOG(log_error, logtype_afpd, "setdirmode: stat %s: %s", name, strerror(errno) );
1153 +    }
1154 +    else if (!S_ISDIR(st.st_mode)) {
1155 +        if (setfilmode(name, hf_mode , &st) < 0) {
1156 +               /* FIXME what do we do then? */
1157 +        }
1158 +    }
1159 +    return 0;
1160 +}
1161 +
1162 +static int RF_setdirmode_adouble(const struct vol *vol, const char * name, mode_t mode, struct stat *st1)
1163 +{
1164 +    int   dropbox = (vol->v_flags & AFPVOL_DROPBOX);
1165 +    int   hf_mode = ad_hf_mode(mode);
1166 +    char  *adouble = vol->vfs->ad_path( name, ADFLAGS_DIR );
1167 +    char  *adouble_p = ad_dir(adouble);
1168 +
1169 +    if (dir_rx_set(mode)) {
1170 +        if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol)) 
1171 +            return -1;
1172 +    }
1173 +
1174 +    if (for_each_adouble("setdirmode", adouble_p, setdirmode_adouble_loop, &hf_mode, vol_noadouble(vol)))
1175 +        return -1;
1176 +
1177 +    if (!dir_rx_set(mode)) {
1178 +        if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol)) 
1179 +            return  -1 ;
1180 +    }
1181 +    return 0;
1182 +}
1183 +
1184 +/* ----------------- */
1185 +static int setdirowner_adouble_loop(struct dirent *de, char *name, void *data, int flag)
1186 +{
1187 +    struct perm   *owner  = data;
1188 +
1189 +    if ( chown( name, owner->uid, owner->gid ) < 0 && errno != EPERM ) {
1190 +         LOG(log_debug, logtype_afpd, "setdirowner: chown %d/%d %s: %s",
1191 +                owner->uid, owner->gid, fullpathname(name), strerror(errno) );
1192 +         /* return ( -1 ); Sometimes this is okay */
1193 +    }
1194 +    return 0;
1195 +}
1196 +
1197 +static int RF_setdirowner_adouble(const struct vol *vol, const char *name, uid_t uid, gid_t gid)
1198 +
1199 +{
1200 +    int           noadouble = vol_noadouble(vol);
1201 +    char          *adouble_p;
1202 +    struct stat   st;
1203 +    struct perm   owner;
1204 +    
1205 +    owner.uid = uid;
1206 +    owner.gid = gid;
1207 +
1208 +    adouble_p = ad_dir(vol->vfs->ad_path( name, ADFLAGS_DIR ));
1209 +
1210 +    if (for_each_adouble("setdirowner", adouble_p, setdirowner_adouble_loop, &owner, noadouble)) 
1211 +        return -1;
1212 +
1213 +    /*
1214 +     * We cheat: we know that chown doesn't do anything.
1215 +     */
1216 +    if ( stat( ".AppleDouble", &st ) < 0) {
1217 +        if (errno == ENOENT && noadouble)
1218 +            return 0;
1219 +        LOG(log_error, logtype_afpd, "setdirowner: stat %s: %s", fullpathname(".AppleDouble"), strerror(errno) );
1220 +        return -1;
1221 +    }
1222 +    if ( gid && gid != st.st_gid && chown( ".AppleDouble", uid, gid ) < 0 && errno != EPERM ) {
1223 +        LOG(log_debug, logtype_afpd, "setdirowner: chown %d/%d %s: %s",
1224 +            uid, gid,fullpathname(".AppleDouble"), strerror(errno) );
1225 +        /* return ( -1 ); Sometimes this is okay */
1226 +    }
1227 +    return 0;
1228 +}
1229 +
1230 +/* ----------------- */
1231 +static int RF_deletefile_adouble(const struct vol *vol, const char *file )
1232 +{
1233 +       return netatalk_unlink(vol->vfs->ad_path( file, ADFLAGS_HF));
1234 +}
1235 +
1236 +/* ----------------- */
1237 +int RF_renamefile_adouble(const struct vol *vol, const char *src, const char *dst)
1238 +{
1239 +    char  adsrc[ MAXPATHLEN + 1];
1240 +    int   err = 0;
1241 +
1242 +    strcpy( adsrc, vol->vfs->ad_path( src, 0 ));
1243 +    if (unix_rename( adsrc, vol->vfs->ad_path( dst, 0 )) < 0) {
1244 +        struct stat st;
1245 +
1246 +        err = errno;
1247 +        if (errno == ENOENT) {
1248 +               struct adouble    ad;
1249 +
1250 +            if (stat(adsrc, &st)) /* source has no ressource fork, */
1251 +                return AFP_OK;
1252 +            
1253 +            /* We are here  because :
1254 +             * -there's no dest folder. 
1255 +             * -there's no .AppleDouble in the dest folder.
1256 +             * if we use the struct adouble passed in parameter it will not
1257 +             * create .AppleDouble if the file is already opened, so we
1258 +             * use a diff one, it's not a pb,ie it's not the same file, yet.
1259 +             */
1260 +            ad_init(&ad, vol->v_adouble); 
1261 +            if (!ad_open(dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666, &ad)) {
1262 +               ad_close(&ad, ADFLAGS_HF);
1263 +               if (!unix_rename( adsrc, vol->vfs->ad_path( dst, 0 )) ) 
1264 +                   err = 0;
1265 +                else 
1266 +                   err = errno;
1267 +            }
1268 +            else { /* it's something else, bail out */
1269 +                   err = errno;
1270 +               }
1271 +           }
1272 +       }
1273 +       if (err) {
1274 +               errno = err;
1275 +               return -1;
1276 +       }
1277 +       return 0;
1278 +}
1279 +
1280 +struct vfs_ops netatalk_adouble = {
1281 +    /* ad_path:           */ ad_path,
1282 +    /* validupath:        */ validupath_adouble,
1283 +    /* rf_chown:          */ RF_chown_adouble,
1284 +    /* rf_renamedir:      */ RF_renamedir_adouble,
1285 +    /* rf_deletecurdir:   */ RF_deletecurdir_adouble,
1286 +    /* rf_setfilmode:     */ RF_setfilmode_adouble,
1287 +    /* rf_setdirmode:     */ RF_setdirmode_adouble,
1288 +    /* rf_setdirunixmode: */ RF_setdirunixmode_adouble,
1289 +    /* rf_setdirowner:    */ RF_setdirowner_adouble,
1290 +    /* rf_deletefile:     */ RF_deletefile_adouble,
1291 +    /* rf_renamefile:     */ RF_renamefile_adouble,
1292 +};
1293 +
1294 +/* =======================================
1295 + osx adouble format 
1296 + */
1297 +static int validupath_osx(const struct vol *vol, const char *name) 
1298 +{
1299 +    return strncasecmp(name,".Apple", 6) && strncasecmp(name,"._", 2);
1300 +}
1301 +
1302 +/* ---------------- */
1303 +int RF_renamedir_osx(const struct vol *vol, const char *oldpath, const char *newpath)
1304 +{
1305 +    /* We simply move the corresponding ad file as well */
1306 +    char   tempbuf[258]="._";
1307 +    return rename(vol->vfs->ad_path(oldpath,0),strcat(tempbuf,newpath));
1308 +}
1309 +
1310 +/* ---------------- */
1311 +int RF_deletecurdir_osx(const struct vol *vol)
1312 +{
1313 +    return netatalk_unlink( vol->vfs->ad_path(".",0) );
1314 +}
1315 +
1316 +/* ---------------- */
1317 +static int RF_setdirunixmode_osx(const struct vol *vol, const char * name, mode_t mode, struct stat *st)
1318 +{
1319 +    return adouble_setfilmode(vol->vfs->ad_path( name, ADFLAGS_DIR ), mode, st);
1320 +}
1321 +
1322 +/* ---------------- */
1323 +static int RF_setdirmode_osx(const struct vol *vol, const char * name, mode_t mode, struct stat *st)
1324 +{
1325 +    return 0;
1326 +}
1327 +
1328 +/* ---------------- */
1329 +static int RF_setdirowner_osx(const struct vol *vol, const char *path, uid_t uid, gid_t gid)
1330 +{
1331 +       return 0;
1332 +}
1333 +
1334 +/* ---------------- */
1335 +int RF_renamefile_osx(const struct vol *vol, const char *src, const char *dst)
1336 +{
1337 +    char  adsrc[ MAXPATHLEN + 1];
1338 +
1339 +    strcpy( adsrc, vol->vfs->ad_path( src, 0 ));
1340 +    return unix_rename( adsrc, vol->vfs->ad_path( dst, 0 ));
1341 +}
1342 +
1343 +struct vfs_ops netatalk_adouble_osx = {
1344 +    /* ad_path:          */ ad_path_osx,
1345 +    /* validupath:       */ validupath_osx,
1346 +    /* rf_chown:         */ RF_chown_adouble,
1347 +    /* rf_renamedir:     */ RF_renamedir_osx,
1348 +    /* rf_deletecurdir:  */ RF_deletecurdir_osx,
1349 +    /* rf_setfilmode:    */ RF_setfilmode_adouble,
1350 +    /* rf_setdirmode:    */ RF_setdirmode_osx,
1351 +    /* rf_setdirunixmode:*/ RF_setdirunixmode_osx,
1352 +    /* rf_setdirowner:   */ RF_setdirowner_osx,
1353 +    /* rf_deletefile:    */ RF_deletefile_adouble,
1354 +    /* rf_renamefile:    */ RF_renamefile_osx,
1355 +};
1356 +
1357 +/* =======================================
1358 +   samba ads format 
1359 + */
1360 +struct vfs_ops netatalk_adouble_ads = {
1361 +    /* ad_path:          */ ad_path_ads,
1362 +    /* validupath:       */ validupath_adouble,
1363 +    /* rf_chown:         */ RF_chown_ads,
1364 +    /* rf_renamedir:     */ RF_renamedir_adouble,
1365 +    /* rf_deletecurdir:  */ RF_deletecurdir_ads,
1366 +    /* rf_setfilmode:    */ RF_setfilmode_ads,
1367 +    /* rf_setdirmode:    */ RF_setdirmode_ads,
1368 +    /* rf_setdirunixmode:*/ RF_setdirunixmode_ads,
1369 +    /* rf_setdirowner:   */ RF_setdirowner_ads,
1370 +    /* rf_deletefile:    */ RF_deletefile_ads,
1371 +    /* rf_renamefile:    */ RF_renamefile_ads,
1372 +};
1373 +
1374 +/* ---------------- */
1375 +void initvol_vfs(struct vol *vol)
1376 +{
1377 +    if (vol->v_adouble == AD_VERSION2_OSX) {
1378 +        vol->vfs = &netatalk_adouble_osx;
1379 +    }
1380 +    else if (vol->v_adouble == AD_VERSION1_ADS) {
1381 +        vol->vfs = &netatalk_adouble_ads;
1382 +    }
1383 +    else {
1384 +        vol->vfs = &netatalk_adouble;
1385 +    }
1386 +}
1387 +
1388 diff -Nur -X .cvsignore -x CVS ../src.dev2/etc/afpd/volume.c ./etc/afpd/volume.c
1389 --- ../src.dev2/etc/afpd/volume.c       Mon Jul 12 08:46:03 2004
1390 +++ ./etc/afpd/volume.c Mon Jul 12 00:29:11 2004
1391 @@ -427,6 +427,8 @@
1392              options[VOLOPT_ADOUBLE].i_value = AD_VERSION2;
1393          else if (strcasecmp(val + 1, "osx") == 0)
1394              options[VOLOPT_ADOUBLE].i_value = AD_VERSION2_OSX;
1395 +        else if (strcasecmp(val + 1, "ads") == 0)
1396 +            options[VOLOPT_ADOUBLE].i_value = AD_VERSION1_ADS;
1397  #endif
1398      } else if (optionok(tmp, "options:", val)) {
1399          char *p;
1400 @@ -523,34 +525,6 @@
1401      }
1402  }
1403  
1404 -/* ----------------- 
1405 - * FIXME should be define elsewhere
1406 -*/
1407 -static int validupath_adouble(const struct vol *vol, const char *name) 
1408 -{
1409 -    return (vol->v_flags & AFPVOL_USEDOTS) ? strncasecmp(name,".Apple", 6) && strcasecmp(name, ".Parent")
1410 -                                           : name[0] != '.';
1411 -}                                           
1412 -
1413 -/* ----------------- */
1414 -static int validupath_osx(const struct vol *vol, const char *name) 
1415 -{
1416 -    return strncasecmp(name,".Apple", 6) && strncasecmp(name,"._", 2);
1417 -}             
1418 -
1419 -/* ---------------- */
1420 -static void initvoladouble(struct vol *vol)
1421 -{
1422 -    if (vol->v_adouble == AD_VERSION2_OSX) {
1423 -        vol->validupath  = validupath_osx;
1424 -        vol->ad_path     = ad_path_osx;
1425 -    }
1426 -    else {
1427 -        vol->validupath  = validupath_adouble;
1428 -        vol->ad_path     = ad_path;
1429 -    }
1430 -}
1431 -
1432  /* ------------------------------- */
1433  static int creatvol(AFPObj *obj, struct passwd *pwd, 
1434                      char *path, char *name, 
1435 @@ -653,7 +627,8 @@
1436             volume->v_adouble = options[VOLOPT_ADOUBLE].i_value;
1437         else 
1438             volume->v_adouble = AD_VERSION;
1439 -       initvoladouble(volume);
1440 +
1441 +       initvol_vfs(volume);
1442  #ifdef FORCE_UIDGID
1443          if (options[VOLOPT_FORCEUID].c_value) {
1444              volume->v_forceuid = strdup(options[VOLOPT_FORCEUID].c_value);
1445 @@ -2231,6 +2206,9 @@
1446              break;
1447          case AD_VERSION2_OSX:
1448              strlcat(buf, "ADOUBLE_VER:osx\n", sizeof(buf));
1449 +            break;
1450 +        case AD_VERSION1_ADS:
1451 +            strlcat(buf, "ADOUBLE_VER:ads\n", sizeof(buf));
1452              break;
1453      }
1454  
1455 diff -Nur -X .cvsignore -x CVS ../src.dev2/etc/afpd/volume.h ./etc/afpd/volume.h
1456 --- ../src.dev2/etc/afpd/volume.h       Mon Jul 12 08:46:03 2004
1457 +++ ./etc/afpd/volume.h Fri Jun 25 22:01:56 2004
1458 @@ -14,6 +14,7 @@
1459  
1460  #include "atalk/unicode.h"
1461  #include "globals.h"
1462 +#include "afp_vfs.h"
1463  
1464  #define AFPVOL_NAMELEN   27
1465  
1466 @@ -75,6 +76,7 @@
1467      int                 v_preexec_close;
1468      
1469      /* adouble indirection */
1470 +    struct vfs_ops      *vfs;
1471      int                 (*validupath)(const struct vol *, const char *);
1472      char                *(*ad_path)(const char *, int);
1473  };
1474 diff -Nur -X .cvsignore -x CVS ../src.dev2/include/atalk/adouble.h ./include/atalk/adouble.h
1475 --- ../src.dev2/include/atalk/adouble.h Tue Jun 15 01:08:28 2004
1476 +++ ./include/atalk/adouble.h   Sun Jun 20 22:33:26 2004
1477 @@ -82,6 +82,7 @@
1478  #define AD_VERSION1    0x00010000
1479  #define AD_VERSION2    0x00020000
1480  #define AD_VERSION2_OSX        0x00020001
1481 +#define AD_VERSION1_ADS        0x00010002
1482  #define AD_VERSION     AD_VERSION2
1483  
1484  /*
1485 @@ -252,6 +253,7 @@
1486                                          the header parameter size is too small.
1487                                       */
1488      char                *(*ad_path)(const char *, int);
1489 +    int                 (*ad_mkrf)(char *);
1490                             
1491  #ifdef USE_MMAPPED_HEADERS
1492      char                *ad_data;
1493 @@ -364,6 +366,7 @@
1494  extern char *ad_dir       __P((const char *));
1495  extern char *ad_path      __P((const char *, int));
1496  extern char *ad_path_osx  __P((const char *, int));
1497 +extern char *ad_path_ads  __P((const char *, int));
1498  
1499  extern int ad_mode        __P((const char *, int));
1500  extern int ad_mkdir       __P((const char *, int));
1501 diff -Nur -X .cvsignore -x CVS ../src.dev2/libatalk/adouble/ad_open.c ./libatalk/adouble/ad_open.c
1502 --- ../src.dev2/libatalk/adouble/ad_open.c      Mon Jul 12 02:01:45 2004
1503 +++ ./libatalk/adouble/ad_open.c        Mon Jul 12 02:12:25 2004
1504 @@ -697,6 +697,25 @@
1505      return( pathbuf );
1506  }
1507  
1508 +/* -------------------- */
1509 +static int ad_mkrf(char *path)
1510 +{
1511 +    char *slash;
1512 +    /*
1513 +     * Probably .AppleDouble doesn't exist, try to mkdir it.
1514 +     */
1515 +     if (NULL == ( slash = strrchr( path, '/' )) ) {
1516 +         return -1;
1517 +     }
1518 +     *slash = '\0';
1519 +     errno = 0;
1520 +     if ( ad_mkdir( path, 0777 ) < 0 ) {
1521 +          return -1;
1522 +     }
1523 +     *slash = '/';
1524 +     return 0;
1525 +}
1526 +
1527  /* ---------------------------------------
1528   * Put the resource fork where it needs to be:
1529   * ._name
1530 @@ -729,8 +748,97 @@
1531      strlcat( pathbuf, slash, MAXPATHLEN +1);
1532      return pathbuf;
1533  }
1534 +/* -------------------- */
1535 +static int ad_mkrf_osx(char *path)
1536 +{
1537 +    return 0;
1538 +}
1539  
1540 -/*
1541 +/* ---------------------------------------
1542 + * Put the .AppleDouble where it needs to be:
1543 + *
1544 + *         /   a/.AppleDouble/b/Afp_AfpInfo
1545 + *     a/b     
1546 + *         \   b/.AppleDouble/.Parent/Afp_AfpInfo
1547 + *
1548 + */
1549 +char *
1550 +ad_path_ads( path, adflags )
1551 +    const char *path;
1552 +    int                adflags;
1553 +{
1554 +    static char        pathbuf[ MAXPATHLEN + 1];
1555 +    char       c, *slash, buf[MAXPATHLEN + 1];
1556 +    size_t      l;
1557 +
1558 +    l = strlcpy(buf, path, MAXPATHLEN +1);
1559 +    if ( adflags & ADFLAGS_DIR ) {
1560 +       strcpy( pathbuf, buf);
1561 +       if ( *buf != '\0' && l < MAXPATHLEN) {
1562 +           pathbuf[l++] = '/';
1563 +           pathbuf[l] = 0;
1564 +       }
1565 +       slash = ".Parent";
1566 +    } else {
1567 +       if (NULL != ( slash = strrchr( buf, '/' )) ) {
1568 +           c = *++slash;
1569 +           *slash = '\0';
1570 +           strcpy( pathbuf, buf);
1571 +           *slash = c;
1572 +       } else {
1573 +           pathbuf[ 0 ] = '\0';
1574 +           slash = buf;
1575 +       }
1576 +    }
1577 +    strlcat( pathbuf, ".AppleDouble/", MAXPATHLEN +1);
1578 +    strlcat( pathbuf, slash, MAXPATHLEN +1);
1579 +
1580 +    strlcat( pathbuf, "/Afp_AfpInfo", MAXPATHLEN +1);
1581 +
1582 +#if 0
1583 +    if ((adflags & ADFLAGS_HF)) {
1584 +        strlcat( pathbuf, "Afp_AfpInfo", MAXPATHLEN +1);
1585 +    else {
1586 +        strlcat( pathbuf, "Afp_Resource", MAXPATHLEN +1);
1587 +    }
1588 +#endif      
1589 +    return( pathbuf );
1590 +}
1591 +
1592 +/* -------------------- */
1593 +static int ad_mkrf_ads(char *path)
1594 +{
1595 +    char *slash;
1596 +    /*
1597 +     * Probably .AppleDouble doesn't exist, try to mkdir it.
1598 +     */
1599 +     if (NULL == ( slash = strrchr( path, '/' )) ) {
1600 +         return -1;
1601 +     }
1602 +     *slash = 0;
1603 +     errno = 0;
1604 +     if ( ad_mkdir( path, 0777 ) < 0 ) {
1605 +         if ( errno == ENOENT ) {
1606 +             char *slash1;
1607 +             
1608 +             if (NULL == ( slash1 = strrchr( path, '/' )) ) 
1609 +                 return -1;
1610 +             errno = 0;
1611 +             *slash1 = 0;
1612 +             if ( ad_mkdir( path, 0777 ) < 0 ) 
1613 +                  return -1;
1614 +             *slash1 = '/';
1615 +             if ( ad_mkdir( path, 0777 ) < 0 )
1616 +                 return -1;
1617 +         }
1618 +         else
1619 +            return -1;
1620 +     }     
1621 +     *slash = '/';
1622 +     return 0;
1623 +}
1624 +
1625 +/* -------------------------
1626   * Support inherited protection modes for AppleDouble files.  The supplied
1627   * mode is ANDed with the parent directory's mask value in lieu of "umask",
1628   * and that value is returned.
1629 @@ -914,10 +1022,16 @@
1630      memset( ad, 0, sizeof( struct adouble ) );
1631      ad->ad_flags = flags;
1632      if (flags == AD_VERSION2_OSX) {
1633 -        ad->ad_path     = ad_path_osx;
1634 +        ad->ad_path = ad_path_osx;
1635 +        ad->ad_mkrf = ad_mkrf_osx;
1636 +    }
1637 +    else if (flags == AD_VERSION1_ADS) {
1638 +        ad->ad_path = ad_path_ads;
1639 +        ad->ad_mkrf = ad_mkrf_ads;
1640      }
1641      else {
1642 -        ad->ad_path     = ad_path;
1643 +        ad->ad_path = ad_path;
1644 +        ad->ad_mkrf = ad_mkrf;
1645      }
1646  }
1647  
1648 @@ -931,7 +1045,7 @@
1649      struct adouble     *ad;
1650  {
1651      struct stat         st;
1652 -    char               *slash, *ad_p;
1653 +    char               *ad_p;
1654      int                        hoflags, admode;
1655      int                 st_invalid;
1656      int                 open_df = 0;
1657 @@ -1031,19 +1145,9 @@
1658             st_invalid = ad_mode_st(ad_p, &admode, &st);
1659             admode = ad_hf_mode(admode); 
1660             if ( errno == ENOENT && !(adflags & ADFLAGS_NOADOUBLE) && ad->ad_flags != AD_VERSION2_OSX) {
1661 -               /*
1662 -                * Probably .AppleDouble doesn't exist, try to
1663 -                * mkdir it.
1664 -                */
1665 -               if (NULL == ( slash = strrchr( ad_p, '/' )) ) {
1666 -                   return ad_error(ad, adflags);
1667 -               }
1668 -               *slash = '\0';
1669 -               errno = 0;
1670 -               if ( ad_mkdir( ad_p, 0777 ) < 0 ) {
1671 +               if (ad->ad_mkrf( ad_p) < 0) {
1672                     return ad_error(ad, adflags);
1673 -               }
1674 -               *slash = '/';
1675 +               }
1676                 admode = mode;
1677                 st_invalid = ad_mode_st(ad_p, &admode, &st);
1678                 admode = ad_hf_mode(admode);