1 First try for a netatalk vfs layer
4 adouble=v1,v2 classic adouble format
5 adouble=osx ._<filename> OSX resource fork.
6 adouble=ads NT like alternate data stream.
9 * cf. patch.vfs for samba ADS vfs layer and patch.samba.xx for samba tree patch.
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.
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.
17 * It's ok for rename, delete, chown and chmod.
19 * Copy from a NT box should work.
21 * Last but not least : only on a new volume!
24 indirection for metadata, aka stored in EA, a different file, whatever.
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
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
36 afpd_LDADD = $(top_builddir)/libatalk/cnid/libcnid.la $(top_builddir)/libatalk/libatalk.la
37 afpd_LDFLAGS = -export-dynamic
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
44 LIBS = @LIBS@ @PAM_LIBS@ @QUOTA_LIBS@ @SLP_LIBS@
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
51 + Copyright (c) 2004 Didier Gautheron
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.
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.
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.
73 +#include <atalk/adouble.h>
77 + /* low level adouble fn */
78 + char *(*ad_path)(const char *, int);
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);
89 + int (*rf_setdirowner)(const struct vol *, const char *path, uid_t owner, gid_t group);
91 + int (*rf_deletefile)(const struct vol *, const char * );
92 + int (*rf_renamefile)(const struct vol *, const char *oldpath, const char *newpath);
96 +void initvol_vfs(struct vol *vol);
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
103 system rmdir with afp error code.
104 ENOENT is not an error.
106 -static int netatalk_rmdir(const char *name)
107 +int netatalk_rmdir(const char *name)
109 if (rmdir(name) < 0) {
111 @@ -2075,15 +2075,11 @@
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));
120 + vol->vfs->rf_renamedir(vol, src, dst);
122 len = strlen( newname );
123 /* rename() succeeded so we need to update our tree even if we can't open
128 ad_init(&ad, vol->v_adouble);
129 @@ -2132,12 +2128,9 @@
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;
143 @@ -2162,42 +2155,9 @@
148 - if (vol->v_adouble == AD_VERSION2_OSX) {
150 - if ((err = netatalk_unlink(vol->ad_path(".",0) )) ) {
155 - /* delete stray .AppleDouble files. this happens to get .Parent files
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, ".."))
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) {
168 - return AFPERR_DIRNEMPT;
171 - strcpy(path + DOT_APPLEDOUBLE_LEN, de->d_name);
172 - if ((err = netatalk_unlink(path))) {
180 - if ( (err = netatalk_rmdir( ".AppleDouble" )) ) {
183 + err = vol->vfs->rf_deletecurdir(vol);
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
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 *,
200 extern mode_t mtoumode __P((struct maccess *));
202 extern int check_access __P((char *name , int mode));
203 extern int file_access __P((struct path *path, int mode));
205 +extern int netatalk_rmdir __P((const char *name));
206 extern int netatalk_unlink __P((const char *name));
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
213 if (!strcmp(name, "..") || !strcmp(name, "."))
216 - if (!vol->validupath(vol, name))
217 + if (!vol->vfs->validupath(vol, name))
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
226 /* second try with adouble open
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;
237 - char adsrc[ MAXPATHLEN + 1];
241 @@ -1055,38 +1054,10 @@
245 - strcpy( adsrc, vol->ad_path( src, 0 ));
247 - if (unix_rename( adsrc, vol->ad_path( dst, 0 )) < 0 ) {
249 + if (vol->vfs->rf_renamefile(vol, src, dst) < 0 ) {
253 - if (errno == ENOENT) {
256 - if (stat(adsrc, &st)) /* source has no ressource fork, */
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.
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 )) )
274 - else { /* it's something else, bail out */
278 /* try to undo the data fork rename,
279 * we know we are on the same device
281 @@ -1436,6 +1407,7 @@
283 deletefile(d_vol, dst, 0);
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) {
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 )) ) {
297 if (checkAttrib && (id = cnid_get(vol->v_cdb, curdir->d_did, file, strlen(file))))
299 cnid_delete(vol->v_cdb, id);
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
309 return AFPERR_NOOBJ ;
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.");
318 if ((vol->v_flags & AFPVOL_NOHEX) && strchr(name, '/'))
321 - if (!vol->validupath(vol, name))
322 + if (!vol->vfs->validupath(vol, name))
325 /* check for vetoed filenames */
330 - rc = deletecurdir( vol, obj->oldtmp, AFPOBJ_TMPSIZ);
331 + rc = deletecurdir( vol);
333 } else if (of_findname(s_path)) {
336 int admode = ad_mode("", 0777);
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);
342 setvoltime(obj, vol );
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
348 rwx-wx-wx or rwx-wx--
349 rwx----wx (is not asked by a Mac with OS >= 8.0 ?)
351 -static int stickydirmode(name, mode, dropbox)
353 +int stickydirmode(name, mode, dropbox)
358 @@ -405,12 +405,12 @@
359 if (setfilmode( path->u_name, mode, &path->st) < 0)
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);
366 /* --------------------- */
367 int setfilmode(name, mode, st)
373 @@ -436,29 +436,18 @@
377 -char *adouble = vol->ad_path( name, ADFLAGS_DIR );
379 int dropbox = (vol->v_flags & AFPVOL_DROPBOX);
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 )
386 - if (vol->v_adouble != AD_VERSION2_OSX) {
387 - if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol)) {
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)) {
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)) {
402 if ( stickydirmode(name, DIRBITS | mode, dropbox) < 0 )
405 @@ -471,26 +460,17 @@
409 - char buf[ MAXPATHLEN + 1];
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);
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 )
426 - if (stickydirmode(adouble_p, DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol)) {
432 if (( dir = opendir( name )) == NULL ) {
433 @@ -516,61 +496,13 @@
438 - /* Don't change subdir perm */
439 - else if (S_ISDIR(st.st_mode)) {
440 - if (stickydirmode(dirp->d_name, DIRBITS | mode, dropbox) < 0)
442 - } else if (stickydirmode(dirp->d_name, mode, dropbox) < 0)
450 - goto setdirmode_noadouble;
453 - /* change perm of .AppleDouble's files
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) );
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 ) {
470 - strcat( buf, dirp->d_name );
472 - if ( stat( buf, &st ) < 0 ) {
473 - LOG(log_error, logtype_afpd, "setdirmode: stat %s: %s", buf, strerror(errno) );
476 - if (!S_ISDIR(st.st_mode)) {
477 - if (setfilmode(buf, hf_mode , &st) < 0) {
478 - /* FIXME what do we do then? */
484 - if (!dir_rx_set(mode)) {
485 - /* XXX: need to preserve special modes */
486 - if (stickydirmode(adouble_p, DIRBITS | mode, dropbox) < 0 ) {
489 + if (vol->vfs->rf_setdirmode(vol, name, mode, NULL) < 0 && !vol_noadouble(vol)) {
493 -setdirmode_noadouble:
494 if (!dir_rx_set(mode)) {
495 if ( stickydirmode(name, DIRBITS | mode, dropbox) < 0 )
501 +/* ----------------------------- */
502 int setdeskowner( uid, gid )
512 if (!path->st_valid) {
514 @@ -665,22 +596,15 @@
518 - ad_p = vol->ad_path( path->u_name, ADFLAGS_HF );
520 - if ( stat( ad_p, &st ) < 0 ) {
524 - if ( chown( ad_p, uid, gid ) < 0 &&
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) );
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 @@
545 - char buf[ MAXPATHLEN + 1];
550 int osx = vol->v_adouble == AD_VERSION2_OSX;
551 - int noadouble = vol_noadouble(vol);
555 if (( dir = opendir( name )) == NULL ) {
557 @@ -723,56 +642,15 @@
563 - goto setdirowner_noadouble;
566 - adouble = vol->ad_path( name, ADFLAGS_DIR );
567 - adouble_p = ad_dir(adouble);
568 - if (( dir = opendir( adouble_p )) == NULL ) {
570 - goto setdirowner_noadouble;
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 ) {
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 */
592 - * We cheat: we know that chown doesn't do anything.
594 - if ( stat( ".AppleDouble", &st ) < 0 ) {
595 - LOG(log_error, logtype_afpd, "setdirowner: stat %s: %s", fullpathname(".AppleDouble"), strerror(errno) );
598 - if ( gid && gid != st.st_gid && chown( ".AppleDouble", uid, gid ) < 0 &&
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) {
607 -setdirowner_noadouble:
609 if ( stat( ".", &st ) < 0 ) {
612 - if ( gid && gid != st.st_gid && chown( ".", uid, gid ) < 0 &&
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) );
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));
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
640 + Copyright (c) 2004 Didier Gautheron
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.
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.
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.
657 +#ifdef HAVE_CONFIG_H
659 +#endif /* HAVE_CONFIG_H */
667 +#include <atalk/adouble.h>
668 +#include <atalk/logger.h>
669 +#include <atalk/util.h>
671 +#include "directory.h"
680 +typedef int (*rf_loop)(struct dirent *, char *, void *, int );
682 +/* ----------------------------- */
684 +for_each_adouble(const char *from, const char *name, rf_loop fn, void *data, int flag)
686 + char buf[ MAXPATHLEN + 1];
693 + if (NULL == ( dp = opendir( name)) ) {
695 + LOG(log_error, logtype_afpd, "%s: opendir %s: %s", from, fullpathname(name),strerror(errno) );
700 + strlcpy( buf, name, sizeof(buf));
701 + strlcat( buf, "/", sizeof(buf) );
702 + m = strchr( buf, '\0' );
704 + while ((de = readdir(dp))) {
705 + if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
709 + strlcat(buf, de->d_name, sizeof(buf));
710 + if (fn && (ret = fn(de, buf, data, flag))) {
720 +/* ------------------------------ */
721 +static int ads_chown_loop(struct dirent *de, char *name, void *data, int flag)
723 + struct perm *owner = data;
725 + if (chown( name , owner->uid, owner->gid ) < 0) {
731 +static int RF_chown_ads(const struct vol *vol, const char *path, uid_t uid, gid_t gid)
742 + ad_p = ad_dir(vol->vfs->ad_path(path, ADFLAGS_HF ));
744 + if ( stat( ad_p, &st ) < 0 ) {
749 + if (chown( ad_p, uid, gid ) < 0) {
752 + return for_each_adouble("chown_ads", ad_p, ads_chown_loop, &owner, 1);
755 +/* --------------------------------- */
756 +static int deletecurdir_ads1_loop(struct dirent *de, char *name, void *data, int flag)
758 + return netatalk_unlink(name);
761 +static int ads_delete_rf(char *name)
765 + if ((err = for_each_adouble("deletecurdir", name, deletecurdir_ads1_loop, NULL, 1)))
767 + return netatalk_rmdir(name);
770 +static int deletecurdir_ads_loop(struct dirent *de, char *name, void *data, int flag)
774 + /* bail if the file exists in the current directory.
775 + * note: this will not fail with dangling symlinks */
777 + if (stat(de->d_name, &st) == 0) {
778 + return AFPERR_DIRNEMPT;
780 + return ads_delete_rf(name);
783 +static int RF_deletecurdir_ads(const struct vol *vol)
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)))
790 + return netatalk_rmdir( ".AppleDouble" );
793 +/* ------------------- */
799 +static int ads_setfilmode_loop(struct dirent *de, char *name, void *data, int flag)
801 + struct set_mode *param = data;
803 + return setfilmode(name, param->mode, param->st);
806 +static int ads_setfilmode(const char * name, mode_t mode, struct stat *st)
808 + mode_t dir_mode = mode;
809 + mode_t file_mode = ad_hf_mode(mode);
810 + struct set_mode param;
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;
819 + /* change folder */
820 + dir_mode |= DIRBITS;
821 + if (dir_rx_set(dir_mode)) {
822 + if (chmod( name, dir_mode ) < 0)
826 + param.mode = file_mode;
827 + if (for_each_adouble("setfilmode_ads", name, ads_setfilmode_loop, ¶m, 0) < 0)
830 + if (!dir_rx_set(dir_mode)) {
831 + if (chmod( name, dir_mode ) < 0)
838 +static int RF_setfilmode_ads(const struct vol *vol, const char * name, mode_t mode, struct stat *st)
840 + return ads_setfilmode(ad_dir(vol->vfs->ad_path( name, ADFLAGS_HF )), mode, st);
843 +/* ------------------- */
844 +static int RF_setdirunixmode_ads(const struct vol *vol, const char * name, mode_t mode, struct stat *st)
846 + char *adouble = vol->vfs->ad_path( name, ADFLAGS_DIR );
847 + char ad_p[ MAXPATHLEN + 1];
848 + int dropbox = (vol->v_flags & AFPVOL_DROPBOX);
850 + strlcpy(ad_p,ad_dir(adouble), MAXPATHLEN + 1);
852 + if (dir_rx_set(mode)) {
855 + if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol))
858 + /* .AppleDouble/.Parent */
859 + if (stickydirmode(ad_p, DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol))
863 + if (ads_setfilmode(ad_dir(vol->vfs->ad_path( name, ADFLAGS_DIR)), mode, st) < 0)
866 + if (!dir_rx_set(mode)) {
867 + if (stickydirmode(ad_p, DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol))
869 + if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol))
875 +/* ------------------- */
881 +static int setdirmode_ads_loop(struct dirent *de, char *name, void *data, int flag)
884 + struct dir_mode *param = data;
885 + int ret = 0; /* 0 ignore error, -1 */
887 + if (dir_rx_set(param->mode)) {
888 + if (stickydirmode(name, DIRBITS | param->mode, param->dropbox) < 0) {
895 + if (ads_setfilmode(name, param->mode, NULL) < 0)
898 + if (!dir_rx_set(param->mode)) {
899 + if (stickydirmode(name, DIRBITS | param->mode, param->dropbox) < 0) {
909 +static int RF_setdirmode_ads(const struct vol *vol, const char * name, mode_t mode, struct stat *st)
911 + char *adouble = vol->vfs->ad_path( name, ADFLAGS_DIR );
912 + char ad_p[ MAXPATHLEN + 1];
913 + struct dir_mode param;
916 + param.dropbox = (vol->v_flags & AFPVOL_DROPBOX);
918 + strlcpy(ad_p,ad_dir(adouble), sizeof(ad_p));
920 + if (dir_rx_set(mode)) {
922 + if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, param.dropbox) < 0 && !vol_noadouble(vol))
926 + if (for_each_adouble("setdirmode_ads", ad_dir(ad_p), setdirmode_ads_loop, ¶m, vol_noadouble(vol)))
929 + if (!dir_rx_set(mode)) {
930 + if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, param.dropbox) < 0 && !vol_noadouble(vol))
936 +/* ------------------- */
937 +static int setdirowner_ads1_loop(struct dirent *de, char *name, void *data, int flag)
939 + struct perm *owner = data;
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 */
949 +static int setdirowner_ads_loop(struct dirent *de, char *name, void *data, int flag)
951 + struct perm *owner = data;
953 + if (for_each_adouble("setdirowner", name, setdirowner_ads1_loop, data, flag) < 0)
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 */
964 +static int RF_setdirowner_ads(const struct vol *vol, const char *name, uid_t uid, gid_t gid)
966 + int noadouble = vol_noadouble(vol);
967 + char adouble_p[ MAXPATHLEN + 1];
974 + strlcpy(adouble_p, ad_dir(vol->vfs->ad_path( name, ADFLAGS_DIR )), sizeof(adouble_p));
976 + if (for_each_adouble("setdirowner", ad_dir(adouble_p), setdirowner_ads_loop, &owner, noadouble))
980 + * We cheat: we know that chown doesn't do anything.
982 + if ( stat( ".AppleDouble", &st ) < 0) {
983 + if (errno == ENOENT && noadouble)
985 + LOG(log_error, logtype_afpd, "setdirowner: stat %s: %s", fullpathname(".AppleDouble"), strerror(errno) );
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 */
996 +/* ------------------- */
997 +static int RF_deletefile_ads(const struct vol *vol, const char *file )
999 + char *ad_p = ad_dir(vol->vfs->ad_path(file, ADFLAGS_HF ));
1001 + return ads_delete_rf(ad_p);
1004 +/* --------------------------- */
1005 +int RF_renamefile_ads(const struct vol *vol, const char *src, const char *dst)
1007 + char adsrc[ MAXPATHLEN + 1];
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) {
1015 + if (errno == ENOENT) {
1016 + struct adouble ad;
1018 + if (stat(adsrc, &st)) /* source has no ressource fork, */
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.
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);
1032 + /* We must delete it */
1033 + RF_deletefile_ads(vol, dst );
1034 + if (!unix_rename( adsrc, ad_dir(vol->vfs->ad_path( dst, 0 ))) )
1039 + else { /* it's something else, bail out */
1051 +/* ===================================================
1052 + classic adouble format
1055 +static int validupath_adouble(const struct vol *vol, const char *name)
1057 + return (vol->v_flags & AFPVOL_USEDOTS) ? strncasecmp(name,".Apple", 6) && strcasecmp(name, ".Parent")
1061 +/* ----------------- */
1062 +static int RF_chown_adouble(const struct vol *vol, const char *path, uid_t uid, gid_t gid)
1068 + ad_p = vol->vfs->ad_path(path, ADFLAGS_HF );
1070 + if ( stat( ad_p, &st ) < 0 )
1071 + return 0; /* ignore */
1073 + return chown( ad_p, uid, gid );
1076 +/* ----------------- */
1077 +int RF_renamedir_adouble(const struct vol *vol, const char *oldpath, const char *newpath)
1082 +/* ----------------- */
1083 +static int deletecurdir_adouble_loop(struct dirent *de, char *name, void *data, int flag)
1088 + /* bail if the file exists in the current directory.
1089 + * note: this will not fail with dangling symlinks */
1091 + if (stat(de->d_name, &st) == 0)
1092 + return AFPERR_DIRNEMPT;
1094 + if ((err = netatalk_unlink(name)))
1100 +static int RF_deletecurdir_adouble(const struct vol *vol)
1104 + /* delete stray .AppleDouble files. this happens to get .Parent files
1106 + if ((err = for_each_adouble("deletecurdir", ".AppleDouble", deletecurdir_adouble_loop, NULL, 1)))
1108 + return netatalk_rmdir( ".AppleDouble" );
1111 +/* ----------------- */
1112 +static int adouble_setfilmode(const char * name, mode_t mode, struct stat *st)
1114 + return setfilmode(name, ad_hf_mode(mode), st);
1117 +static int RF_setfilmode_adouble(const struct vol *vol, const char * name, mode_t mode, struct stat *st)
1119 + return adouble_setfilmode(vol->vfs->ad_path( name, ADFLAGS_HF ), mode, st);
1122 +/* ----------------- */
1123 +static int RF_setdirunixmode_adouble(const struct vol *vol, const char * name, mode_t mode, struct stat *st)
1125 + char *adouble = vol->vfs->ad_path( name, ADFLAGS_DIR );
1126 + int dropbox = (vol->v_flags & AFPVOL_DROPBOX);
1128 + if (dir_rx_set(mode)) {
1129 + if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol))
1133 + if (adouble_setfilmode(vol->vfs->ad_path( name, ADFLAGS_DIR ), mode, st) < 0)
1136 + if (!dir_rx_set(mode)) {
1137 + if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol))
1143 +/* ----------------- */
1144 +static int setdirmode_adouble_loop(struct dirent *de, char *name, void *data, int flag)
1146 + int hf_mode = *(int *)data;
1149 + if ( stat( name, &st ) < 0 ) {
1152 + LOG(log_error, logtype_afpd, "setdirmode: stat %s: %s", name, strerror(errno) );
1154 + else if (!S_ISDIR(st.st_mode)) {
1155 + if (setfilmode(name, hf_mode , &st) < 0) {
1156 + /* FIXME what do we do then? */
1162 +static int RF_setdirmode_adouble(const struct vol *vol, const char * name, mode_t mode, struct stat *st1)
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);
1169 + if (dir_rx_set(mode)) {
1170 + if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol))
1174 + if (for_each_adouble("setdirmode", adouble_p, setdirmode_adouble_loop, &hf_mode, vol_noadouble(vol)))
1177 + if (!dir_rx_set(mode)) {
1178 + if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol))
1184 +/* ----------------- */
1185 +static int setdirowner_adouble_loop(struct dirent *de, char *name, void *data, int flag)
1187 + struct perm *owner = data;
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 */
1197 +static int RF_setdirowner_adouble(const struct vol *vol, const char *name, uid_t uid, gid_t gid)
1200 + int noadouble = vol_noadouble(vol);
1203 + struct perm owner;
1208 + adouble_p = ad_dir(vol->vfs->ad_path( name, ADFLAGS_DIR ));
1210 + if (for_each_adouble("setdirowner", adouble_p, setdirowner_adouble_loop, &owner, noadouble))
1214 + * We cheat: we know that chown doesn't do anything.
1216 + if ( stat( ".AppleDouble", &st ) < 0) {
1217 + if (errno == ENOENT && noadouble)
1219 + LOG(log_error, logtype_afpd, "setdirowner: stat %s: %s", fullpathname(".AppleDouble"), strerror(errno) );
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 */
1230 +/* ----------------- */
1231 +static int RF_deletefile_adouble(const struct vol *vol, const char *file )
1233 + return netatalk_unlink(vol->vfs->ad_path( file, ADFLAGS_HF));
1236 +/* ----------------- */
1237 +int RF_renamefile_adouble(const struct vol *vol, const char *src, const char *dst)
1239 + char adsrc[ MAXPATHLEN + 1];
1242 + strcpy( adsrc, vol->vfs->ad_path( src, 0 ));
1243 + if (unix_rename( adsrc, vol->vfs->ad_path( dst, 0 )) < 0) {
1247 + if (errno == ENOENT) {
1248 + struct adouble ad;
1250 + if (stat(adsrc, &st)) /* source has no ressource fork, */
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.
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 )) )
1268 + else { /* it's something else, bail out */
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,
1294 +/* =======================================
1295 + osx adouble format
1297 +static int validupath_osx(const struct vol *vol, const char *name)
1299 + return strncasecmp(name,".Apple", 6) && strncasecmp(name,"._", 2);
1302 +/* ---------------- */
1303 +int RF_renamedir_osx(const struct vol *vol, const char *oldpath, const char *newpath)
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));
1310 +/* ---------------- */
1311 +int RF_deletecurdir_osx(const struct vol *vol)
1313 + return netatalk_unlink( vol->vfs->ad_path(".",0) );
1316 +/* ---------------- */
1317 +static int RF_setdirunixmode_osx(const struct vol *vol, const char * name, mode_t mode, struct stat *st)
1319 + return adouble_setfilmode(vol->vfs->ad_path( name, ADFLAGS_DIR ), mode, st);
1322 +/* ---------------- */
1323 +static int RF_setdirmode_osx(const struct vol *vol, const char * name, mode_t mode, struct stat *st)
1328 +/* ---------------- */
1329 +static int RF_setdirowner_osx(const struct vol *vol, const char *path, uid_t uid, gid_t gid)
1334 +/* ---------------- */
1335 +int RF_renamefile_osx(const struct vol *vol, const char *src, const char *dst)
1337 + char adsrc[ MAXPATHLEN + 1];
1339 + strcpy( adsrc, vol->vfs->ad_path( src, 0 ));
1340 + return unix_rename( adsrc, vol->vfs->ad_path( dst, 0 ));
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,
1357 +/* =======================================
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,
1374 +/* ---------------- */
1375 +void initvol_vfs(struct vol *vol)
1377 + if (vol->v_adouble == AD_VERSION2_OSX) {
1378 + vol->vfs = &netatalk_adouble_osx;
1380 + else if (vol->v_adouble == AD_VERSION1_ADS) {
1381 + vol->vfs = &netatalk_adouble_ads;
1384 + vol->vfs = &netatalk_adouble;
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
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;
1398 } else if (optionok(tmp, "options:", val)) {
1400 @@ -523,34 +525,6 @@
1404 -/* -----------------
1405 - * FIXME should be define elsewhere
1407 -static int validupath_adouble(const struct vol *vol, const char *name)
1409 - return (vol->v_flags & AFPVOL_USEDOTS) ? strncasecmp(name,".Apple", 6) && strcasecmp(name, ".Parent")
1413 -/* ----------------- */
1414 -static int validupath_osx(const struct vol *vol, const char *name)
1416 - return strncasecmp(name,".Apple", 6) && strncasecmp(name,"._", 2);
1419 -/* ---------------- */
1420 -static void initvoladouble(struct vol *vol)
1422 - if (vol->v_adouble == AD_VERSION2_OSX) {
1423 - vol->validupath = validupath_osx;
1424 - vol->ad_path = ad_path_osx;
1427 - vol->validupath = validupath_adouble;
1428 - vol->ad_path = ad_path;
1432 /* ------------------------------- */
1433 static int creatvol(AFPObj *obj, struct passwd *pwd,
1434 char *path, char *name,
1436 volume->v_adouble = options[VOLOPT_ADOUBLE].i_value;
1438 volume->v_adouble = AD_VERSION;
1439 - initvoladouble(volume);
1441 + initvol_vfs(volume);
1443 if (options[VOLOPT_FORCEUID].c_value) {
1444 volume->v_forceuid = strdup(options[VOLOPT_FORCEUID].c_value);
1445 @@ -2231,6 +2206,9 @@
1447 case AD_VERSION2_OSX:
1448 strlcat(buf, "ADOUBLE_VER:osx\n", sizeof(buf));
1450 + case AD_VERSION1_ADS:
1451 + strlcat(buf, "ADOUBLE_VER:ads\n", sizeof(buf));
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
1460 #include "atalk/unicode.h"
1461 #include "globals.h"
1462 +#include "afp_vfs.h"
1464 #define AFPVOL_NAMELEN 27
1467 int v_preexec_close;
1469 /* adouble indirection */
1470 + struct vfs_ops *vfs;
1471 int (*validupath)(const struct vol *, const char *);
1472 char *(*ad_path)(const char *, int);
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
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
1486 the header parameter size is too small.
1488 char *(*ad_path)(const char *, int);
1489 + int (*ad_mkrf)(char *);
1491 #ifdef USE_MMAPPED_HEADERS
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));
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 @@
1508 +/* -------------------- */
1509 +static int ad_mkrf(char *path)
1513 + * Probably .AppleDouble doesn't exist, try to mkdir it.
1515 + if (NULL == ( slash = strrchr( path, '/' )) ) {
1520 + if ( ad_mkdir( path, 0777 ) < 0 ) {
1527 /* ---------------------------------------
1528 * Put the resource fork where it needs to be:
1530 @@ -729,8 +748,97 @@
1531 strlcat( pathbuf, slash, MAXPATHLEN +1);
1534 +/* -------------------- */
1535 +static int ad_mkrf_osx(char *path)
1541 +/* ---------------------------------------
1542 + * Put the .AppleDouble where it needs to be:
1544 + * / a/.AppleDouble/b/Afp_AfpInfo
1546 + * \ b/.AppleDouble/.Parent/Afp_AfpInfo
1550 +ad_path_ads( path, adflags )
1554 + static char pathbuf[ MAXPATHLEN + 1];
1555 + char c, *slash, buf[MAXPATHLEN + 1];
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++] = '/';
1565 + slash = ".Parent";
1567 + if (NULL != ( slash = strrchr( buf, '/' )) ) {
1570 + strcpy( pathbuf, buf);
1573 + pathbuf[ 0 ] = '\0';
1577 + strlcat( pathbuf, ".AppleDouble/", MAXPATHLEN +1);
1578 + strlcat( pathbuf, slash, MAXPATHLEN +1);
1580 + strlcat( pathbuf, "/Afp_AfpInfo", MAXPATHLEN +1);
1583 + if ((adflags & ADFLAGS_HF)) {
1584 + strlcat( pathbuf, "Afp_AfpInfo", MAXPATHLEN +1);
1586 + strlcat( pathbuf, "Afp_Resource", MAXPATHLEN +1);
1589 + return( pathbuf );
1592 +/* -------------------- */
1593 +static int ad_mkrf_ads(char *path)
1597 + * Probably .AppleDouble doesn't exist, try to mkdir it.
1599 + if (NULL == ( slash = strrchr( path, '/' )) ) {
1604 + if ( ad_mkdir( path, 0777 ) < 0 ) {
1605 + if ( errno == ENOENT ) {
1608 + if (NULL == ( slash1 = strrchr( path, '/' )) )
1612 + if ( ad_mkdir( path, 0777 ) < 0 )
1615 + if ( ad_mkdir( path, 0777 ) < 0 )
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;
1637 + else if (flags == AD_VERSION1_ADS) {
1638 + ad->ad_path = ad_path_ads;
1639 + ad->ad_mkrf = ad_mkrf_ads;
1642 - ad->ad_path = ad_path;
1643 + ad->ad_path = ad_path;
1644 + ad->ad_mkrf = ad_mkrf;
1648 @@ -931,7 +1045,7 @@
1652 - char *slash, *ad_p;
1654 int hoflags, admode;
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) {
1662 - * Probably .AppleDouble doesn't exist, try to
1665 - if (NULL == ( slash = strrchr( ad_p, '/' )) ) {
1666 - return ad_error(ad, adflags);
1670 - if ( ad_mkdir( ad_p, 0777 ) < 0 ) {
1671 + if (ad->ad_mkrf( ad_p) < 0) {
1672 return ad_error(ad, adflags);
1677 st_invalid = ad_mode_st(ad_p, &admode, &st);
1678 admode = ad_hf_mode(admode);