]> arthur.barton.de Git - netatalk.git/commitdiff
- added a cache for directories offspring count.
authordidg <didg>
Fri, 11 Oct 2002 14:18:21 +0000 (14:18 +0000)
committerdidg <didg>
Fri, 11 Oct 2002 14:18:21 +0000 (14:18 +0000)
- added unix name in struct dir.

- added pread/pwrite, (there was at least one bug in adf_off book keeping).

- removed (temporary?) memory mmap header, it was unused and made the code
  unreadable.

- used a new struct path with unix name, mac name and file stat.

- fixed for catsearch (not well tested)

- temporary ATACC and NO_UAM_LOAD, I will remove them (ATACC is a test coverage tool).

- added AFP 3.1 calls readext,writeext, bytelockext, enumerateext2
  (catsearchext, enumerateext are the same) . --afp3 parameter in
  configure. configure.in changes aren't good. Maybe get CVS samba stuff
  (eg for linux there's no sendfile64 on 32 bits box). The biggest change
  is that we can't use the ressource fork len in the header (it's too
  small). Not well tested.

- fixed few signed/unsigned missmatch, mainly when a signed fetched from the wire is checked
  against and unsigned buffer size.

31 files changed:
acconfig.h
configure.in
etc/afpd/afp_dsi.c
etc/afpd/afs.c
etc/afpd/appl.c
etc/afpd/auth.c
etc/afpd/catsearch.c
etc/afpd/desktop.c
etc/afpd/directory.c
etc/afpd/directory.h
etc/afpd/enumerate.c
etc/afpd/file.c
etc/afpd/file.h
etc/afpd/filedir.c
etc/afpd/filedir.h
etc/afpd/fork.c
etc/afpd/fork.h
etc/afpd/ofork.c
etc/afpd/volume.c
include/atalk/adouble.h
include/atalk/asp.h
include/atalk/dsi.h
libatalk/adouble/ad_flush.c
libatalk/adouble/ad_open.c
libatalk/adouble/ad_read.c
libatalk/adouble/ad_sendfile.c
libatalk/adouble/ad_size.c
libatalk/adouble/ad_write.c
libatalk/dsi/dsi_stream.c
libatalk/util/Makefile.am
libatalk/util/strcasestr.c [new file with mode: 0644]

index 932f412055db695a21c7d0094f6c9a083168963f..5af797270bbaea467fed01e74888101df04cb5de 100644 (file)
@@ -48,6 +48,7 @@
 #undef USE_OLD_RQUOTA
 #undef USE_UFS_QUOTA_H
 #undef WITH_CATSEARCH
+#undef AFP3x
 #undef HAVE_DECL_ERRNO
 #undef HAVE_DECL_SYS_ERRLIST
 #undef HAVE_DECL_SYS_NERR
index 564c0c40d658adcbfc880573a318d86288daaa6a..35c37cecc3cbb381b9cfb8a686672c326fc8f7d6 100644 (file)
@@ -1,4 +1,4 @@
-dnl $Id: configure.in,v 1.168 2002-10-04 15:11:57 srittau Exp $
+dnl $Id: configure.in,v 1.169 2002-10-11 14:18:22 didg Exp $
 dnl configure.in for netatalk
 
 AC_INIT(bin/adv1tov2/adv1tov2.c)
@@ -72,6 +72,8 @@ AC_CHECK_LIB(ubik, main)
 # Be sure to test before adding AFS libs in LIBS path as AFS lib
 # has such a function that works only on AFS filesystems.
 AC_CHECK_FUNCS(access)
+# 
+AC_CHECK_FUNCS(pread pwrite)
 
 dnl Checks for header files.
 AC_HEADER_DIRENT
@@ -104,7 +106,7 @@ AC_FUNC_MMAP
 AC_TYPE_SIGNAL
 AC_FUNC_UTIME_NULL
 AC_FUNC_WAIT3
-AC_CHECK_FUNCS(flock getcwd gethostname gettimeofday getusershell mkdir rmdir select socket strdup strstr strtoul setpgrp strchr memcpy)
+AC_CHECK_FUNCS(flock getcwd gethostname gettimeofday getusershell mkdir rmdir select socket strdup strcasestr strstr strtoul setpgrp strchr memcpy)
 AC_FUNC_SETPGRP
 
 dnl Checks for (v)snprintf
@@ -184,6 +186,20 @@ AC_ARG_ENABLE(debug,
        fi
 )
 
+afp3=no
+AC_ARG_ENABLE(afp3,
+       [  --enable-afp3          enable AFP 3.x calls],
+       if test "$enableval" = "yes"; then
+               afp3=yes
+               AC_DEFINE(AFP3x, 1)
+               AC_MSG_RESULT([enabling AFP 3.x calls])
+       fi
+)
+
+if test "$afp3" = "yes"; then
+        AC_SYS_LARGEFILE
+fi
+
 
 dnl ----------- A NOTE ABOUT DROPKLUDGE
 dnl The trouble with this fix is that if you know what the file is called, it
index f881de659cc44a898ace619254f3be8d7b3b5549..0566942bb3ed40ae859dd13a81ef32629a940941 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: afp_dsi.c,v 1.24 2002-08-30 19:32:40 didg Exp $
+ * $Id: afp_dsi.c,v 1.25 2002-10-11 14:18:23 didg Exp $
  *
  * Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu)
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
@@ -102,11 +102,11 @@ static void afp_dsi_timedown()
     it.it_interval.tv_usec = 0;
     it.it_value.tv_sec = 300;
     it.it_value.tv_usec = 0;
+
     if ( setitimer( ITIMER_REAL, &it, 0 ) < 0 ) {
         LOG(log_error, logtype_afpd, "afp_timedown: setitimer: %s", strerror(errno) );
         afp_dsi_die(1);
     }
-
     memset(&sv, 0, sizeof(sv));
     sv.sa_handler = afp_dsi_die;
     sigemptyset( &sv.sa_mask );
@@ -132,7 +132,8 @@ static void alarm_handler()
     /* if we're in the midst of processing something,
        don't die. */
     if ((child.flags & CHILD_RUNNING) || (child.tickle++ < child.obj->options.timeout)) {
-        dsi_tickle(child.obj->handle);
+        if (!pollvoltime(child.obj))
+            dsi_tickle(child.obj->handle);
     } else { /* didn't receive a tickle. close connection */
         LOG(log_error, logtype_afpd, "afp_alarm: child timed out");
         afp_dsi_die(1);
@@ -235,9 +236,9 @@ void afp_over_dsi(AFPObj *obj)
             if (child.flags & CHILD_DIE)
                 dsi_tickle(dsi);
             continue;
-        } else if (!(child.flags & CHILD_DIE)) /* reset tickle timer */
+        } else if (!(child.flags & CHILD_DIE)) /* reset tickle timer */
             setitimer(ITIMER_REAL, &dsi->timer, NULL);
-
+        }
         switch(cmd) {
         case DSIFUNC_CLOSE:
             afp_dsi_close(obj);
index 1d22608a0729382b4b38b3d1b339a491b6f05564..365fca87cbea7cb08bd95481cbe38be824480e6b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: afs.c,v 1.12 2002-10-05 14:04:47 didg Exp $
+ * $Id: afs.c,v 1.13 2002-10-11 14:18:24 didg Exp $
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
  */
@@ -78,7 +78,7 @@ int           ibuflen, *rbuflen;
     struct ViceIoctl   vi;
     struct vol         *vol;
     struct dir         *dir;
-    char               *path;
+    struct path                *path;
     u_int32_t          did;
     u_int16_t          vid;
 
@@ -101,7 +101,7 @@ int         ibuflen, *rbuflen;
         *rbuflen = 0;
         return( AFPERR_NOOBJ );
     }
-    if ( *path != '\0' ) {
+    if ( *path->m_name != '\0' ) {
         *rbuflen = 0;
         return( AFPERR_BITMAP );
     }
@@ -168,7 +168,8 @@ int         ibuflen, *rbuflen;
     struct ViceIoctl   vi;
     struct vol         *vol;
     struct dir         *dir;
-    char               *path, *iend;
+    char               *iend;
+    struct path                *path;
     u_int32_t          did;
     u_int16_t          vid;
 
@@ -193,7 +194,7 @@ int         ibuflen, *rbuflen;
         *rbuflen = 0;
         return( AFPERR_NOOBJ );
     }
-    if ( *path != '\0' ) {
+    if ( *path->m_name != '\0' ) {
         *rbuflen = 0;
         return( AFPERR_BITMAP );
     }
index 1902776463d3d5256e62e32263372a7b8f579aa5..2e6c0b714f22303c645cbde13144034d7434a217 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: appl.c,v 1.7 2002-10-05 14:04:47 didg Exp $
+ * $Id: appl.c,v 1.8 2002-10-11 14:18:25 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -152,8 +152,8 @@ char        *path;
     strncpy( p, path, strlen( path ));
 
     while ( dir->d_parent != NULL ) {
-        p -= strlen( dir->d_name ) + 1;
-        strcpy( p, dir->d_name );
+        p -= strlen( dir->d_m_name ) + 1;
+        strcpy( p, dir->d_m_name );
         dir = dir->d_parent;
     }
     return( p );
@@ -170,7 +170,8 @@ int         ibuflen, *rbuflen;
     int                        tfd, cc;
     u_int32_t           did;
     u_int16_t          vid, mplen;
-    char               *path, *dtf, *p, *mp;
+    struct path         *path;
+    char                *dtf, *p, *mp;
     u_char             creator[ 4 ];
     u_char             appltag[ 4 ];
     char               *mpath, *tempfile;
@@ -199,7 +200,7 @@ int         ibuflen, *rbuflen;
     if (( path = cname( vol, dir, &ibuf )) == NULL ) {
         return( AFPERR_NOOBJ );
     }
-    if ( *path == '\0' ) {
+    if ( *path->m_name == '\0' ) {
         return( AFPERR_BADTYPE );
     }
 
@@ -216,7 +217,7 @@ int         ibuflen, *rbuflen;
         return( AFPERR_PARAM );
     }
     mpath = obj->newtmp;
-    mp = makemacpath( mpath, AFPOBJ_TMPSIZ, curdir, path );
+    mp = makemacpath( mpath, AFPOBJ_TMPSIZ, curdir, path->m_name );
     mplen =  mpath + AFPOBJ_TMPSIZ - mp;
 
     /* write the new appl entry at start of temporary file */
@@ -256,7 +257,8 @@ int         ibuflen, *rbuflen;
     int                        tfd, cc;
     u_int32_t           did;
     u_int16_t          vid, mplen;
-    char               *path, *dtf, *mp;
+    struct path        *path;
+    char                *dtf, *mp;
     u_char             creator[ 4 ];
     char                *tempfile, *mpath;
 
@@ -281,7 +283,7 @@ int         ibuflen, *rbuflen;
     if (( path = cname( vol, dir, &ibuf )) == NULL ) {
         return( AFPERR_NOOBJ );
     }
-    if ( *path == '.' ) {
+    if ( *path->m_name == '\0' ) {
         return( AFPERR_BADTYPE );
     }
 
@@ -298,7 +300,7 @@ int         ibuflen, *rbuflen;
         return( AFPERR_PARAM );
     }
     mpath = obj->newtmp;
-    mp = makemacpath( mpath, AFPOBJ_TMPSIZ, curdir, path );
+    mp = makemacpath( mpath, AFPOBJ_TMPSIZ, curdir, path->m_name );
     mplen =  mpath + AFPOBJ_TMPSIZ - mp;
     cc = copyapplfile( sa.sdt_fd, tfd, mp, mplen );
     close( tfd );
@@ -320,7 +322,6 @@ AFPObj      *obj;
 char   *ibuf, *rbuf;
 int            ibuflen, *rbuflen;
 {
-    struct stat                st;
     struct vol         *vol;
     char               *p, *q;
     int                        cc, buflen;
@@ -328,7 +329,8 @@ int         ibuflen, *rbuflen;
     u_char             creator[ 4 ];
     u_char             appltag[ 4 ];
     char                *buf, *cbuf;
-
+    struct path         *path;
+    
     ibuf += 2;
 
     memcpy( &vid, ibuf, sizeof( vid ));
@@ -434,17 +436,17 @@ int               ibuflen, *rbuflen;
     memcpy( q, p, len );
     q = cbuf;
 
-    if (( p = cname( vol, vol->v_dir, &q )) == NULL ) {
+    if (( path = cname( vol, vol->v_dir, &q )) == NULL ) {
         *rbuflen = 0;
         return( AFPERR_NOITEM );
     }
 
-    if ( stat( mtoupath(vol, p), &st ) < 0 ) {
+    if ( *path->m_name == '\0' || path->st_errno ) {
         *rbuflen = 0;
         return( AFPERR_NOITEM );
     }
     buflen = *rbuflen - sizeof( bitmap ) - sizeof( appltag );
-    if ( getfilparams(vol, bitmap, p, curdir, &st, rbuf + sizeof( bitmap ) +
+    if ( getfilparams(vol, bitmap, path, curdir, rbuf + sizeof( bitmap ) +
                       sizeof( appltag ), &buflen ) != AFP_OK ) {
         *rbuflen = 0;
         return( AFPERR_BITMAP );
index 7f54d5eca2adfd86ee31bf4931182658ea96e09a..2f9eda74dfca391f95574b4e587c81bb0e60bc33 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: auth.c,v 1.29 2002-09-26 00:02:47 didg Exp $
+ * $Id: auth.c,v 1.30 2002-10-11 14:18:25 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -49,6 +49,8 @@ extern void afp_get_cmdline( int *ac, char ***av );
 #include "switch.h"
 #include "status.h"
 
+#include "fork.h"
+
 int    afp_version = 11;
 static int afp_version_index;
 
@@ -73,7 +75,11 @@ static struct afp_versions   afp_versions[] = {
             { "AFPVersion 1.1",        11 },
             { "AFPVersion 2.0",        20 },
             { "AFPVersion 2.1",        21 },
-            { "AFP2.2",        22 }
+            { "AFP2.2",        22 },
+#ifdef AFP3x
+            { "AFP3.0", 30 },
+            { "AFP3.1", 31 }
+#endif            
         };
 
 static struct uam_mod uam_modules = {NULL, NULL, &uam_modules, &uam_modules};
@@ -286,6 +292,20 @@ static int login(AFPObj *obj, struct passwd *pwd, void (*logout)(void))
         uuid = pwd->pw_uid;
 
     afp_switch = postauth_switch;
+    switch (afp_version) {
+    case 31:
+       uam_afpserver_action(AFP_ENUMERATE_EXT2, UAM_AFPSERVER_POSTAUTH, afp_enumerate_ext2, NULL); 
+    case 30:
+       uam_afpserver_action(AFP_BYTELOCK_EXT,  UAM_AFPSERVER_POSTAUTH, afp_bytelock_ext, NULL); 
+        /* enumerate_ext and catsearch_ext are using the same packet as no ext calls */
+#ifdef WITH_CATSEARCH
+       uam_afpserver_action(AFP_CATSEARCH_EXT, UAM_AFPSERVER_POSTAUTH, afp_catsearch, NULL); 
+#endif
+       uam_afpserver_action(AFP_ENUMERATE_EXT, UAM_AFPSERVER_POSTAUTH, afp_enumerate, NULL); 
+       uam_afpserver_action(AFP_READ_EXT,      UAM_AFPSERVER_POSTAUTH, afp_read_ext, NULL); 
+       uam_afpserver_action(AFP_WRITE_EXT,     UAM_AFPSERVER_POSTAUTH, afp_write_ext, NULL); 
+       break;
+    }
     obj->logout = logout;
 
 #ifdef FORCE_UIDGID
@@ -330,6 +350,10 @@ int                ibuflen, *rbuflen;
     }
     if ( i == num )                            /* An inappropo version */
         return send_reply(obj, AFPERR_BADVERS );
+
+    if (afp_version >= 30 && obj->proto != AFPPROTO_DSI)
+        return send_reply(obj, AFPERR_BADVERS );
+
     ibuf += len;
     ibuflen -= len;
 
@@ -403,7 +427,8 @@ int         ibuflen, *rbuflen;
     char username[MACFILELEN + 1], *start = ibuf;
     struct uam_obj *uam;
     struct passwd *pwd;
-    int len;
+    size_t len;
+    int    ret;
 
     *rbuflen = 0;
     ibuf += 2;
@@ -434,12 +459,12 @@ int               ibuflen, *rbuflen;
 
     /* send it off to the uam. we really don't use ibuflen right now. */
     ibuflen -= (ibuf - start);
-    len = uam->u.uam_changepw(obj, username, pwd, ibuf, ibuflen,
+    ret = uam->u.uam_changepw(obj, username, pwd, ibuf, ibuflen,
                               rbuf, rbuflen);
     LOG(log_info, logtype_afpd, "password change %s.",
-        (len == AFPERR_AUTHCONT) ? "continued" :
-        (len ? "failed" : "succeeded"));
-    return len;
+        (ret == AFPERR_AUTHCONT) ? "continued" :
+        (ret ? "failed" : "succeeded"));
+    return ret;
 }
 
 
index 6b9ef02d48bda296d7d1e8dec19bf77deeb2374f..3f91e7191d2eeb99cf354c9746ae879fe3a22a2a 100644 (file)
@@ -30,6 +30,7 @@
 #include <errno.h>
 #include <syslog.h>
 #include <unistd.h>
+#include <ctype.h>
 
 #if STDC_HEADERS
 #include <string.h>
@@ -108,11 +109,12 @@ struct scrit {
  *
  */
 struct dsitem {
-       char *lname;     /* Long name */
+       char *m_name;    /* Mac name */
+       char *u_name;    /* unix name (== strrchr('/', path)) */
        struct dir *dir; /* Structure describing this directory */
        int pidx;        /* Parent's dsitem structure index. */
        int checked;     /* Have we checked this directory ? */
-       char *path;      /* UNIX path to this directory */
+       char *path;      /* absolute UNIX path to this directory */
 };
  
 
@@ -128,9 +130,10 @@ static int dsidx = 0;           /* First free item index... */
 static struct scrit c1, c2;          /* search criteria */
 
 /* Puts new item onto directory stack. */
-static int addstack(char *lname, struct dir *dir, int pidx)
+static int addstack(char *uname, char *mname, struct dir *dir, int pidx)
 {
        struct dsitem *ds;
+       int           l;
 
        /* check if we have some space on stack... */
        if (dsidx >= dssize) {
@@ -142,14 +145,18 @@ static int addstack(char *lname, struct dir *dir, int pidx)
 
        /* Put new element. Allocate and copy lname and path. */
        ds = dstack + dsidx++;
-       ds->lname = strdup(lname);
+       if (!(ds->m_name = strdup(mname)))
+               return -1;
        ds->dir = dir;
        ds->pidx = pidx;
        if (pidx >= 0) {
-               ds->path = malloc(strlen(dstack[pidx].path) + strlen(ds->lname) + 2);
+               l = strlen(dstack[pidx].path);
+               if (!(ds->path = malloc(l + strlen(uname) + 2) ))
+                       return -1;
                strcpy(ds->path, dstack[pidx].path);
                strcat(ds->path, "/");
-               strcat(ds->path, ds->lname);
+               strcat(ds->path, uname);
+               ds->u_name = ds->path +l +1;
        }
 
        ds->checked = 0;
@@ -170,7 +177,7 @@ static int reducestack()
        while (dsidx > 0) {
                if (dstack[dsidx-1].checked) {
                        dsidx--;
-                       free(dstack[dsidx].lname);
+                       free(dstack[dsidx].m_name);
                        free(dstack[dsidx].path);
                        /* Check if we need to free (or release) dir structures */
                } else
@@ -185,7 +192,7 @@ static void clearstack()
        save_cidx = -1;
        while (dsidx > 0) {
                dsidx--;
-               free(dstack[dsidx].lname);
+               free(dstack[dsidx].m_name);
                free(dstack[dsidx].path);
                /* Check if we need to free (or release) dir structures */
        }
@@ -194,9 +201,8 @@ static void clearstack()
 /* Fills in dir field of dstack[cidx]. Must fill parent dirs' fields if needed... */
 static int resolve_dir(struct vol *vol, int cidx)
 {
-       struct dir *dir, *curdir;
-       struct stat statbuf;
-
+       struct dir *dir, *cdir;
+       
        if (dstack[cidx].dir != NULL)
                return 1;
 
@@ -206,44 +212,49 @@ static int resolve_dir(struct vol *vol, int cidx)
        if (dstack[dstack[cidx].pidx].dir == NULL && resolve_dir(vol, dstack[cidx].pidx) == 0)
               return 0;
 
-       curdir = dstack[dstack[cidx].pidx].dir;
-       dir = curdir->d_child;
+       cdir = dstack[dstack[cidx].pidx].dir;
+       dir = cdir->d_child;
        while (dir) {
-               if (strcmp(dir->d_name, dstack[cidx].lname) == 0)
+               if (strcmp(dir->d_m_name, dstack[cidx].m_name) == 0)
                        break;
-               dir = (dir == curdir->d_child->d_prev) ? NULL : dir->d_next;
+               dir = (dir == cdir->d_child->d_prev) ? NULL : dir->d_next;
        } /* while */
 
-       if (!dir)
-               if (stat(dstack[cidx].path, &statbuf)==-1) {
+       if (!dir) {
+               struct path path;
+
+               path.u_name = dstack[cidx].path;   
+               if (of_stat(&path)==-1) {
                        syslog(LOG_DEBUG, "resolve_dir: stat %s: %s", dstack[cidx].path, strerror(errno));
                        return 0;
                }
-
-       if (!dir && ((dir = adddir(vol, curdir, dstack[cidx].lname, strlen(dstack[cidx].lname),
-                                               dstack[cidx].path, strlen(dstack[cidx].path), &statbuf)) == NULL))
+               path.m_name = dstack[cidx].m_name;
+               path.u_name = dstack[cidx].u_name;   
+               /* adddir works with a filename not absolute pathname */
+               if ((dir = adddir(vol, cdir, &path)) == NULL)
                        return 0;
+       }
        dstack[cidx].dir = dir;
 
        return 1;
 } /* resolve_dir */
 
 /* Looks up for an opened adouble structure, opens resource fork of selected file. */
-static struct adouble *adl_lkup(char *upath, struct stat *sb)
+static struct adouble *adl_lkup(struct path *path)
 {
        static struct adouble ad;
        struct adouble *adp;
        struct ofork *of;
-       int isdir = S_ISDIR(sb->st_mode);
+       int isdir = S_ISDIR(path->st.st_mode);
 
-       if (!isdir && (of = of_findname(upath, sb ))) {
+       if (!isdir && (of = of_findname(path))) {
                adp = of->of_ad;
        } else {
                memset(&ad, 0, sizeof(ad));
                adp = &ad;
        } 
 
-       if ( ad_open( upath, ADFLAGS_HF | (isdir)?ADFLAGS_DIR:0, O_RDONLY, 0, adp) < 0 ) {
+       if ( ad_open( path->u_name, ADFLAGS_HF | (isdir)?ADFLAGS_DIR:0, O_RDONLY, 0, adp) < 0 ) {
                return NULL;
        } 
        return adp;     
@@ -257,18 +268,14 @@ static struct adouble *adl_lkup(char *upath, struct stat *sb)
  * fname - our fname (translated to UNIX)
  * cidx - index in directory stack
  */
-static int crit_check(struct vol *vol, char *uname, char *fname, int cidx) {
+static int crit_check(struct vol *vol, struct path *path, int cidx) {
        int r = 0;
-       struct stat sbuf;
        u_int16_t attr;
-       struct finderinfo *finfo = NULL;
+       struct finderinfo *finfo = NULL, finderinfo;
        struct adouble *adp = NULL;
        time_t c_date, b_date;
 
-       if (stat(uname, &sbuf) < 0)
-               return 0;
-       
-       if (S_ISDIR(sbuf.st_mode)) {
+       if (S_ISDIR(path->st.st_mode)) {
                r = 2;
                if (!c1.dbitmap)
                        return r;
@@ -279,15 +286,16 @@ static int crit_check(struct vol *vol, char *uname, char *fname, int cidx) {
        /* Kind of optimization: 
         * -- first check things we've already have - filename
         * -- last check things we get from ad_open()
+        * FIXME strmcp strstr (icase)
         */
 
        /* Check for filename */
        if (c1.rbitmap & (1<<DIRPBIT_LNAME)) { 
                if (c1.rbitmap & (1<<CATPBIT_PARTIAL)) {
-                       if (strstr(fname, c1.lname) == NULL)
+                       if (strcasestr(path->u_name, c1.lname) == NULL)
                                goto crit_check_ret;
                } else
-                       if (strcmp(fname, c1.lname) != 0)
+                       if (strcasecmp(path->u_name, c1.lname) != 0)
                                goto crit_check_ret;
        } /* if (c1.rbitmap & ... */
 
@@ -302,72 +310,84 @@ static int crit_check(struct vol *vol, char *uname, char *fname, int cidx) {
 
        /* Check for modification date FIXME: should we look at adouble structure ? */
        if ((c1.rbitmap & (1<<DIRPBIT_MDATE))) 
-               if (sbuf.st_mtime < c1.mdate || sbuf.st_mtime > c2.mdate)
+               if (path->st.st_mtime < c1.mdate || path->st.st_mtime > c2.mdate)
                        goto crit_check_ret;
 
        /* Check for creation date... */
        if (c1.rbitmap & (1<<DIRPBIT_CDATE)) {
-               if (adp || (adp = adl_lkup(uname, &sbuf))) {
+               if (adp || (adp = adl_lkup(path))) {
                        if (ad_getdate(adp, AD_DATE_CREATE, (u_int32_t*)&c_date) >= 0)
                                c_date = AD_DATE_TO_UNIX(c_date);
-                       else c_date = sbuf.st_mtime;
-               } else c_date = sbuf.st_mtime;
+                       else c_date = path->st.st_mtime;
+               } else c_date = path->st.st_mtime;
                if (c_date < c1.cdate || c_date > c2.cdate)
                        goto crit_check_ret;
        }
 
        /* Check for backup date... */
        if (c1.rbitmap & (1<<DIRPBIT_BDATE)) {
-               if (adp || (adp == adl_lkup(uname, &sbuf))) {
+               if (adp || (adp == adl_lkup(path))) {
                        if (ad_getdate(adp, AD_DATE_BACKUP, (u_int32_t*)&b_date) >= 0)
                                b_date = AD_DATE_TO_UNIX(b_date);
-                       else b_date = sbuf.st_mtime;
-               } else b_date = sbuf.st_mtime;
+                       else b_date = path->st.st_mtime;
+               } else b_date = path->st.st_mtime;
                if (b_date < c1.bdate || b_date > c2.bdate)
                        goto crit_check_ret;
        }
                                
        /* Check attributes */
-       if ((c1.rbitmap & (1<<DIRPBIT_ATTR)) && c2.attr != 0)
-               if (adp || (adp = adl_lkup(uname, &sbuf))) {
+       if ((c1.rbitmap & (1<<DIRPBIT_ATTR)) && c2.attr != 0) {
+               if (adp || (adp = adl_lkup(path))) {
                        ad_getattr(adp, &attr);
                        if ((attr & c2.attr) != c1.attr)
                                goto crit_check_ret;
                } else goto crit_check_ret;
-               
+       }               
 
         /* Check file type ID */
-       if ((c1.rbitmap & (1<<DIRPBIT_FINFO)) && c2.finfo.f_type != 0)
-               if (adp || (adp = adl_lkup(uname, &sbuf))) {
-                       finfo = (struct finderinfo*)ad_entry(adp, ADEID_FINDERI);
-                       if (finfo->f_type != c1.finfo.f_type)
-                               goto crit_check_ret;
-               } else goto crit_check_ret;
-
-       /* Check creator ID */
-       if ((c1.rbitmap & (1<<DIRPBIT_FINFO)) && c2.finfo.creator != 0)
-               if (adp || (adp = adl_lkup(uname, &sbuf))) {
-                       finfo = (struct finderinfo*)ad_entry(adp, ADEID_FINDERI);
-                       if (finfo->creator != c1.finfo.creator)
-                               goto crit_check_ret;
-               } else goto crit_check_ret;
+       if ((c1.rbitmap & (1<<DIRPBIT_FINFO)) && c2.finfo.f_type != 0) {
+               if (!adp)
+                       adp = adl_lkup(path);
+               finfo = get_finderinfo(path->m_name, adp, &finderinfo);
+               if (finfo->f_type != c1.finfo.f_type)
+                       goto crit_check_ret;
+       }
        
+       /* Check creator ID */
+       if ((c1.rbitmap & (1<<DIRPBIT_FINFO)) && c2.finfo.creator != 0) {
+               if (!finfo) {
+                       if (!adp)
+                               adp = adl_lkup(path);
+                       finfo = get_finderinfo(path->m_name, adp, &finderinfo);
+               }
+               if (finfo->creator != c1.finfo.creator)
+                       goto crit_check_ret;
+       }
+               
        /* Check finder info attributes */
-       if ((c1.rbitmap & (1<<DIRPBIT_FINFO)) && c2.finfo.attrs != 0)
-               if (adp || (adp = adl_lkup(uname, &sbuf))) {
+       if ((c1.rbitmap & (1<<DIRPBIT_FINFO)) && c2.finfo.attrs != 0) {
+               u_int8_t attrs = 0;
+
+               if (adp || (adp = adl_lkup(path))) {
                        finfo = (struct finderinfo*)ad_entry(adp, ADEID_FINDERI);
-                       if ((finfo->attrs & c2.finfo.attrs) != c1.finfo.attrs)
-                               goto crit_check_ret;
-               } else goto crit_check_ret;
+                       attrs = finfo->attrs;
+               }
+               else if (*path->u_name == '.') {
+                       attrs = htons(FINDERINFO_INVISIBLE);
+               }
 
+               if ((attrs & c2.finfo.attrs) != c1.finfo.attrs)
+                       goto crit_check_ret;
+       }
+       
        /* Check label */
-       if ((c1.rbitmap & (1<<DIRPBIT_FINFO)) && c2.finfo.label != 0)
-               if (adp || (adp = adl_lkup(uname, &sbuf))) {
+       if ((c1.rbitmap & (1<<DIRPBIT_FINFO)) && c2.finfo.label != 0) {
+               if (adp || (adp = adl_lkup(path))) {
                        finfo = (struct finderinfo*)ad_entry(adp, ADEID_FINDERI);
                        if ((finfo->label & c2.finfo.label) != c1.finfo.label)
                                goto crit_check_ret;
                } else goto crit_check_ret;
-       
+       }       
        /* FIXME: Attributes check ! */
        
        /* All criteria are met. */
@@ -380,7 +400,7 @@ crit_check_ret:
 
 
 /* Adds an item to resultset. */
-static int rslt_add(struct vol *vol, struct stat *statbuf, char *fname, short cidx, int isdir, char **rbuf)
+static int rslt_add(struct vol *vol, char *fname, short cidx, int isdir, char **rbuf)
 {
        char *p = *rbuf;
        int l = fname != NULL ? strlen(fname) : 0;
@@ -402,7 +422,8 @@ static int rslt_add(struct vol *vol, struct stat *statbuf, char *fname, short ci
        /* Fill offset of returned file name */
        if (fname != NULL) {
                *p++ = 0;
-               *p++ = (int)(p - *rbuf) - 1;
+               *p = (int)(p - *rbuf) - 1;
+               p++;
                p[0] = l;
                strcpy(p+1, fname);
                p += l + 1;
@@ -431,17 +452,17 @@ static int rslt_add(struct vol *vol, struct stat *statbuf, char *fname, short ci
 static int catsearch(struct vol *vol, struct dir *dir,  
                     int rmatches, int *pos, char *rbuf, u_int32_t *nrecs, int *rsize)
 {
-       int cidx, r, i;
+       int cidx, r;
        char *fname = NULL;
        struct dirent *entry;
-       struct stat statbuf;
        int result = AFP_OK;
        int ccr;
+        struct path path;
        char *orig_dir = NULL;
        int orig_dir_len = 128;
-       char *path = vol->v_path;
+       char *vpath = vol->v_path;
        char *rrbuf = rbuf;
-
+        
        if (*pos != 0 && *pos != cur_pos) 
                return AFPERR_CATCHNG;
 
@@ -454,13 +475,13 @@ static int catsearch(struct vol *vol, struct dir *dir,
                if (dirpos != NULL) {
                        closedir(dirpos);
                        dirpos = NULL;
-               } /* if (dirpos != NULL) */
+               } 
                
-               if (addstack("", dir, -1) == -1) {
+               if (addstack("","", dir, -1) == -1) {
                        result = AFPERR_MISC;
                        goto catsearch_end;
                }
-               dstack[0].path = strdup(path);
+               dstack[0].path = strdup(vpath);
                /* FIXME: Sometimes DID is given by klient ! (correct this one above !) */
        }
 
@@ -498,9 +519,12 @@ static int catsearch(struct vol *vol, struct dir *dir,
                chdir(dstack[cidx].path);
                while ((entry=readdir(dirpos)) != NULL) {
                        (*pos)++;
-                       if (veto_file(VETO_STR, entry->d_name))
-                               continue;
-                       if (stat(entry->d_name, &statbuf) != 0) {
+
+                       if (!(fname = path.m_name = check_dirent(vol, entry->d_name)))
+                          continue;
+
+                       path.u_name = entry->d_name;
+                       if (of_stat(&path) != 0) {
                                switch (errno) {
                                case EACCES:
                                case ELOOP:
@@ -514,21 +538,28 @@ static int catsearch(struct vol *vol, struct dir *dir,
                                        result = AFPERR_MISC;
                                        goto catsearch_end;
                                } /* switch (errno) */
-                       } /* if (stat(entry->d_name, &statbuf) != 0) */
-                       fname = utompath(vol, entry->d_name);
+                       } /* if (stat(entry->d_name, &path.st) != 0) */
+#if 0
                        for (i = 0; fname[i] != 0; i++)
                                fname[i] = tolower(fname[i]);
-                       if (strlen(fname) > MACFILELEN) 
-                               continue;
-                       ccr = crit_check(vol, entry->d_name, fname, cidx);
+#endif
+                       ccr = crit_check(vol, &path, cidx);
+                       /* bit 1 means that we have to descend into this directory. */
+                       if ((ccr & 2) && S_ISDIR(path.st.st_mode)) {
+                               if (addstack(entry->d_name, fname, NULL, cidx) == -1) {
+                                       result = AFPERR_MISC;
+                                       goto catsearch_end;
+                               } 
+                       }
+
                        /* bit 0 means that criteria has ben met */
-                       if (ccr & 1) {
-                               r = rslt_add(vol, &statbuf, 
+                       if ((ccr & 1)) {
+                               r = rslt_add(vol,  
                                             (c1.fbitmap&(1<<FILPBIT_LNAME))|(c1.dbitmap&(1<<DIRPBIT_LNAME)) ? 
-                                                utompath(vol, entry->d_name) : NULL,   
+                                                fname : NULL,  
                                             (c1.fbitmap&(1<<FILPBIT_PDID))|(c1.dbitmap&(1<<DIRPBIT_PDID)) ? 
                                                 cidx : -1, 
-                                            S_ISDIR(statbuf.st_mode), &rrbuf); 
+                                            S_ISDIR(path.st.st_mode), &rrbuf); 
                                if (r == 0) {
                                        result = AFPERR_MISC;
                                        goto catsearch_end;
@@ -540,18 +571,10 @@ static int catsearch(struct vol *vol, struct dir *dir,
                                /* Block size limit */
                                if (rrbuf - rbuf >= 448)
                                        goto catsearch_pause;
-
                        } 
-                       /* bit 1 means that we have to descend into this directory. */
-                       if (ccr & 2) {
-                               if (S_ISDIR(statbuf.st_mode))
-                                       if (addstack(entry->d_name, NULL, cidx) == -1) {
-                                               result = AFPERR_MISC;
-                                               goto catsearch_end;
-                                       } /* if (addstack... */
-                       }
                } /* while ((entry=readdir(dirpos)) != NULL) */
-               closedir(dirpos);dirpos = NULL;
+               closedir(dirpos);
+               dirpos = NULL;
                dstack[cidx].checked = 1;
        } /* while (current_idx = reducestack()) != -1) */
 
@@ -581,12 +604,9 @@ int afp_catsearch(AFPObj *obj, char *ibuf, int ibuflen,
     u_int32_t   rmatches, reserved;
     u_int32_t  catpos[4];
     u_int32_t   pdid = 0;
-    char        *lname = NULL;
-    struct dir *dir;
-    int ret, rsize, i = 0;
+    int ret, rsize;
     u_int32_t nrecs = 0;
-    static int nrr = 1;
-    char *spec1, *spec2, *bspec1, *bspec2;
+    unsigned char *spec1, *spec2, *bspec1, *bspec2;
 
     memset(&c1, 0, sizeof(c1));
     memset(&c2, 0, sizeof(c2));
@@ -596,9 +616,10 @@ int afp_catsearch(AFPObj *obj, char *ibuf, int ibuflen,
     ibuf += sizeof(vid);
 
     *rbuflen = 0;
-    if ((vol = getvolbyvid(vid)) == NULL)
+    if ((vol = getvolbyvid(vid)) == NULL) {
         return AFPERR_PARAM;
-
+    }
+    
     memcpy(&rmatches, ibuf, sizeof(rmatches));
     rmatches = ntohl(rmatches);
     ibuf += sizeof(rmatches); 
@@ -622,7 +643,6 @@ int afp_catsearch(AFPObj *obj, char *ibuf, int ibuflen,
     ibuf += sizeof(c1.rbitmap);
 
     if (! (c1.fbitmap || c1.dbitmap)) {
-           *rbuflen = 0;
            return AFPERR_BITMAP;
     }
 
@@ -704,7 +724,7 @@ int afp_catsearch(AFPObj *obj, char *ibuf, int ibuflen,
                /* ressource fork length */
        }
        else {
-               /* error */
+           return AFPERR_BITMAP;  /* error */
        }
     } /* Offspring count/ressource fork length */
 
@@ -713,13 +733,17 @@ int afp_catsearch(AFPObj *obj, char *ibuf, int ibuflen,
         /* Get the long filename */    
        memcpy(c1.lname, bspec1 + spec1[1] + 1, (bspec1 + spec1[1])[0]);
        c1.lname[(bspec1 + spec1[1])[0]]= 0;
+#if 0  
        for (i = 0; c1.lname[i] != 0; i++)
                c1.lname[i] = tolower(c1.lname[i]);
+#endif         
        /* FIXME: do we need it ? It's always null ! */
        memcpy(c2.lname, bspec2 + spec2[1] + 1, (bspec2 + spec2[1])[0]);
        c2.lname[(bspec2 + spec2[1])[0]]= 0;
+#if 0
        for (i = 0; c2.lname[i] != 0; i++)
                c2.lname[i] = tolower(c2.lname[i]);
+#endif
     }
 
 
@@ -728,12 +752,15 @@ int afp_catsearch(AFPObj *obj, char *ibuf, int ibuflen,
     ret = catsearch(vol, vol->v_dir, rmatches, &catpos[0], rbuf+24, &nrecs, &rsize);
     memcpy(rbuf, catpos, sizeof(catpos));
     rbuf += sizeof(catpos);
+
     c1.fbitmap = htons(c1.fbitmap);
     memcpy(rbuf, &c1.fbitmap, sizeof(c1.fbitmap));
     rbuf += sizeof(c1.fbitmap);
+
     c1.dbitmap = htons(c1.dbitmap);
     memcpy(rbuf, &c1.dbitmap, sizeof(c1.dbitmap));
     rbuf += sizeof(c1.dbitmap);
+
     nrecs = htonl(nrecs);
     memcpy(rbuf, &nrecs, sizeof(nrecs));
     rbuf += sizeof(nrecs);
index 325a5563701e8dfa1ee0915390082e60e324c825..230fe718a72acaf9f28b74573bc55e0fb142789b 100644 (file)
@@ -1,7 +1,12 @@
 /*
- * $Id: desktop.c,v 1.18 2002-10-05 14:04:47 didg Exp $
+ * $Id: desktop.c,v 1.19 2002-10-11 14:18:26 didg Exp $
  *
  * See COPYRIGHT.
+ *
+ * bug:
+ * afp_XXXcomment are (the only) functions able to open
+ * a ressource fork when there's no data fork, eg after
+ * it was removed with samba.
  */
 
 #ifdef HAVE_CONFIG_H
@@ -574,7 +579,7 @@ char *dtfile(const struct vol *vol, u_char creator[], char *ext )
 {
     static char        path[ MAXPATHLEN + 1];
     char       *p;
-    int                i;
+    unsigned int i;
 
     strcpy( path, vol->v_path );
     strcat( path, "/.AppleDesktop/" );
@@ -604,18 +609,26 @@ char *dtfile(const struct vol *vol, u_char creator[], char *ext )
     return( path );
 }
 
+/* 
+ * mpath is only a filename 
+*/
 char *mtoupath(const struct vol *vol, char *mpath)
 {
     static char  upath[ MAXPATHLEN + 1];
     char       *m, *u;
     int                 i = 0;
-
+    int          changed = 0;
+    
     if ( *mpath == '\0' ) {
         return( "." );
     }
 
 #ifdef FILE_MANGLING
-    mpath = demangle(vol, mpath);
+    m = demangle(vol, mpath);
+    if (m != mpath) {
+        changed = 1;
+        mpath = m;
+    }
 #endif /* FILE_MANGLING */
 
     m = mpath;
@@ -633,6 +646,7 @@ char *mtoupath(const struct vol *vol, char *mpath)
         if (vol->v_mtoupage && ((*m & 0x80) ||
                                 vol->v_flags & AFPVOL_MAPASCII)) {
             *u = vol->v_mtoupage->map[(unsigned char) *m].value;
+            changed = 1;
             if (!*u && *m) {
                 /* if conversion failed, encode in hex
                  * to prevent silly truncation
@@ -661,6 +675,7 @@ char *mtoupath(const struct vol *vol, char *mpath)
                 *u++ = ':';
                 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
                 *u = hexdig[ *m & 0x0f ];
+                changed = 1;
             } else
                 *u = *m;
         u++;
@@ -673,7 +688,7 @@ char *mtoupath(const struct vol *vol, char *mpath)
     LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
 #endif /* DEBUG */
 
-    return( upath );
+    return( (changed)?upath:mpath );
 }
 
 #define hextoint( c )  ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
@@ -737,7 +752,8 @@ int         ibuflen, *rbuflen;
     struct vol         *vol;
     struct dir         *dir;
     struct ofork        *of;
-    char               *path, *name, *upath;
+    struct path         *path;
+    char                *name, *upath;
     int                        clen;
     u_int32_t           did;
     u_int16_t          vid;
@@ -767,23 +783,29 @@ int               ibuflen, *rbuflen;
 
     clen = (u_char)*ibuf++;
     clen = min( clen, 199 );
-    upath = mtoupath( vol, path );
-    if ((*path == '\0') || !(of = of_findname(upath, NULL))) {
+
+    upath = path->u_name;
+    if (check_access(upath, OPENACC_WR ) < 0) {
+        return AFPERR_ACCESS;
+    }
+
+    if (*path->m_name == '\0' || !(of = of_findname(path))) {
         memset(&ad, 0, sizeof(ad));
         adp = &ad;
     } else
         adp = of->of_ad;
+
     if (ad_open( upath , vol_noadouble(vol) |
-                 (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
+                 (( *path->m_name == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
                  O_RDWR|O_CREAT, 0666, adp) < 0 ) {
         return( AFPERR_ACCESS );
     }
 
-    if ( ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT ) {
-        if ( *path == '\0' ) {
-            name = curdir->d_name;
+    if ( (ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT) ) {
+        if ( *path->m_name == '\0' ) {
+            name = curdir->d_m_name;
         } else {
-            name = path;
+            name = path->m_name;
         }
         ad_setentrylen( adp, ADEID_NAME, strlen( name ));
         memcpy( ad_entry( adp, ADEID_NAME ), name,
@@ -806,6 +828,7 @@ int         ibuflen, *rbuflen;
     struct vol         *vol;
     struct dir         *dir;
     struct ofork        *of;
+    struct path         *s_path;
     char               *path, *upath;
     u_int32_t          did;
     u_int16_t          vid;
@@ -825,13 +848,14 @@ int               ibuflen, *rbuflen;
         return( AFPERR_NOOBJ );
     }
 
-    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
+    if (( s_path = cname( vol, dir, &ibuf )) == NULL ) {
         return( AFPERR_NOOBJ );
     }
 
+    upath = s_path->u_name;
+    path  = s_path->m_name;
 
-    upath = mtoupath( vol, path );
-    if ((*path == '\0') || !(of = of_findname(upath, NULL))) {
+    if (*path == '\0' || !(of = of_findname(s_path))) {
         memset(&ad, 0, sizeof(ad));
         adp = &ad;
     } else
@@ -856,6 +880,8 @@ int         ibuflen, *rbuflen;
             ad_getentrylen( adp, ADEID_COMMENT ));
     *rbuflen = ad_getentrylen( adp, ADEID_COMMENT ) + 1;
     ad_close( adp, ADFLAGS_HF );
+
+    /* return AFPERR_NOITEM if len == 0 ? */
     return( AFP_OK );
 }
 
@@ -868,6 +894,7 @@ int         ibuflen, *rbuflen;
     struct vol         *vol;
     struct dir         *dir;
     struct ofork        *of;
+    struct path         *s_path;
     char               *path, *upath;
     u_int32_t          did;
     u_int16_t          vid;
@@ -887,12 +914,17 @@ int               ibuflen, *rbuflen;
         return( AFPERR_NOOBJ );
     }
 
-    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
+    if (( s_path = cname( vol, dir, &ibuf )) == NULL ) {
         return( AFPERR_NOOBJ );
     }
 
-    upath = mtoupath( vol, path );
-    if ((*path == '\0') || !(of = of_findname(upath, NULL))) {
+    upath = s_path->u_name;
+    path  = s_path->m_name;
+    if (check_access(upath, OPENACC_WR ) < 0) {
+        return AFPERR_ACCESS;
+    }
+
+    if (path == '\0' || !(of = of_findname(s_path))) {
         memset(&ad, 0, sizeof(ad));
         adp = &ad;
     } else
index 3542399fb4253a81873a0fb23a362fb7d99861cd..3843493acb23351b4d74063d1540c1c7ce918a01 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: directory.c,v 1.41 2002-10-05 14:04:47 didg Exp $
+ * $Id: directory.c,v 1.42 2002-10-11 14:18:27 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -63,9 +63,11 @@ struct dir   *curdir;
 
 #define SENTINEL (&sentinel)
 static struct dir sentinel = { SENTINEL, SENTINEL, NULL, DIRTREE_COLOR_BLACK,
-                                 NULL, NULL, NULL, NULL, NULL, 0, 0, NULL };
-static struct dir      rootpar = { SENTINEL, SENTINEL, NULL, 0,
-                                NULL, NULL, NULL, NULL, NULL, 0, 0, NULL };
+                                 NULL, NULL, NULL, NULL, NULL, 0, 0, 
+                                 0, 0, NULL, NULL};
+static struct dir rootpar  = { SENTINEL, SENTINEL, NULL, 0,
+                                 NULL, NULL, NULL, NULL, NULL, 0, 0, 
+                                 0, 0, NULL, NULL};
 
 /* (from IM: Toolbox Essentials)
  * dirFinderInfo (DInfo) fields:
@@ -110,7 +112,7 @@ u_int32_t   did;
     dir = vol->v_root;
     while ( dir != SENTINEL ) {
         if (dir->d_did == did)
-            return dir->d_name ? dir : NULL;
+            return dir->d_m_name ? dir : NULL;
         dir = (dir->d_did > did) ? dir->d_left : dir->d_right;
     }
     return NULL;
@@ -331,8 +333,12 @@ struct dir *dir;
 
     /* i'm not sure if it really helps to delete stuff. */
 #ifndef REMOVE_NODES 
-    free(dir->d_name);
-    dir->d_name = NULL;
+    if (dir->d_u_name != dir->d_m_name) {
+        free(dir->d_u_name);
+    }
+    free(dir->d_m_name);
+    dir->d_m_name = NULL;
+    dir->d_u_name = NULL;
 #else /* ! REMOVE_NODES */
 
     /* go searching for a node with at most one child */
@@ -406,12 +412,17 @@ struct dir        *dir;
         }
 
         /* set the node's d_name */
-        node->d_name = save.d_name;
+        node->d_m_name = save.d_m_name;
+        node->d_u_name = save.d_u_name;
     }
 
     if (node->d_color == DIRTREE_COLOR_BLACK)
         dir_rmrecolor(vol, leaf);
-    free(node->d_name);
+
+    if (node->d_u_name != node->d_m_name) {
+        free(node->d_u_name);
+    }
+    free(node->d_m_name);
     free(node);
 #endif /* ! REMOVE_NODES */
 }
@@ -473,26 +484,24 @@ struct dir *dir;
  * attempt to extend the current dir. tree to include path
  * as a side-effect, movecwd to that point and return the new dir
  */
-
 static struct dir *
             extenddir( vol, dir, path )
-            struct vol *vol;
+struct vol     *vol;
 struct dir     *dir;
-char   *path;
+struct path *path;
 {
     char       *p;
-    struct stat        st;
 
-    p = mtoupath(vol, path );
-    if ( stat( p, &st ) != 0 ) {
+    path->u_name = p = mtoupath(vol, path->m_name );
+    if ( of_stat( path ) != 0 ) {
         return( NULL );
     }
-    if (!S_ISDIR(st.st_mode)) {
+
+    if (!S_ISDIR(path->st.st_mode)) {
         return( NULL );
     }
 
-    if (( dir = adddir( vol, dir, path, strlen( path ), p, strlen(p),
-                        &st)) == NULL ) {
+    if (( dir = adddir( vol, dir, path)) == NULL ) {
         return( NULL );
     }
 
@@ -509,7 +518,8 @@ static int deletedir(char *dir)
     DIR *dp;
     struct dirent      *de;
     struct stat st;
-    int len, err;
+    size_t len;
+    int err;
 
     if ((len = strlen(dir)) > sizeof(path))
         return AFPERR_PARAM;
@@ -582,7 +592,8 @@ static int copydir(char *src, char *dst, int noadouble)
     struct dirent      *de;
     struct stat st;
     struct utimbuf      ut;
-    int slen, dlen, err;
+    size_t slen, dlen;
+    int err;
 
     /* doesn't exist or the path is too long. */
     if (((slen = strlen(src)) > sizeof(spath) - 2) ||
@@ -731,13 +742,18 @@ struct dir        *dir;
     }
 
     if (dir != SENTINEL) {
-        free( dir->d_name );
+        if (dir->d_u_name != dir->d_m_name) {
+            free(dir->d_u_name);
+        }
+        free(dir->d_m_name);
         free( dir );
     }
 }
 
-
-struct dir *dirnew(const int len)
+/* --------------------------------------------
+ * most of the time mac name and unix name are the same 
+*/
+struct dir *dirnew(const char *m_name, const char *u_name)
 {
     struct dir *dir;
 
@@ -745,7 +761,16 @@ struct dir *dirnew(const int len)
     if (!dir)
         return NULL;
 
-    if ((dir->d_name = (char *) malloc(sizeof(char)*len)) == NULL) {
+    if ((dir->d_m_name = strdup(m_name)) == NULL) {
+        free(dir);
+        return NULL;
+    }
+
+    if (m_name == u_name) {
+        dir->d_u_name = dir->d_m_name;
+    }
+    else if ((dir->d_u_name = strdup(u_name)) == NULL) {
+        free(dir->d_m_name);
         free(dir);
         return NULL;
     }
@@ -755,16 +780,36 @@ struct dir *dirnew(const int len)
     return dir;
 }
 
-
-/* XXX: this needs to be changed to handle path types */
-char *
+/* -------------------------------------------------- */
+/* XXX: this needs to be changed to handle path types 
+ return
+ if it's a filename:
+      in extenddir:
+         compute unix name
+         stat the file
+      return mac name
+ if it's a dirname:
+      not in the cache
+          in extenddir
+              compute unix name
+              stat the dir
+      in the cache 
+
+  u_name can be
+  XXXX u_name can be an alias on m_name if the m_name is
+  a valid unix name.
+  
+*/
+struct path *
 cname( vol, dir, cpath )
 const struct vol       *vol;
 struct dir     *dir;
 char   **cpath;
 {
-    struct dir         *cdir;
-    static char                path[ MAXPATHLEN + 1];
+    struct dir            *cdir;
+    static char                   path[ MAXPATHLEN + 1];
+    static struct path ret;
+
     char               *data, *p;
     char        *u;
     int                        extend = 0;
@@ -779,7 +824,9 @@ char        **cpath;
     *cpath += len + 2;
     *path = '\0';
     u = NULL;
-
+    ret.m_name = path;
+    ret.st_errno = 0;
+    ret.st_valid = 0;
     for ( ;; ) {
         if ( len == 0 ) {
             if ( !extend && movecwd( vol, dir ) < 0 ) {
@@ -810,7 +857,10 @@ char       **cpath;
                        strncpy(path, u, olen);
                        path[olen] = '\0';
             }
-            return( path );
+            if (!ret.st_valid || *path == '\0') {
+               ret.u_name = ".";
+            }               
+            return &ret;
         }
 
         if ( *data == '\0' ) {
@@ -821,7 +871,7 @@ char        **cpath;
 
         while ( *data == '\0' && len > 0 ) {
             if ( dir->d_parent == NULL ) {
-                return( NULL );
+                return NULL;
             }
             dir = dir->d_parent;
             data++;
@@ -845,27 +895,13 @@ char      **cpath;
         if (len == 1)
             len--;
 
-#ifdef notdef
-        /*
-         * Dung Nguyen <ntd@adb.fr>
-         *
-         * AFPD cannot handle paths with "::" if the "::" notation is
-         * not at the beginning of the path. The following path will not
-         * be interpreted correctly:
-         *
-         * :a:b:::c: (directory c at the same level as directory a) */
-        if ( len > 0 ) {
-            data++;
-            len--;
-        }
-#endif /* notdef */
         *p = '\0';
 
         if ( p != path ) { /* we got something */
             if ( !extend ) {
                 cdir = dir->d_child;
                 while (cdir) {
-                    if ( strcasecmp( cdir->d_name, path ) == 0 ) {
+                    if ( strcasecmp( cdir->d_m_name, path ) == 0 ) {
                         break;
                     }
                     cdir = (cdir == dir->d_child->d_prev) ? NULL :
@@ -875,25 +911,25 @@ char      **cpath;
                     ++extend;
                     /* if dir == curdir it always succeed,
                        even if curdir is deleted. 
-                       it's not a pb because it will failed in extenddir
+                       it's not a pb because it will fail in extenddir
                     */
                     if ( movecwd( vol, dir ) < 0 ) {
                        /* dir is not valid anymore 
                           we delete dir from the cache and abort.
                        */
                        dir_invalidate(vol, dir);
-                        return( NULL );
+                        return NULL;
                     }
-                    cdir = extenddir( vol, dir, path );
+                    cdir = extenddir( vol, dir, &ret );
                 }
 
             } else {
-                cdir = extenddir( vol, dir, path );
+                cdir = extenddir( vol, dir, &ret );
             }
 
             if ( cdir == NULL ) {
                 if ( len > 0 ) {
-                    return( NULL );
+                    return NULL;
                 }
 
             } else {
@@ -928,7 +964,7 @@ struct dir  *dir;
     *p = '.';
     for ( d = dir; d->d_parent != NULL && d != curdir; d = d->d_parent ) {
         *--p = '/';
-        u = mtoupath(vol, d->d_name );
+        u = d->d_u_name;
         n = strlen( u );
         p -= n;
         strncpy( p, u, n );
@@ -946,25 +982,61 @@ struct dir        *dir;
     return( 0 );
 }
 
+/*
+ * We can't use unix file's perm to support Apple's inherited protection modes.
+ * If we aren't the file's owner we can't change its perms when moving it and smb
+ * nfs,... don't even try.
+*/
+#define AFP_CHECK_ACCESS 
+
+int check_access(char *path, int mode)
+{
+#ifdef AFP_CHECK_ACCESS
+struct maccess ma;
+char *p;
+
+    p = ad_dir(path);
+    if (!p)
+       return -1;
+
+    accessmode(p, &ma, curdir, NULL);
+    if ((mode & OPENACC_WR) && !(ma.ma_user & AR_UWRITE))
+        return -1;
+    if ((mode & OPENACC_RD) && !(ma.ma_user & AR_UREAD))
+        return -1;
+#endif
+    return 0;
+}
+
+/* ------------------------------ 
+   (".", curdir)
+   (name, dir) with curdir:name == dir, from afp_enumerate
+*/
 int getdirparams(const struct vol *vol,
-                 u_int16_t bitmap,
-                 char *upath, struct dir *dir, struct stat *st,
+                 u_int16_t bitmap, struct path *s_path,
+                 struct dir *dir, 
                  char *buf, int *buflen )
 {
     struct maccess     ma;
     struct adouble     ad;
     char               *data, *nameoff = NULL;
-    DIR                        *dp;
-    struct dirent      *de;
-    int                        bit = 0, isad = 1;
+    int                        bit = 0, isad = 0;
     u_int32_t           aint;
     u_int16_t          ashort;
-
-    memset(&ad, 0, sizeof(ad));
-
-    if ( ad_open( upath, ADFLAGS_HF|ADFLAGS_DIR, O_RDONLY,
-                  DIRBITS | 0777, &ad) < 0 ) {
-        isad = 0;
+    int             ret;
+    struct stat *st = &s_path->st;
+    char *upath = s_path->u_name;
+    
+    if ((bitmap & ((1 << DIRPBIT_ATTR)  |
+                  (1 << DIRPBIT_CDATE) |
+                  (1 << DIRPBIT_MDATE) |
+                  (1 << DIRPBIT_BDATE) |
+                  (1 << DIRPBIT_FINFO)))) {
+        memset(&ad, 0, sizeof(ad));
+       if ( !ad_open( upath, ADFLAGS_HF|ADFLAGS_DIR, O_RDONLY,
+                  DIRBITS | 0777, &ad)) {
+            isad = 1;
+        }
     }
 
     data = buf;
@@ -1041,7 +1113,7 @@ int getdirparams(const struct vol *vol,
             break;
 
         case DIRPBIT_LNAME :
-            if (dir->d_name) /* root of parent can have a null name */
+            if (dir->d_m_name) /* root of parent can have a null name */
                 nameoff = data;
             else
                 memset(data, 0, sizeof(u_int16_t));
@@ -1061,25 +1133,13 @@ int getdirparams(const struct vol *vol,
         case DIRPBIT_OFFCNT :
             ashort = 0;
             /* this needs to handle current directory access rights */
-            if ((dp = opendir( upath ))) {
-                while (( de = readdir( dp )) != NULL ) {
-                    if (!strcmp(de->d_name, "..") || !strcmp(de->d_name, "."))
-                        continue;
-
-                    if (!validupath(vol, de->d_name))
-                        continue;
-
-                    /* check for vetoed filenames */
-                    if (veto_file(vol->v_veto, de->d_name))
-                        continue;
-
-                    /* now check against too long a filename */
-                    if (strlen(utompath(vol, de->d_name)) > MACFILELEN)
-                        continue;
-
-                    ashort++;
-                }
-                closedir( dp );
+            if (st->st_ctime == dir->ctime) {
+               ashort = dir->offcnt;
+            }
+            else if ((ret = for_each_dirent(vol, upath, NULL,NULL)) >= 0) {
+                ashort = ret;
+                dir->offcnt = ashort;
+                dir->ctime = st->st_ctime;
             }
             ashort = htons( ashort );
             memcpy( data, &ashort, sizeof( ashort ));
@@ -1133,11 +1193,11 @@ int getdirparams(const struct vol *vol,
         ashort = htons( data - buf );
         memcpy( nameoff, &ashort, sizeof( ashort ));
 
-        if ((aint = strlen( dir->d_name )) > MACFILELEN)
+        if ((aint = strlen( dir->d_m_name )) > MACFILELEN)
             aint = MACFILELEN;
 
         *data++ = aint;
-        memcpy( data, dir->d_name, aint );
+        memcpy( data, dir->d_m_name, aint );
         data += aint;
     }
     if ( isad ) {
@@ -1147,6 +1207,7 @@ int getdirparams(const struct vol *vol,
     return( AFP_OK );
 }
 
+/* ----------------------------- */
 int afp_setdirparams(obj, ibuf, ibuflen, rbuf, rbuflen )
 AFPObj      *obj;
 char   *ibuf, *rbuf;
@@ -1154,7 +1215,7 @@ int               ibuflen, *rbuflen;
 {
     struct vol *vol;
     struct dir *dir;
-    char       *path;
+    struct path *path;
     u_int16_t  vid, bitmap;
     u_int32_t   did;
     int                rc;
@@ -1186,7 +1247,7 @@ int               ibuflen, *rbuflen;
         return( AFPERR_NOOBJ );
     }
 
-    if ( *path != '\0' ) {
+    if ( *path->m_name != '\0' ) {
         return( AFPERR_BADTYPE ); /* not a directory */
     }
 
@@ -1208,8 +1269,16 @@ int              ibuflen, *rbuflen;
  *
  * assume path == '\0' eg. it's a directory in canonical form
 */
+
+struct path Cur_Path = {
+    "",  /* mac name */
+    ".", /* unix name */
+    0,  /* stat is not set */
+    0,  /* */
+};
+
 int setdirparams(const struct vol *vol, 
-                 char *path, u_int16_t bitmap, char *buf )
+                 struct path *path, u_int16_t bitmap, char *buf )
 {
     struct maccess     ma;
     struct adouble     ad;
@@ -1224,7 +1293,7 @@ int setdirparams(const struct vol *vol,
     int                 change_parent_mdate = 0;
     int                 newdate = 0;
 
-    upath = mtoupath(vol, path);
+    upath = path->u_name;
     memset(&ad, 0, sizeof(ad));
 
     if (ad_open( upath, vol_noadouble(vol)|ADFLAGS_HF|ADFLAGS_DIR,
@@ -1250,8 +1319,8 @@ int setdirparams(const struct vol *vol,
          * to set our name, etc.
          */
         if ( ad_getoflags( &ad, ADFLAGS_HF ) & O_CREAT ) {
-            ad_setentrylen( &ad, ADEID_NAME, strlen( curdir->d_name ));
-            memcpy( ad_entry( &ad, ADEID_NAME ), curdir->d_name,
+            ad_setentrylen( &ad, ADEID_NAME, strlen( curdir->d_m_name ));
+            memcpy( ad_entry( &ad, ADEID_NAME ), curdir->d_m_name,
                     ad_getentrylen( &ad, ADEID_NAME ));
         }
     }
@@ -1500,7 +1569,7 @@ setdirparam_done:
        if (!movecwd(vol, curdir->d_parent)) {
            newdate = AD_DATE_FROM_UNIX(tv.tv_sec);
            bitmap = 1<<DIRPBIT_MDATE;
-           setdirparams(vol, "", bitmap, (char *)&newdate);
+           setdirparams(vol, &Cur_Path, bitmap, (char *)&newdate);
            /* should we reset curdir ?*/
        }
     }
@@ -1514,10 +1583,10 @@ char    *ibuf, *rbuf;
 int            ibuflen, *rbuflen;
 {
     struct adouble     ad;
-    struct stat         st;
     struct vol         *vol;
     struct dir         *dir;
-    char               *path, *upath;
+    char               *upath;
+    struct path         *s_path;
     u_int32_t          did;
     u_int16_t          vid;
 
@@ -1539,20 +1608,21 @@ int             ibuflen, *rbuflen;
         return( AFPERR_NOOBJ );
     }
 
-    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
+    if (( s_path = cname( vol, dir, &ibuf )) == NULL ) {
         switch( errno ) {
         case EACCES:
             return( AFPERR_ACCESS );
-        case EEXIST:                           /* FIXME this on is impossible? */
+        case EEXIST:                           /* FIXME this one is impossible? */
             return( AFPERR_EXIST );
         default:
             return( AFPERR_NOOBJ );
         }
     }
     /* FIXME check done elswhere? cname was able to move curdir to it! */
-       if (*path == '\0')
-               return AFPERR_EXIST;
-    upath = mtoupath(vol, path);
+    if (*s_path->m_name == '\0')
+        return AFPERR_EXIST;
+
+    upath = s_path->u_name;
     {
     int ret;
         if (0 != (ret = check_name(vol, upath))) {
@@ -1578,12 +1648,10 @@ int             ibuflen, *rbuflen;
         }
     }
 
-    if (stat(upath, &st) < 0) {
+    if (of_stat(s_path) < 0) {
         return AFPERR_MISC;
     }
-
-    if ((dir = adddir( vol, curdir, path, strlen( path ), upath,
-                       strlen(upath), &st)) == NULL) {
+    if ((dir = adddir( vol, curdir, s_path)) == NULL) {
         return AFPERR_MISC;
     }
 
@@ -1599,8 +1667,8 @@ int               ibuflen, *rbuflen;
         return( AFPERR_ACCESS );
     }
 
-    ad_setentrylen( &ad, ADEID_NAME, strlen( path ));
-    memcpy( ad_entry( &ad, ADEID_NAME ), path,
+    ad_setentrylen( &ad, ADEID_NAME, strlen( s_path->m_name ));
+    memcpy( ad_entry( &ad, ADEID_NAME ), s_path->m_name,
             ad_getentrylen( &ad, ADEID_NAME ));
     ad_flush( &ad, ADFLAGS_HF );
     ad_close( &ad, ADFLAGS_HF );
@@ -1612,7 +1680,12 @@ createdir_done:
     return( AFP_OK );
 }
 
-
+/*
+ * dst       new unix filename (not a pathname)
+ * newname   new mac name
+ * newparent curdir
+ *
+*/
 int renamedir(src, dst, dir, newparent, newname, noadouble)
 char   *src, *dst, *newname;
 struct dir     *dir, *newparent;
@@ -1622,7 +1695,7 @@ const int noadouble;
     struct dir         *parent;
     char                *buf;
     int                        len, err;
-
+    
     /* existence check moved to afp_moveandrename */
     if ( rename( src, dst ) < 0 ) {
         switch ( errno ) {
@@ -1672,12 +1745,29 @@ const int noadouble;
     ad_close( &ad, ADFLAGS_HF );
 
 renamedir_done:
-    if ((buf = (char *) realloc( dir->d_name, len + 1 )) == NULL ) {
-        LOG(log_error, logtype_afpd, "renamedir: realloc: %s", strerror(errno) );
+    if (dir->d_m_name == dir->d_u_name)
+        dir->d_u_name = NULL;
+
+    if ((buf = (char *) realloc( dir->d_m_name, len + 1 )) == NULL ) {
+        LOG(log_error, logtype_afpd, "renamedir: realloc mac name: %s", strerror(errno) );
+        /* FIXME : fatal ? */
         return AFPERR_MISC;
     }
-    dir->d_name = buf;
-    strcpy( dir->d_name, newname );
+    dir->d_m_name = buf;
+    strcpy( dir->d_m_name, newname );
+
+    if (newname == dst) {
+       free(dir->d_u_name);
+       dir->d_u_name = dir->d_m_name;
+    }
+    else {
+        if ((buf = (char *) realloc( dir->d_u_name, strlen(dst) + 1 )) == NULL ) {
+            LOG(log_error, logtype_afpd, "renamedir: realloc unix name: %s", strerror(errno) );
+            return AFPERR_MISC;
+        }
+        dir->d_u_name = buf;
+        strcpy( dir->d_u_name, dst );
+    }
 
     if (( parent = dir->d_parent ) == NULL ) {
         return( AFP_OK );
@@ -1812,7 +1902,7 @@ int pathlen;
         return( AFPERR_NOOBJ );
     }
 
-    if ( rmdir(mtoupath(vol, fdir->d_name)) < 0 ) {
+    if ( rmdir(fdir->d_u_name) < 0 ) {
         switch ( errno ) {
         case ENOENT :
             return( AFPERR_NOOBJ );
@@ -1937,7 +2027,9 @@ int               ibuflen, *rbuflen;
     return( AFP_OK );
 }
 
-/* variable DID support */
+/* ------------------------------------
+  variable DID support 
+*/
 int afp_closedir(obj, ibuf, ibuflen, rbuf, rbuflen )
 AFPObj      *obj;
 char   *ibuf, *rbuf;
@@ -1974,16 +2066,17 @@ int             ibuflen, *rbuflen;
     return AFP_OK;
 }
 
-/* did creation gets done automatically */
+/* did creation gets done automatically 
+ * there's a pb again with case but move it to cname
+*/
 int afp_opendir(obj, ibuf, ibuflen, rbuf, rbuflen )
 AFPObj      *obj;
 char   *ibuf, *rbuf;
 int            ibuflen, *rbuflen;
 {
     struct vol         *vol;
-    struct dir         *dir, *parentdir;
-    struct stat         st;
-    char               *path, *upath;
+    struct dir         *parentdir;
+    struct path                *path;
     u_int32_t          did;
     u_int16_t          vid;
 
@@ -2013,29 +2106,18 @@ int             ibuflen, *rbuflen;
         }
     }
 
-    /* see if we already have the directory. */
-    upath = mtoupath(vol, path);
-    if ( stat( upath, &st ) < 0 ) {
-        return( AFPERR_NOOBJ );
+    if ( *path->m_name != '\0' ) {
+        return( AFPERR_BADTYPE ); /* not a directory */
     }
 
-    dir = parentdir->d_child;
-    while (dir) {
-        if (strdiacasecmp(dir->d_name, path) == 0) {
-            memcpy(rbuf, &dir->d_did, sizeof(dir->d_did));
-            *rbuflen = sizeof(dir->d_did);
-            return AFP_OK;
-        }
-        dir = (dir == parentdir->d_child->d_prev) ? NULL : dir->d_next;
+    if ( !path->st_valid && of_stat(path ) < 0 ) {
+        return( AFPERR_NOOBJ );
     }
-
-    /* we don't already have a did. add one in. */
-    if ((dir = adddir(vol, parentdir, path, strlen(path),
-                      upath, strlen(upath), &st)) == NULL) {
-        return AFPERR_MISC;
+    if ( path->st_errno ) {
+        return( AFPERR_NOOBJ );
     }
 
-    memcpy(rbuf, &dir->d_did, sizeof(dir->d_did));
-    *rbuflen = sizeof(dir->d_did);
+    memcpy(rbuf, &curdir->d_did, sizeof(curdir->d_did));
+    *rbuflen = sizeof(curdir->d_did);
     return AFP_OK;
 }
index 28dff40d3d6b18f99797e5bc178d3a278dadb02b..8217fd30dc77d3bc21e6662423b9e7449a000c0a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: directory.h,v 1.5 2002-07-15 14:19:09 srittau Exp $
+ * $Id: directory.h,v 1.6 2002-10-11 14:18:28 didg Exp $
  *
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
@@ -30,6 +30,7 @@
 #include <sys/types.h>
 /*#include <sys/stat.h>*/ /* including it here causes some confusion */
 #include <netatalk/endian.h>
+#include <dirent.h>
 
 /* sys/types.h usually snarfs in major/minor macros. if they don't
  * try this file. */
@@ -50,7 +51,21 @@ struct dir {
     void        *d_ofork;            /* oforks using this directory. */
     u_int32_t   d_did;
     int                d_flags;
-    char       *d_name;
+
+    time_t      ctime;                /* inode ctime */
+    int         offcnt;               /* offspring count */
+
+    char       *d_m_name;             /* mac name */
+    char        *d_u_name;            /* unix name */
+};
+
+struct path {
+    char       *m_name;             /* mac name */
+    char        *u_name;            /* unix name */
+
+    int         st_valid;
+    int         st_errno;
+    struct stat st;
 };
 
 /* child addition/removal macros */
@@ -147,25 +162,35 @@ struct maccess {
 #define        AR_UWRITE       (1<<2)
 #define        AR_UOWN         (1<<7)
 
-extern struct dir       *dirnew __P((const int));
+extern struct dir       *dirnew __P((const char *, const char *));
 extern void             dirfree __P((struct dir *));
 extern struct dir      *dirsearch __P((const struct vol *, u_int32_t));
 extern struct dir      *dirlookup __P((const struct vol *, u_int32_t));
-extern struct dir      *adddir __P((struct vol *, struct dir *, char *,
-                                               int, char *, int, struct stat *));
+
+extern struct dir      *adddir __P((struct vol *, struct dir *, 
+                                               struct path *));
+
 extern struct dir       *dirinsert __P((struct vol *, struct dir *));
 extern int              movecwd __P((const struct vol *, struct dir *));
 extern int              deletecurdir __P((const struct vol *, char *, int));
-extern char            *cname __P((const struct vol *, struct dir *,
+extern struct path      *cname __P((const struct vol *, struct dir *,
                              char **));
 extern mode_t           mtoumode __P((struct maccess *));
 extern void             utommode __P((struct stat *, struct maccess *));
-extern int getdirparams __P((const struct vol *, u_int16_t, char *,
-                                 struct dir *, struct stat *, char *, int *));
-extern int setdirparams __P((const struct vol *, char *, u_int16_t, char *));
+extern int getdirparams __P((const struct vol *, u_int16_t, struct path *,
+                                 struct dir *, char *, int *));
+extern int setdirparams __P((const struct vol *, struct path *, u_int16_t, char *));
 extern int renamedir __P((char *, char *, struct dir *,
                               struct dir *, char *, const int));
 
+typedef int (*dir_loop)(struct dirent *, char *, void *);
+
+extern int  for_each_dirent __P((const struct vol *, char *, dir_loop , void *));
+
+extern int  check_access __P((char *name , int mode));
+
+/* from enumerate.c */
+extern char *check_dirent __P((const struct vol *, char *));
 
 /* FP functions */
 extern int     afp_createdir __P((AFPObj *, char *, int, char *, int *));
@@ -176,7 +201,8 @@ extern int  afp_mapid __P((AFPObj *, char *, int, char *, int *));
 extern int     afp_mapname __P((AFPObj *, char *, int, char *, int *));
 
 /* from enumerate.c */
-extern int     afp_enumerate __P((AFPObj *, char *, int, char *, int *));
+extern int     afp_enumerate __P((AFPObj *, char *, unsigned int, char *, unsigned int *));
+extern int     afp_enumerate_ext2 __P((AFPObj *, char *, unsigned int, char *, unsigned int *));
 extern int     afp_catsearch __P((AFPObj *, char *, int, char *, int *));
 
 #endif
index 1fd9d5eee7bb67a7f4065baa547524e1e8a86bfc..66cfaa245c2bcbf2375b852d8ca0d28471f55363 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: enumerate.c,v 1.23 2002-10-05 14:04:47 didg Exp $
+ * $Id: enumerate.c,v 1.24 2002-10-11 14:18:28 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -12,7 +12,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <dirent.h>
 #include <errno.h>
 
 #include <atalk/logger.h>
 #include "volume.h"
 #include "globals.h"
 #include "file.h"
+#include "fork.h"
 #include "filedir.h"
 
 #define min(a,b)       ((a)<(b)?(a):(b))
 
+/* ---------------------------- */
 struct dir *
-            adddir( vol, dir, name, namlen, upath, upathlen, st )
-            struct vol *vol;
+            adddir( vol, dir, path)
+struct vol     *vol;
 struct dir     *dir;
-char   *name, *upath;
-int            namlen, upathlen;
-struct stat *st;
+struct path     *path;
 {
     struct dir *cdir, *edir;
-#if AD_VERSION > AD_VERSION1
-    struct adouble ad;
-#endif /* AD_VERSION > AD_VERSION1 */
-
+    int                upathlen;
+    char        *name;
+    char        *upath;
 #ifndef USE_LASTDID
     struct stat lst, *lstp;
 #endif /* USE_LASTDID */
+    struct stat *st;
 
-    if ((cdir = dirnew(namlen + 1)) == NULL) {
+    upath = path->u_name;
+    name  = path->m_name;    
+    st    = &path->st;
+    upathlen = strlen(upath);
+    if ((cdir = dirnew(name, upath)) == NULL) {
         LOG(log_error, logtype_afpd, "adddir: malloc: %s", strerror(errno) );
         return NULL;
     }
-    strcpy( cdir->d_name, name );
-    cdir->d_name[namlen] = '\0';
 
     cdir->d_did = 0;
 
-#if AD_VERSION > AD_VERSION1
-    /* look in AD v2 header */
-    memset(&ad, 0, sizeof(ad));
-    if (ad_open(upath, ADFLAGS_HF|ADFLAGS_DIR, O_RDONLY, 0, &ad) >= 0) {
-        /* if we can parse the AppleDouble header, retrieve the DID entry into cdir->d_did */
-        memcpy(&cdir->d_did, ad_entry(&ad, ADEID_DID), sizeof(cdir->d_did));
-        ad_close(&ad, ADFLAGS_HF);
-    }
-#endif /* AD_VERSION */
-
 #ifdef CNID_DB
     /* add to cnid db */
     cdir->d_did = cnid_add(vol->v_db, st, dir->d_did, upath,
@@ -102,17 +93,8 @@ struct stat *st;
     }
 
     if ((edir = dirinsert( vol, cdir ))) {
-#ifndef CNID_DB
-        if (edir->d_name) {
-            if (strcmp(edir->d_name, cdir->d_name)) {
-                LOG(log_info, logtype_afpd, "WARNING: DID conflict for '%s' and '%s'. Are these the same file?", edir->d_name, cdir->d_name);
-            }
-            free(cdir->d_name);
-            free(cdir);
-            return edir;
-        }
-#endif /* CNID_DB */
-        edir->d_name = cdir->d_name;
+        edir->d_m_name = cdir->d_m_name;
+        edir->d_u_name = cdir->d_u_name;
         free(cdir);
         cdir = edir;
     }
@@ -122,37 +104,118 @@ struct stat *st;
     dirchildadd(dir, cdir);
     return( cdir );
 }
-
 /*
  * Struct to save directory reading context in. Used to prevent
  * O(n^2) searches on a directory.
  */
 struct savedir {
-    u_short    sd_vid;
-    int                sd_did;
-    int                sd_buflen;
-    char       *sd_buf;
-    char       *sd_last;
-    int                sd_sindex;
+    u_short     sd_vid;
+    u_int32_t   sd_did;
+    int                 sd_buflen;
+    char        *sd_buf;
+    char        *sd_last;
+    unsigned int sd_sindex;
 };
 #define SDBUFBRK       1024
 
-int afp_enumerate(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj      *obj;
-char   *ibuf, *rbuf;
-int            ibuflen, *rbuflen;
+static int enumerate_loop(struct dirent *de, char *mname, void *data)
+{
+    struct savedir *sd = data; 
+    char *start, *end;
+    int  len;
+    
+    end = sd->sd_buf + sd->sd_buflen;
+    len = strlen(de->d_name);
+    *(sd->sd_last)++ = len;
+
+    if ( sd->sd_last + len + 2 > end ) {
+        char *buf;
+
+        start = sd->sd_buf;
+        if (!(buf = realloc( sd->sd_buf, sd->sd_buflen +SDBUFBRK )) ) {
+            LOG(log_error, logtype_afpd, "afp_enumerate: realloc: %s",
+                        strerror(errno) );
+            errno = ENOMEM;
+            return -1;
+        }
+        sd->sd_buf = buf;
+        sd->sd_buflen += SDBUFBRK;
+        sd->sd_last = ( sd->sd_last - start ) + sd->sd_buf;
+        end = sd->sd_buf + sd->sd_buflen;
+    }
+
+    memcpy( sd->sd_last, de->d_name, len + 1 );
+    sd->sd_last += len + 1;
+    return 0;
+}
+
+/* ----------------------------- */
+char *check_dirent(const struct vol *vol, char *name)
+{
+    char *m_name = NULL;
+
+    if (!strcmp(name, "..") || !strcmp(name, "."))
+        return NULL;
+
+    if (!(validupath(vol, name)))
+        return NULL;
+
+    /* check for vetoed filenames */
+    if (veto_file(vol->v_veto, name))
+        return NULL;
+
+    /* now check against too big a file */
+    if (strlen(m_name = utompath(vol, name)) > MACFILELEN)
+        return NULL;
+
+    return m_name;
+}
+
+/* ----------------------------- */
+int 
+for_each_dirent(const struct vol *vol, char *name, dir_loop fn, void *data)
+{
+    DIR             *dp;
+    struct dirent      *de;
+    char            *m_name;
+    int             ret;
+    
+    if (( dp = opendir( name)) == NULL ) {
+        return -1;
+    }
+    ret = 0;
+    for ( de = readdir( dp ); de != NULL; de = readdir( dp )) {
+        if (!(m_name = check_dirent(vol, de->d_name)))
+            continue;
+
+        ret++;
+        if (fn && fn(de,m_name, data) < 0) {
+           closedir(dp);
+           return -1;
+        }
+    }
+    closedir(dp);
+    return ret;
+}
+
+/* ----------------------------- */
+static int enumerate(obj, ibuf, ibuflen, rbuf, rbuflen, is64 )
+AFPObj       *obj;
+char        *ibuf, *rbuf;
+unsigned int ibuflen, *rbuflen;
+int     is64;
 {
-    struct stat                        st;
     static struct savedir      sd = { 0, 0, 0, NULL, NULL, 0 };
     struct vol                 *vol;
     struct dir                 *dir;
-    struct dirent              *de;
-    DIR                                *dp;
     int                                did, ret, esz, len, first = 1;
-    char                       *path, *data, *end, *start;
+    char                        *data, *start;
     u_int16_t                  vid, fbitmap, dbitmap, reqcnt, actcnt = 0;
-    u_int16_t                  sindex, maxsz, sz = 0;
-
+    u_int16_t                  temp16;
+    u_int32_t                  sindex, maxsz, sz = 0;
+    struct path                 *o_path;
+    struct path                 s_path;
+    
     if ( sd.sd_buflen == 0 ) {
         if (( sd.sd_buf = (char *)malloc( SDBUFBRK )) == NULL ) {
             LOG(log_error, logtype_afpd, "afp_enumerate: malloc: %s", strerror(errno) );
@@ -201,20 +264,40 @@ int               ibuflen, *rbuflen;
     reqcnt = ntohs( reqcnt );
     ibuf += sizeof( reqcnt );
 
-    memcpy( &sindex, ibuf, sizeof( sindex ));
-    sindex = ntohs( sindex );
-    ibuf += sizeof( sindex );
-
-    memcpy( &maxsz, ibuf, sizeof( maxsz ));
-    maxsz = ntohs( maxsz );
-    ibuf += sizeof( maxsz );
-
+    if (is64) {
+        memcpy( &sindex, ibuf, sizeof( sindex ));
+        sindex = ntohs( sindex );
+        ibuf += sizeof( sindex );
+    }
+    else {
+        memcpy( &temp16, ibuf, sizeof( temp16 ));
+        sindex = ntohs( temp16 );
+        ibuf += sizeof( temp16 );
+    }
+    
+    if (is64) {
+        memcpy( &maxsz, ibuf, sizeof( maxsz ));
+        maxsz = ntohs( maxsz );
+        ibuf += sizeof( maxsz );
+    }
+    else {
+        memcpy( &temp16, ibuf, sizeof( temp16 ));
+        maxsz = ntohs( temp16 );
+        ibuf += sizeof( temp16 );
+    }
+    
     maxsz = min(maxsz, *rbuflen);
 
-    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
+    if (( o_path = cname( vol, dir, &ibuf )) == NULL) {
         *rbuflen = 0;
         return( AFPERR_NODIR );
     }
+
+    if ( *o_path->m_name != '\0') {
+        *rbuflen = 0;
+        return( AFPERR_BADTYPE );
+    }
+
     data = rbuf + 3 * sizeof( u_int16_t );
     sz = 3 * sizeof( u_int16_t );
 
@@ -225,58 +308,38 @@ int               ibuflen, *rbuflen;
      */
     if ( sindex == 1 || curdir->d_did != sd.sd_did || vid != sd.sd_vid ) {
         sd.sd_last = sd.sd_buf;
-
-        if (( dp = opendir( mtoupath(vol, path ))) == NULL ) {
-            *rbuflen = 0;
-            return (errno == ENOTDIR) ? AFPERR_BADTYPE : AFPERR_NODIR;
+        if ( !o_path->st_valid && stat( ".", &o_path->st ) < 0 ) {
+            switch (errno) {
+            case EACCES:
+               return AFPERR_ACCESS;
+            case ENOTDIR:
+                return AFPERR_BADTYPE;
+            case ENOMEM:
+                return AFPERR_MISC;
+            default:
+                return AFPERR_NODIR;
+            }
         }
-
-        end = sd.sd_buf + sd.sd_buflen;
-        for ( de = readdir( dp ); de != NULL; de = readdir( dp )) {
-            if (!strcmp(de->d_name, "..") || !strcmp(de->d_name, "."))
-                continue;
-
-            if (!(validupath(vol, de->d_name)))
-                continue;
-
-            /* check for vetoed filenames */
-            if (veto_file(vol->v_veto, de->d_name))
-                continue;
-
-            /* now check against too big a file */
-            if (strlen(utompath(vol, de->d_name)) > MACFILELEN)
-                continue;
-
-            len = strlen(de->d_name);
-            *(sd.sd_last)++ = len;
-
-            if ( sd.sd_last + len + 2 > end ) {
-                char *buf;
-
-                start = sd.sd_buf;
-                if ((buf = (char *) realloc( sd.sd_buf, sd.sd_buflen +
-                                             SDBUFBRK )) == NULL ) {
-                    LOG(log_error, logtype_afpd, "afp_enumerate: realloc: %s",
-                        strerror(errno) );
-                    closedir(dp);
-                    *rbuflen = 0;
-                    return AFPERR_MISC;
-                }
-                sd.sd_buf = buf;
-                sd.sd_buflen += SDBUFBRK;
-                sd.sd_last = ( sd.sd_last - start ) + sd.sd_buf;
-                end = sd.sd_buf + sd.sd_buflen;
+        curdir->ctime  = o_path->st.st_ctime; /* play safe */
+        if ((ret = for_each_dirent(vol, ".", enumerate_loop, (void *)&sd)) < 0) {
+            *rbuflen = 0;
+            switch (errno) {
+            case EACCES:
+               return AFPERR_ACCESS;
+            case ENOTDIR:
+                return AFPERR_BADTYPE;
+            case ENOMEM:
+                return AFPERR_MISC;
+            default:
+                return AFPERR_NODIR;
             }
-
-            memcpy( sd.sd_last, de->d_name, len + 1 );
-            sd.sd_last += len + 1;
         }
+        curdir->offcnt = ret;
         *sd.sd_last = 0;
 
         sd.sd_last = sd.sd_buf;
         sd.sd_sindex = 1;
 
-        closedir( dp );
         sd.sd_vid = vid;
         sd.sd_did = did;
     }
@@ -291,7 +354,7 @@ int         ibuflen, *rbuflen;
     while ( sd.sd_sindex < sindex ) {
         len = *(sd.sd_last)++;
         if ( len == 0 ) {
-            sd.sd_did = -1;    /* invalidate sd struct to force re-read */
+            sd.sd_did = 0;     /* invalidate sd struct to force re-read */
             *rbuflen = 0;
             return( AFPERR_NOOBJ );
         }
@@ -319,8 +382,8 @@ int         ibuflen, *rbuflen;
             sd.sd_last += len + 1;
             continue;
         }
-
-        if (stat( sd.sd_last, &st ) < 0 ) {
+        s_path.u_name = sd.sd_last;
+        if (of_stat( &s_path) < 0 ) {
             /*
              * Somebody else plays with the dir, well it can be us with 
             * "Empty Trash..."
@@ -328,7 +391,7 @@ int         ibuflen, *rbuflen;
 
             /* so the next time it won't try to stat it again
              * another solution would be to invalidate the cache with 
-             * sd.sd_did = -1 but if it's not ENOENT error it will start again
+             * sd.sd_did = 0 but if it's not ENOENT error it will start again
              */
             *sd.sd_last = 0;
             sd.sd_last += len + 1;
@@ -340,28 +403,29 @@ int               ibuflen, *rbuflen;
          * inaccurate, since that means /dev/null is a file, /dev/printer
          * is a file, etc.
          */
-        if ( S_ISDIR(st.st_mode)) {
+        if ( S_ISDIR(s_path.st.st_mode)) {
             if ( dbitmap == 0 ) {
                 sd.sd_last += len + 1;
                 continue;
             }
-            path = utompath(vol, sd.sd_last);
             dir = curdir->d_child;
+            s_path.m_name = NULL;
             while (dir) {
-                if ( strcmp( dir->d_name, path ) == 0 ) {
+                if ( strcmp( dir->d_u_name, s_path.u_name ) == 0 ) {
                     break;
                 }
                 dir = (dir == curdir->d_child->d_prev) ? NULL : dir->d_next;
             }
-            if (!dir && ((dir = adddir( vol, curdir, path, strlen( path ),
-                                        sd.sd_last, len, &st)) == NULL)) {
-                *rbuflen = 0;
-                return AFPERR_MISC;
+            if (!dir) {
+                s_path.m_name = utompath(vol, s_path.u_name);
+                if ((dir = adddir( vol, curdir, &s_path)) == NULL) {
+                    *rbuflen = 0;
+                    return AFPERR_MISC;
+                }
             }
 
-
-            if (( ret = getdirparams(vol, dbitmap, sd.sd_last, dir,
-                                     &st, data + 2 * sizeof( u_char ), &esz )) != AFP_OK ) {
+            if (( ret = getdirparams(vol, dbitmap, &s_path, dir,
+                                     data + 2 * sizeof( u_char ), &esz )) != AFP_OK ) {
                 *rbuflen = 0;
                 return( ret );
             }
@@ -371,10 +435,9 @@ int                ibuflen, *rbuflen;
                 sd.sd_last += len + 1;
                 continue;
             }
-
-            if (( ret = getfilparams(vol, fbitmap, utompath(vol, sd.sd_last),
-                                     curdir, &st, data + 2 * sizeof( u_char ), &esz )) !=
-                    AFP_OK ) {
+            s_path.m_name = utompath(vol, s_path.u_name);
+            if (( ret = getfilparams(vol, fbitmap, &s_path, curdir, 
+                                     data + 2 * sizeof( u_char ), &esz )) != AFP_OK ) {
                 *rbuflen = 0;
                 return( ret );
             }
@@ -406,7 +469,7 @@ int         ibuflen, *rbuflen;
 
         sz += esz + 2 * sizeof( u_char );
         *data++ = esz + 2 * sizeof( u_char );
-        *data++ = S_ISDIR(st.st_mode) ? FILDIRBIT_ISDIR : FILDIRBIT_ISFILE;
+        *data++ = S_ISDIR(s_path.st.st_mode) ? FILDIRBIT_ISDIR : FILDIRBIT_ISFILE;
         data += esz;
         actcnt++;
         sd.sd_last += len + 1;
@@ -414,7 +477,7 @@ int         ibuflen, *rbuflen;
 
     if ( actcnt == 0 ) {
         *rbuflen = 0;
-        sd.sd_did = -1;                /* invalidate sd struct to force re-read */
+        sd.sd_did = 0;         /* invalidate sd struct to force re-read */
         return( AFPERR_NOOBJ );
     }
     sd.sd_sindex = sindex + actcnt;
@@ -435,4 +498,21 @@ int                ibuflen, *rbuflen;
     return( AFP_OK );
 }
 
+/* ----------------------------- */
+int afp_enumerate(obj, ibuf, ibuflen, rbuf, rbuflen )
+AFPObj       *obj;
+char        *ibuf, *rbuf;
+unsigned int ibuflen, *rbuflen;
+{
+    return enumerate(obj, ibuf,ibuflen ,rbuf,rbuflen , 0);
+}
+
+/* ----------------------------- */
+int afp_enumerate_ext2(obj, ibuf, ibuflen, rbuf, rbuflen )
+AFPObj       *obj;
+char        *ibuf, *rbuf;
+unsigned int ibuflen, *rbuflen;
+{
+    return enumerate(obj, ibuf,ibuflen ,rbuf,rbuflen , 1);
+}
 
index 9f8ca89a74f8cbc27d0a4bc4934b0b1b2fdbd342..938dadc548f0149c3939c14ef8efec6289153df4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: file.c,v 1.62 2002-10-05 14:04:47 didg Exp $
+ * $Id: file.c,v 1.63 2002-10-11 14:18:29 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -85,6 +85,37 @@ const u_char ufinderi[] = {
                               0, 0, 0, 0, 0, 0, 0, 0
                           };
 
+/* FIXME mpath : unix or mac name ? (for now it's mac name ) */
+void *get_finderinfo(const char *mpath, struct adouble *adp, void *data)
+{
+    struct extmap      *em;
+
+    if (adp) {
+        memcpy(data, ad_entry(adp, ADEID_FINDERI), 32);
+    }
+    else {
+        memcpy(data, ufinderi, 32);
+    }
+
+    if ((!adp  || !memcmp(ad_entry(adp, ADEID_FINDERI),ufinderi , 8 )) 
+               && (em = getextmap( mpath ))
+    ) {
+        memcpy(data, em->em_type, sizeof( em->em_type ));
+        memcpy(data + 4, em->em_creator, sizeof(em->em_creator));
+    }
+    return data;
+}
+
+#define PARAM_NEED_ADP(b) ((b) & ((1 << FILPBIT_ATTR)  |\
+                                 (1 << FILPBIT_CDATE) |\
+                                 (1 << FILPBIT_MDATE) |\
+                                 (1 << FILPBIT_BDATE) |\
+                                 (1 << FILPBIT_FINFO) |\
+                                 (1 << FILPBIT_RFLEN) |\
+                                 (1 << FILPBIT_EXTRFLEN) |\
+                                 (1 << FILPBIT_PDINFO)))
+
+
 int getmetadata(struct vol *vol,
                  u_int16_t bitmap,
                  char *path, struct dir *dir, struct stat *st,
@@ -93,14 +124,11 @@ int getmetadata(struct vol *vol,
 #ifndef USE_LASTDID
     struct stat                lst, *lstp;
 #endif /* USE_LASTDID */
-    struct stat                hst;
-    struct extmap      *em;
     char               *data, *nameoff = NULL, *upath;
     int                        bit = 0;
     u_int32_t          aint;
     u_int16_t          ashort;
     u_char              achar, fdType[4];
-    struct maccess     ma;
 
 #ifdef DEBUG
     LOG(log_info, logtype_afpd, "begin getmetadata:");
@@ -126,6 +154,7 @@ int getmetadata(struct vol *vol,
 #if 0
             /* FIXME do we want a visual clue if the file is read only
              */
+            struct maccess     ma;
             accessmode( ".", &ma, dir , NULL);
             if ((ma.ma_user & AR_UWRITE)) {
                accessmode( upath, &ma, dir , st);
@@ -172,22 +201,14 @@ int getmetadata(struct vol *vol,
             break;
 
         case FILPBIT_FINFO :
-            if (adp)
-                memcpy(data, ad_entry(adp, ADEID_FINDERI), 32);
-            else {
-                memcpy(data, ufinderi, 32);
+           get_finderinfo(path, adp, (char *)data);
+            if (!adp) {
                 if (*upath == '.') { /* make it invisible */
                     ashort = htons(FINDERINFO_INVISIBLE);
                     memcpy(data + FINDERINFO_FRFLAGOFF, &ashort, sizeof(ashort));
                 }
             }
 
-            if ((!adp  || !memcmp(ad_entry(adp, ADEID_FINDERI),ufinderi , 8 )) 
-               && (em = getextmap( path ))
-            ) {
-                memcpy(data, em->em_type, sizeof( em->em_type ));
-                memcpy(data + 4, em->em_creator, sizeof(em->em_creator));
-            }
             data += 32;
             break;
 
@@ -267,14 +288,20 @@ int getmetadata(struct vol *vol,
             break;
 
         case FILPBIT_DFLEN :
-            aint = htonl( st->st_size );
+            if  (st->st_size > 0xffffffff)
+               aint = 0xffffffff;
+            else
+               aint = htonl( st->st_size );
             memcpy(data, &aint, sizeof( aint ));
             data += sizeof( aint );
             break;
 
         case FILPBIT_RFLEN :
             if ( adp ) {
-                aint = htonl( ad_getentrylen( adp, ADEID_RFORK ));
+                if (adp->ad_rlen > 0xffffffff)
+                    aint = 0xffffffff;
+                else
+                    aint = htonl( adp->ad_rlen);
             } else {
                 aint = 0;
             }
@@ -329,7 +356,25 @@ int getmetadata(struct vol *vol,
             memset(data, 0, sizeof( ashort ));
             data += sizeof( ashort );
             break;
-
+        case FILPBIT_EXTDFLEN:
+            aint = htonl(st->st_size >> 32);
+            memcpy(data, &aint, sizeof( aint ));
+            data += sizeof( aint );
+            aint = htonl(st->st_size);
+            memcpy(data, &aint, sizeof( aint ));
+            data += sizeof( aint );
+            break;
+        case FILPBIT_EXTRFLEN:
+            aint = 0;
+            if (adp) 
+                aint = htonl(adp->ad_rlen >> 32);
+            memcpy(data, &aint, sizeof( aint ));
+            data += sizeof( aint );
+            if (adp) 
+                aint = htonl(adp->ad_rlen);
+            memcpy(data, &aint, sizeof( aint ));
+            data += sizeof( aint );
+            break;
         default :
             return( AFPERR_BITMAP );
         }
@@ -352,49 +397,52 @@ int getmetadata(struct vol *vol,
 /* ----------------------- */
 int getfilparams(struct vol *vol,
                  u_int16_t bitmap,
-                 char *path, struct dir *dir, struct stat *st,
+                 struct path *path, struct dir *dir, 
                  char *buf, int *buflen )
 {
     struct adouble     ad, *adp;
     struct ofork        *of;
     char                   *upath;
     u_int16_t          attrbits = 0;
+    int                 opened = 0;
     int rc;    
+
 #ifdef DEBUG
-    LOG(log_info, logtype_afpd, "begin getfilparams:");
+    LOG(log_info, logtype_default, "begin getfilparams:");
 #endif /* DEBUG */
 
-    upath = mtoupath(vol, path);
-    if ((of = of_findname(upath, st))) {
-        adp = of->of_ad;
-       attrbits = ((of->of_ad->ad_df.adf_refcount > 0) ? ATTRBIT_DOPEN : 0);
-       attrbits |= ((of->of_ad->ad_hf.adf_refcount > of->of_ad->ad_df.adf_refcount)? ATTRBIT_ROPEN : 0);
-
-    } else {
-        memset(&ad, 0, sizeof(ad));
-        adp = &ad;
-    }
+    opened = PARAM_NEED_ADP(bitmap);
+    adp = NULL;
+    if (opened) {
+        upath = path->u_name;
+        if ((of = of_findname(path))) {
+            adp = of->of_ad;
+           attrbits = ((of->of_ad->ad_df.adf_refcount > 0) ? ATTRBIT_DOPEN : 0);
+           attrbits |= ((of->of_ad->ad_hf.adf_refcount > of->of_ad->ad_df.adf_refcount)? ATTRBIT_ROPEN : 0);
+        } else {
+            memset(&ad, 0, sizeof(ad));
+            adp = &ad;
+        }
 
-    if ( ad_open( upath, ADFLAGS_HF, O_RDONLY, 0, adp) < 0 ) {
-        adp = NULL;
-    }
-    else {
-#if 0
-       /* FIXME 
-          we need to check if the file is open by another process.
-          it's slow so we only do it if we have to:
-          - bitmap is requested.
-          - we don't already have the answer!
-       */
-       if ((bitmap & (1 << FILPBIT_ATTR))) {
-               if (!(attrbits & ATTRBIT_ROPEN)) {
-               }
-               if (!(attrbits & ATTRBIT_DOPEN)) {
-               }
+        if ( ad_open( upath, ADFLAGS_HF, O_RDONLY, 0, adp) < 0 ) {
+             adp = NULL;
+        }
+        else {
+           /* FIXME 
+              we need to check if the file is open by another process.
+              it's slow so we only do it if we have to:
+              - bitmap is requested.
+              - we don't already have the answer!
+           */
+           if ((bitmap & (1 << FILPBIT_ATTR))) {
+                if (!(attrbits & ATTRBIT_ROPEN)) {
+                }
+                if (!(attrbits & ATTRBIT_DOPEN)) {
+                }
+           }
        }
-#endif         
     }
-    rc = getmetadata(vol, bitmap, path, dir, st, buf, buflen, adp, attrbits);
+    rc = getmetadata(vol, bitmap, path->m_name, dir, &path->st, buf, buflen, adp, attrbits);
     if ( adp ) {
         ad_close( adp, ADFLAGS_HF );
     }
@@ -411,7 +459,7 @@ AFPObj      *obj;
 char   *ibuf, *rbuf;
 int            ibuflen, *rbuflen;
 {
-    struct stat         st;
+    struct stat         *st;
     struct adouble     ad, *adp;
     struct vol         *vol;
     struct dir         *dir;
@@ -420,6 +468,8 @@ int         ibuflen, *rbuflen;
     int                        creatf, did, openf, retvalue = AFP_OK;
     u_int16_t          vid;
     int                 ret;
+    struct path                *s_path;
+    
 #ifdef DEBUG
     LOG(log_info, logtype_afpd, "begin afp_createfile:");
 #endif /* DEBUG */
@@ -445,17 +495,20 @@ int               ibuflen, *rbuflen;
         return( AFPERR_NOOBJ );
     }
 
-    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
+    if (( s_path = cname( vol, dir, &ibuf )) == NULL ) {
         return( AFPERR_NOOBJ );
     }
 
-    upath = mtoupath(vol, path);
+    if ( *s_path->m_name == '\0' ) {
+        return( AFPERR_BADTYPE );
+    }
+
+    upath = s_path->u_name;
     if (0 != (ret = check_name(vol, upath))) 
        return  ret;
-
-    ret = stat(upath, &st);
+    
     /* if upath is deleted we already in trouble anyway */
-    if (!ret && (of = of_findname(upath, &st))) {
+    if ((of = of_findname(s_path))) {
         adp = of->of_ad;
     } else {
         memset(&ad, 0, sizeof(ad));
@@ -463,7 +516,7 @@ int         ibuflen, *rbuflen;
     }
     if ( creatf) {
         /* on a hard create, fail if file exists and is open */
-        if (!ret && of)
+        if (of)
             return AFPERR_BUSY;
         openf = O_RDWR|O_CREAT|O_TRUNC;
     } else {
@@ -485,14 +538,15 @@ int               ibuflen, *rbuflen;
             return( AFPERR_ACCESS );
         case ENOENT:
             /* on noadouble volumes, just creating the data fork is ok */
-            if (vol_noadouble(vol) && (stat(upath, &st) == 0))
+            st = &s_path->st;
+            if (vol_noadouble(vol) && (stat(upath, st) == 0))
                 goto createfile_done;
             /* fallthrough */
         default :
             return( AFPERR_PARAM );
         }
     }
-
+    path = s_path->m_name;
     ad_setentrylen( adp, ADEID_NAME, strlen( path ));
     memcpy(ad_entry( adp, ADEID_NAME ), path,
            ad_getentrylen( adp, ADEID_NAME ));
@@ -523,7 +577,7 @@ int         ibuflen, *rbuflen;
 {
     struct vol *vol;
     struct dir *dir;
-    char       *path;
+    struct path *s_path;
     int                did, rc;
     u_int16_t  vid, bitmap;
 
@@ -553,11 +607,11 @@ int               ibuflen, *rbuflen;
     bitmap = ntohs( bitmap );
     ibuf += sizeof( bitmap );
 
-    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
+    if (( s_path = cname( vol, dir, &ibuf )) == NULL ) {
         return( AFPERR_NOOBJ );
     }
 
-    if ( *path == '\0' ) {
+    if ( *s_path->m_name == '\0' ) {
         return( AFPERR_BADTYPE ); /* it's a directory */
     }
 
@@ -565,7 +619,7 @@ int         ibuflen, *rbuflen;
         ibuf++;
     }
 
-    if (( rc = setfilparams(vol, path, bitmap, ibuf )) == AFP_OK ) {
+    if (( rc = setfilparams(vol, s_path, bitmap, ibuf )) == AFP_OK ) {
         setvoltime(obj, vol );
     }
 
@@ -580,9 +634,10 @@ int                ibuflen, *rbuflen;
  * cf AFP3.0.pdf page 252 for change_mdate and change_parent_mdate logic  
  *
 */
+extern struct path Cur_Path;
 
 int setfilparams(struct vol *vol,
-                 char *path, u_int16_t bitmap, char *buf )
+                 struct path *path, u_int16_t bitmap, char *buf )
 {
     struct adouble     ad, *adp;
     struct ofork        *of;
@@ -604,8 +659,8 @@ int setfilparams(struct vol *vol,
     LOG(log_info, logtype_afpd, "begin setfilparams:");
 #endif /* DEBUG */
 
-    upath = mtoupath(vol, path);
-    if ((of = of_findname(upath, NULL))) {
+    upath = path->u_name;
+    if ((of = of_findname(path))) {
         adp = of->of_ad;
     } else {
         memset(&ad, 0, sizeof(ad));
@@ -624,8 +679,8 @@ int setfilparams(struct vol *vol,
         }
         isad = 0;
     } else if ((ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT) ) {
-        ad_setentrylen( adp, ADEID_NAME, strlen( path ));
-        memcpy(ad_entry( adp, ADEID_NAME ), path,
+        ad_setentrylen( adp, ADEID_NAME, strlen( path->m_name ));
+        memcpy(ad_entry( adp, ADEID_NAME ), path->m_name,
                ad_getentrylen( adp, ADEID_NAME ));
     }
 
@@ -675,7 +730,7 @@ int setfilparams(struct vol *vol,
 
             if (!memcmp( ad_entry( adp, ADEID_FINDERI ), ufinderi, 8 )
                     && ( 
-                     ((em = getextmap( path )) &&
+                     ((em = getextmap( path->m_name )) &&
                       !memcmp(buf, em->em_type, sizeof( em->em_type )) &&
                       !memcmp(buf + 4, em->em_creator,sizeof( em->em_creator)))
                      || ((em = getdefextmap()) &&
@@ -761,7 +816,7 @@ setfilparam_done:
     if (change_parent_mdate && gettimeofday(&tv, NULL) == 0) {
         newdate = AD_DATE_FROM_UNIX(tv.tv_sec);
         bitmap = 1<<FILPBIT_MDATE;
-        setdirparams(vol, "", bitmap, (char *)&newdate);
+        setdirparams(vol, &Cur_Path, bitmap, (char *)&newdate);
     }
 
 #ifdef DEBUG
@@ -875,6 +930,8 @@ rename_retry:
     return( AFP_OK );
 }
 
+/* -----------------------------------
+*/
 int afp_copyfile(obj, ibuf, ibuflen, rbuf, rbuflen )
 AFPObj      *obj;
 char   *ibuf, *rbuf;
@@ -882,9 +939,11 @@ int                ibuflen, *rbuflen;
 {
     struct vol *vol;
     struct dir *dir;
-    char       *newname, *path, *p, *upath;
+    char       *newname, *p, *upath;
+    struct path *s_path;
     u_int32_t  sdid, ddid;
-    int                plen, err, retvalue = AFP_OK;
+    size_t      plen;
+    int         err, retvalue = AFP_OK;
     u_int16_t  svid, dvid;
 
 #ifdef DEBUG
@@ -911,10 +970,10 @@ int               ibuflen, *rbuflen;
     memcpy(&ddid, ibuf, sizeof( ddid ));
     ibuf += sizeof( ddid );
 
-    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
+    if (( s_path = cname( vol, dir, &ibuf )) == NULL ) {
         return( AFPERR_NOOBJ );
     }
-    if ( *path == '\0' ) {
+    if ( *s_path->m_name == '\0' ) {
         return( AFPERR_BADTYPE );
     }
 
@@ -925,10 +984,9 @@ int                ibuflen, *rbuflen;
      *      we just balk if the file is opened already. */
 
     newname = obj->newtmp;
-    strcpy( newname, path );
+    strcpy( newname, s_path->m_name );
 
-    upath = mtoupath(vol, newname );
-    if (of_findname(upath, NULL))
+    if (of_findname(s_path))
         return AFPERR_DENYCONF;
 
     p = ctoupath( vol, curdir, newname );
@@ -946,10 +1004,10 @@ int              ibuflen, *rbuflen;
         return( AFPERR_PARAM );
     }
 
-    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
+    if (( s_path = cname( vol, dir, &ibuf )) == NULL ) {
         return( AFPERR_NOOBJ );
     }
-    if ( *path != '\0' ) {
+    if ( *s_path->m_name != '\0' ) {
         return( AFPERR_BADTYPE ); /* not a directory. AFPERR_PARAM? */
     }
 
@@ -1029,7 +1087,9 @@ char      *src, *dst, *newname;
 const int   noadouble;
 {
     struct adouble     ad;
+#ifdef SENDFILE_FLAVOR_LINUX
     struct stat         st;
+#endif
     char               filebuf[8192];
     int                        sfd, dfd, len, err = AFP_OK;
     ssize_t             cc;
@@ -1356,7 +1416,7 @@ delete_unlock:
     return err;
 }
 
-
+/* ------------------------------------ */
 #ifdef CNID_DB
 /* return a file id */
 int afp_createid(obj, ibuf, ibuflen, rbuf, rbuflen )
@@ -1364,14 +1424,17 @@ AFPObj      *obj;
 char   *ibuf, *rbuf;
 int            ibuflen, *rbuflen;
 {
-    struct stat         st;
+    struct stat         *st;
+#if AD_VERSION > AD_VERSION1
     struct adouble     ad;
+#endif
     struct vol         *vol;
     struct dir         *dir;
-    char               *path, *upath;
+    char               *upath;
     int                 len;
     cnid_t             did, id;
     u_short            vid;
+    struct path         *s_path;
 
 #ifdef DEBUG
     LOG(log_info, logtype_afpd, "begin afp_createid:");
@@ -1397,17 +1460,18 @@ int             ibuflen, *rbuflen;
         return( AFPERR_PARAM );
     }
 
-    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
+    if (( s_path = cname( vol, dir, &ibuf )) == NULL ) {
         return( AFPERR_PARAM );
     }
 
-    if ( *path == '\0' ) {
+    if ( *s_path->m_name == '\0' ) {
         return( AFPERR_BADTYPE );
     }
 
-    upath = mtoupath(vol, path);
-    if (stat(upath, &st) < 0) {
-        switch (errno) {
+    upath = s_path->u_name;
+    switch (s_path->st_errno) {
+        case 0:
+             break; /* success */
         case EPERM:
         case EACCES:
             return AFPERR_ACCESS;
@@ -1415,10 +1479,9 @@ int              ibuflen, *rbuflen;
             return AFPERR_NOOBJ;
         default:
             return AFPERR_PARAM;
-        }
     }
-
-    if (id = cnid_lookup(vol->v_db, &st, did, upath, len = strlen(upath))) {
+    st = &s_path->st;
+    if ((id = cnid_lookup(vol->v_db, st, did, upath, len = strlen(upath)))) {
         memcpy(rbuf, &id, sizeof(id));
         *rbuflen = sizeof(id);
         return AFPERR_EXISTID;
@@ -1432,7 +1495,7 @@ int               ibuflen, *rbuflen;
     }
 #endif /* AD_VERSION > AD_VERSION1 */
 
-    if (id = cnid_add(vol->v_db, &st, did, upath, len, id) != CNID_INVALID) {
+    if ((id = cnid_add(vol->v_db, st, did, upath, len, id)) != CNID_INVALID) {
         memcpy(rbuf, &id, sizeof(id));
         *rbuflen = sizeof(id);
         return AFP_OK;
@@ -1456,16 +1519,17 @@ int             ibuflen, *rbuflen;
     }
 }
 
-/* resolve a file id */
+/* ------------------------------
+   resolve a file id */
 int afp_resolveid(obj, ibuf, ibuflen, rbuf, rbuflen )
 AFPObj      *obj;
 char   *ibuf, *rbuf;
 int            ibuflen, *rbuflen;
 {
-    struct stat         st;
     struct vol         *vol;
     struct dir         *dir;
     char               *upath;
+    struct path         path;
     int                 err, buflen;
     cnid_t             id;
     u_int16_t          vid, bitmap;
@@ -1497,8 +1561,8 @@ int               ibuflen, *rbuflen;
     if (( dir = dirlookup( vol, id )) == NULL ) {
         return AFPERR_NOID; /* idem AFPERR_PARAM */
     }
-
-    if ((movecwd(vol, dir) < 0) || (stat(upath, &st) < 0)) {
+    path.u_name = upath;
+    if (movecwd(vol, dir) < 0 || of_stat(&path) < 0) {
         switch (errno) {
         case EACCES:
         case EPERM:
@@ -1509,18 +1573,17 @@ int             ibuflen, *rbuflen;
             return AFPERR_PARAM;
         }
     }
-
     /* directories are bad */
-    if (S_ISDIR(st.st_mode))
+    if (S_ISDIR(path.st.st_mode))
         return AFPERR_BADTYPE;
 
     memcpy(&bitmap, ibuf, sizeof(bitmap));
     bitmap = ntohs( bitmap );
-
-    if ((err = getfilparams(vol, bitmap, utompath(vol, upath), curdir, &st,
-                            rbuf + sizeof(bitmap), &buflen)) != AFP_OK)
+    path.m_name = utompath(vol, upath);
+    if ((err = getfilparams(vol, bitmap, &path , curdir, 
+                            rbuf + sizeof(bitmap), &buflen)) != AFP_OK) {
         return err;
-
+    }
     *rbuflen = buflen + sizeof(bitmap);
     memcpy(rbuf, ibuf, sizeof(bitmap));
 
@@ -1531,6 +1594,7 @@ int               ibuflen, *rbuflen;
     return AFP_OK;
 }
 
+/* ------------------------------ */
 int afp_deleteid(obj, ibuf, ibuflen, rbuf, rbuflen )
 AFPObj      *obj;
 char   *ibuf, *rbuf;
@@ -1625,8 +1689,9 @@ int               ibuflen, *rbuflen;
     struct stat         srcst, destst;
     struct vol         *vol;
     struct dir         *dir, *sdir;
-    char               *spath, temp[17], *path, *p;
+    char               *spath, temp[17], *p;
     char                *supath, *upath;
+    struct path         *path;
     int                 err;
     struct adouble     ads;
     struct adouble     add;
@@ -1673,13 +1738,14 @@ int             ibuflen, *rbuflen;
         return( AFPERR_PARAM );
     }
 
-    if ( *path == '\0' ) {
+    if ( *path->m_name == '\0' ) {
         return( AFPERR_BADTYPE );   /* it's a dir */
     }
 
-    upath = mtoupath(vol, path);
-    if (stat(upath, &srcst) < 0) {
-        switch (errno) {
+    upath = path->u_name;
+    switch (path->st_errno) {
+        case 0:
+             break;
         case ENOENT:
             return AFPERR_NOID;
         case EPERM:
@@ -1687,21 +1753,21 @@ int             ibuflen, *rbuflen;
             return AFPERR_ACCESS;
         default:
             return AFPERR_PARAM;
-        }
     }
     memset(&ads, 0, sizeof(ads));
     adsp = &ads;
-    if ((s_of = of_findname(upath, &srcst))) {
+    if ((s_of = of_findname(path))) {
             /* reuse struct adouble so it won't break locks */
             adsp = s_of->of_ad;
     }
+    memcpy(&srcst, &path->st, sizeof(struct stat));
     /* save some stuff */
     sdir = curdir;
     spath = obj->oldtmp;
     supath = obj->newtmp;
-    strcpy(spath, path);
+    strcpy(spath, path->m_name);
     strcpy(supath, upath); /* this is for the cnid changing */
-    p = ctoupath( vol, sdir, spath);
+    p = absupath( vol, sdir, upath);
 
     /* look for the source cnid. if it doesn't exist, don't worry about
      * it. */
@@ -1718,18 +1784,19 @@ int             ibuflen, *rbuflen;
         return( AFPERR_PARAM );
     }
 
-    if ( *path == '\0' ) {
+    if ( *path->m_name == '\0' ) {
         return( AFPERR_BADTYPE );
     }
 
     /* FPExchangeFiles is the only call that can return the SameObj
      * error */
-    if ((curdir == sdir) && strcmp(spath, path) == 0)
+    if ((curdir == sdir) && strcmp(spath, path->m_name) == 0)
         return AFPERR_SAMEOBJ;
+    memcpy(&srcst, &path->st, sizeof(struct stat));
 
-    upath = mtoupath(vol, path);
-    if (stat(upath, &destst) < 0) {
-        switch (errno) {
+    switch (errno) {
+        case 0:
+             break;
         case ENOENT:
             return AFPERR_NOID;
         case EPERM:
@@ -1737,20 +1804,21 @@ int             ibuflen, *rbuflen;
             return AFPERR_ACCESS;
         default:
             return AFPERR_PARAM;
-        }
     }
     memset(&add, 0, sizeof(add));
     addp = &add;
-    if ((d_of = of_findname( upath, &destst))) {
+    if ((d_of = of_findname( path))) {
             /* reuse struct adouble so it won't break locks */
             addp = d_of->of_ad;
     }
+    memcpy(&destst, &path->st, sizeof(struct stat));
 
     /* they are not on the same device and at least one is open
     */
     if ((d_of || s_of)  && srcst.st_dev != destst.st_dev)
         return AFPERR_MISC;
     
+    upath = path->u_name;
 #ifdef CNID_DB
     /* look for destination id. */
     did = cnid_lookup(vol->v_db, &destst, curdir->d_did, upath,
@@ -1772,12 +1840,12 @@ int             ibuflen, *rbuflen;
     /* rename destination to source */
     if ((err = renamefile(upath, p, spath, vol_noadouble(vol), addp)) < 0)
         goto err_src_to_tmp;
-    of_rename(vol, d_of, curdir, path, sdir, spath);
+    of_rename(vol, d_of, curdir, path->m_name, sdir, spath);
 
     /* rename temp to destination */
-    if ((err = renamefile(temp, upath, path, vol_noadouble(vol), adsp)) < 0)
+    if ((err = renamefile(temp, upath, path->m_name, vol_noadouble(vol), adsp)) < 0)
         goto err_dest_to_src;
-    of_rename(vol, s_of, curdir, temp, curdir, path);
+    of_rename(vol, s_of, curdir, temp, curdir, path->m_name);
 
 #ifdef CNID_DB
     /* id's need switching. src -> dest and dest -> src. */
@@ -1829,8 +1897,8 @@ err_temp_to_dest:
 
 err_dest_to_src:
     /* rename source back to dest */
-    renamefile(p, upath, path, vol_noadouble(vol), addp);
-    of_rename(vol, d_of, sdir, spath, curdir, path);
+    renamefile(p, upath, path->m_name, vol_noadouble(vol), addp);
+    of_rename(vol, d_of, sdir, spath, curdir, path->m_name);
 
 err_src_to_tmp:
     /* rename temp back to source */
index 84049e9ab1539841dd0156fa2dcedea683a4a4fd..60a39b0319e519f839522d6e78f6324232f58c30 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: file.h,v 1.11 2002-10-09 18:46:31 didg Exp $
+ * $Id: file.h,v 1.12 2002-10-11 14:18:31 didg Exp $
  *
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
@@ -76,14 +76,16 @@ struct extmap {
 extern struct extmap   *getextmap __P((const char *));
 extern struct extmap   *getdefextmap __P((void));
 
-extern int getfilparams __P((struct vol *, u_int16_t, char *,
-                                 struct dir *, struct stat *, char *buf,
-                                 int *));
-extern int setfilparams __P((struct vol *, char *, u_int16_t, char *));
+extern int getfilparams __P((struct vol *, u_int16_t, struct path *,
+                                 struct dir *, char *buf, int *));
+
+extern int setfilparams __P((struct vol *, struct path *, u_int16_t, char *));
 extern int renamefile   __P((char *, char *, char *, const int, struct adouble *));
 extern int copyfile     __P((char *, char *, char *, const int));
 extern int deletefile   __P((char *, int));
 
+extern void *get_finderinfo __P((const char *, struct adouble *, void *));
+
 /* FP functions */
 extern int      afp_exchangefiles __P((AFPObj *, char *, int, char *, int *));
 extern int     afp_setfilparams __P((AFPObj *, char *, int, char *, int *));
index 48278fcfc12ed6c3b7751c36580c7deec2814dae..3913b9e809fea7a765ec6e6d65d118024285226e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: filedir.c,v 1.32 2002-10-05 14:04:47 didg Exp $
+ * $Id: filedir.c,v 1.33 2002-10-11 14:18:31 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -54,6 +54,7 @@ char *strchr (), *strrchr ();
 #include "file.h"
 #include "globals.h"
 #include "filedir.h"
+#include "unix.h"
 
 int matchfile2dirperms(upath, vol, did)
 /* Since it's kinda' big; I decided against an
@@ -68,7 +69,7 @@ more information */
     struct stat        st, sb;
     struct dir *dir;
     char       *adpath;
-    int                uid;
+    uid_t       uid;
     int         ret = AFP_OK;
 #ifdef DEBUG
     LOG(log_info, logtype_afpd, "begin matchfile2dirperms:");
@@ -88,8 +89,8 @@ more information */
     else if (stat(".", &sb) < 0) {
         LOG(log_error, logtype_afpd,
             "matchfile2dirperms: Error checking directory \"%s\": %s",
-            dir->d_name, strerror(errno));
-        ret AFPERR_NOOBJ;
+            dir->d_m_name, strerror(errno));
+        ret AFPERR_NOOBJ;
     }
     else {
         uid=geteuid();
@@ -140,13 +141,13 @@ AFPObj      *obj;
 char   *ibuf, *rbuf;
 int            ibuflen, *rbuflen;
 {
-    struct stat                st;
+    struct stat                *st;
     struct vol         *vol;
     struct dir         *dir;
     u_int32_t           did;
     int                        buflen, ret;
-    char               *path;
     u_int16_t          fbitmap, dbitmap, vid;
+    struct path         *s_path;
 
 #ifdef DEBUG
     LOG(log_info, logtype_afpd, "begin afp_getfildirparams:");
@@ -175,26 +176,33 @@ int               ibuflen, *rbuflen;
     dbitmap = ntohs( dbitmap );
     ibuf += sizeof( dbitmap );
 
-    if (( path = cname( vol, dir, &ibuf )) == NULL) {
+    if (( s_path = cname( vol, dir, &ibuf )) == NULL) {
         return( AFPERR_NOOBJ );
     }
 
-    if ( stat( mtoupath(vol, path ), &st ) < 0 ) {
+    st   = &s_path->st;
+    if (!s_path->st_valid) {
+        /* it's a dir and it should be there
+         * because we chdir in it in cname
+         */
+        of_stat(s_path);
+    }
+    if ( s_path->st_errno != 0 ) {
         return( AFPERR_NOOBJ );
     }
 
     buflen = 0;
-    if (S_ISDIR(st.st_mode)) {
+    if (S_ISDIR(st->st_mode)) {
         if (dbitmap) {
-            ret = getdirparams(vol, dbitmap, ".", curdir,
-                               &st, rbuf + 3 * sizeof( u_int16_t ), &buflen );
+            ret = getdirparams(vol, dbitmap, s_path, curdir,
+                                 rbuf + 3 * sizeof( u_int16_t ), &buflen );
             if (ret != AFP_OK )
                 return( ret );
         }
         /* this is a directory */
         *(rbuf + 2 * sizeof( u_int16_t )) = (char) FILDIRBIT_ISDIR;
     } else {
-        if (fbitmap && ( ret = getfilparams(vol, fbitmap, path, curdir, &st,
+        if (fbitmap && ( ret = getfilparams(vol, fbitmap, s_path, curdir, 
                                             rbuf + 3 * sizeof( u_int16_t ), &buflen )) != AFP_OK ) {
             return( ret );
         }
@@ -217,41 +225,15 @@ int               ibuflen, *rbuflen;
     return( AFP_OK );
 }
 
-/*
- * We can't use unix file's perm to support Apple's inherited protection modes.
- * If we aren't the file's owner we can't change its perms when moving it and smb
- * nfs,... don't even try.
-*/
-#define AFP_CHECK_ACCESS 
-
-int check_access(char *path, int mode)
-{
-#ifdef AFP_CHECK_ACCESS
-struct maccess ma;
-char *p;
-
-    p = ad_dir(path);
-    if (!p)
-       return -1;
-
-    accessmode(p, &ma, curdir, NULL);
-    if ((mode & OPENACC_WR) && !(ma.ma_user & AR_UWRITE))
-        return -1;
-    if ((mode & OPENACC_RD) && !(ma.ma_user & AR_UREAD))
-        return -1;
-#endif
-    return 0;
-}
-
 int afp_setfildirparams(obj, ibuf, ibuflen, rbuf, rbuflen )
 AFPObj      *obj;
 char   *ibuf, *rbuf;
 int            ibuflen, *rbuflen;
 {
-    struct stat        st;
+    struct stat        *st;
     struct vol *vol;
     struct dir *dir;
-    char       *path;
+    struct path *path;
     u_int16_t  vid, bitmap;
     int                did, rc;
 
@@ -286,10 +268,17 @@ int               ibuflen, *rbuflen;
         return( AFPERR_NOOBJ );
     }
 
-    if ( stat( mtoupath(vol, path ), &st ) < 0 ) {
-        return( AFPERR_NOOBJ );
+    st   = &path->st;
+    if (!path->st_valid) {
+        /* it's a dir and it should be there
+         * because we chdir in it in cname
+         */
+        of_stat(path);
     }
 
+    if ( path->st_errno != 0 ) {
+        return( AFPERR_NOOBJ );
+    }
     /*
      * If ibuf is odd, make it even.
      */
@@ -297,7 +286,7 @@ int         ibuflen, *rbuflen;
         ibuf++;
     }
 
-    if (S_ISDIR(st.st_mode)) {
+    if (S_ISDIR(st->st_mode)) {
         rc = setdirparams(vol, path, bitmap, ibuf );
     } else {
         rc = setfilparams(vol, path, bitmap, ibuf );
@@ -349,12 +338,12 @@ int         isdir;
     char            *p;
     char            *upath;
     int             rc;
-    struct stat     st;
+    struct stat     *st;
     int             adflags;
     struct adouble     ad;
     struct adouble     *adp;
-    struct ofork       *opened;
-
+    struct ofork       *opened = NULL;
+    struct path         path;
 #ifdef CNID_DB
     cnid_t      id;
 #endif /* CNID_DB */
@@ -369,7 +358,9 @@ int         isdir;
         id = cnid_get(vol->v_db, sdir->d_did, p, strlen(p));
 #endif /* CNID_DB */
         p = ctoupath( vol, sdir, oldname );
-        if ((opened = of_findname(p, NULL))) {
+        path.st_valid = 0;
+        path.u_name = p;
+        if ((opened = of_findname(&path))) {
             /* reuse struct adouble so it won't break locks */
             adp = opened->of_ad;
         }
@@ -397,6 +388,8 @@ int         isdir;
     }
 
     upath = mtoupath(vol, newname);
+    path.u_name = upath;
+    st = &path.st;    
     if (0 != (rc = check_name(vol, upath))) {
             return  rc;
     }
@@ -407,14 +400,16 @@ int         isdir;
             return AFP_OK;
 
         /* deal with case insensitive, case-preserving filesystems. */
-        if ((stat(upath, &st) == 0) && strdiacasecmp(oldname, newname))
+        if ((stat(upath, st) == 0) && strdiacasecmp(oldname, newname))
             return AFPERR_EXIST;
 
-    } else if (stat(upath, &st ) == 0)
+    } else if (stat(upath, st ) == 0)
         return AFPERR_EXIST;
 
     if ( !isdir ) {
-        if (of_findname(upath, &st)) {
+        path.st_valid = 1;
+        path.st_errno = errno;
+        if (of_findname(&path)) {
             rc = AFPERR_EXIST; /* was AFPERR_BUSY; */
         } else {
             rc = renamefile( p, upath, newname,vol_noadouble(vol), adp );
@@ -427,11 +422,11 @@ int         isdir;
     if ( rc == AFP_OK ) {
 #ifdef CNID_DB
         /* renaming may have moved the file/dir across a filesystem */
-        if (stat(upath, &st) < 0)
+        if (stat(upath, st) < 0)
             return AFPERR_MISC;
 
         /* fix up the catalog entry */
-        cnid_update(vol->v_db, id, &st, curdir->d_did, upath, strlen(upath));
+        cnid_update(vol->v_db, id, st, curdir->d_did, upath, strlen(upath));
 #endif /* CNID_DB */
     }
 
@@ -446,9 +441,10 @@ int                ibuflen, *rbuflen;
 {
     struct vol *vol;
     struct dir *sdir;
-    char               *path, *oldname, *newname;
+    char        *oldname, *newname;
+    struct path *path;
     u_int32_t  did;
-    int                        plen;
+    size_t      plen;
     u_int16_t  vid;
     int         isdir = 0;
     int         rc;
@@ -482,8 +478,8 @@ int         ibuflen, *rbuflen;
     sdir = curdir;
     newname = obj->newtmp;
     oldname = obj->oldtmp;
-    if ( *path != '\0' ) {
-        strcpy(oldname, path); /* an extra copy for of_rename */
+    if ( *path->m_name != '\0' ) {
+        strcpy(oldname, path->m_name); /* an extra copy for of_rename */
     }
     else {
         if ( sdir->d_parent == NULL ) { /* root directory */
@@ -494,7 +490,7 @@ int         ibuflen, *rbuflen;
             return( AFPERR_NOOBJ );
         }
         isdir = 1;
-        strcpy(oldname, sdir->d_name);
+        strcpy(oldname, sdir->d_m_name);
     }
 
     /* another place where we know about the path type */
@@ -534,7 +530,8 @@ int         ibuflen, *rbuflen;
 {
     struct vol         *vol;
     struct dir         *dir;
-    char               *path, *upath;
+    struct path         *s_path;
+    char               *upath;
     int                        did, rc;
     u_int16_t          vid;
 
@@ -560,14 +557,14 @@ int               ibuflen, *rbuflen;
         return( AFPERR_NOOBJ );
     }
 
-    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
+    if (( s_path = cname( vol, dir, &ibuf )) == NULL ) {
         return( AFPERR_NOOBJ );
     }
 
-    upath = mtoupath(vol, path );
-    if ( *path == '\0' ) {
+    upath = s_path->u_name;
+    if ( *s_path->m_name == '\0' ) {
         rc = deletecurdir( vol, obj->oldtmp, AFPOBJ_TMPSIZ);
-    } else if (of_findname(upath, NULL)) {
+    } else if (of_findname(s_path)) {
         rc = AFPERR_BUSY;
     } else if ((rc = deletefile( upath, 1)) == AFP_OK) {
 #ifdef CNID_DB /* get rid of entry */
@@ -585,26 +582,24 @@ int               ibuflen, *rbuflen;
 
     return( rc );
 }
-
-char *ctoupath( vol, dir, name )
+char *absupath( vol, dir, u )
 const struct vol       *vol;
 struct dir     *dir;
-char   *name;
+char   *u;
 {
     struct dir *d;
     static char        path[ MAXPATHLEN + 1];
-    char       *p, *u;
+    char       *p;
     int                len;
 
     p = path + sizeof( path ) - 1;
     *p = '\0';
-    u = mtoupath(vol, name );
     len = strlen( u );
     p -= len;
     strncpy( p, u, len );
     for ( d = dir; d->d_parent; d = d->d_parent ) {
         *--p = '/';
-        u = mtoupath(vol, d->d_name );
+        u = d->d_u_name;
         len = strlen( u );
         p -= len;
         strncpy( p, u, len );
@@ -617,6 +612,14 @@ char       *name;
     return( p );
 }
 
+char *ctoupath( vol, dir, name )
+const struct vol       *vol;
+struct dir     *dir;
+char   *name;
+{
+    return absupath(vol, dir, mtoupath(vol, name));
+}
+
 /* ------------------------- */
 int afp_moveandrename(obj, ibuf, ibuflen, rbuf, rbuflen )
 AFPObj      *obj;
@@ -626,10 +629,10 @@ int               ibuflen, *rbuflen;
     struct vol *vol;
     struct dir *sdir, *ddir;
     int         isdir = 0;
-    char           *oldname, *newname;
-    char        *path;
+    char       *oldname, *newname;
+    struct path *path;
     int                did;
-    int                plen;
+    size_t      plen;
     u_int16_t  vid;
     int         rc;
 #ifdef DROPKLUDGE
@@ -670,12 +673,12 @@ int               ibuflen, *rbuflen;
     sdir = curdir;
     newname = obj->newtmp;
     oldname = obj->oldtmp;
-    if ( *path != '\0' ) {
+    if ( *path->m_name != '\0' ) {
         /* not a directory */
-        strcpy(oldname, path); /* an extra copy for of_rename */
+        strcpy(oldname, path->m_name); /* an extra copy for of_rename */
     } else {
         isdir = 1;
-        strcpy(oldname, sdir->d_name);
+        strcpy(oldname, sdir->d_m_name);
     }
 
     /* get the destination directory */
@@ -685,7 +688,7 @@ int         ibuflen, *rbuflen;
     if (( path = cname( vol, ddir, &ibuf )) == NULL ) {
         return( AFPERR_NOOBJ );
     }
-    if ( *path != '\0' ) {
+    if ( *path->m_name != '\0' ) {
         return( AFPERR_BADTYPE );
     }
 
@@ -711,7 +714,7 @@ int         ibuflen, *rbuflen;
         char *upath = mtoupath(vol, newname);
 #ifdef DROPKLUDGE
         if (vol->v_flags & AFPVOL_DROPBOX) {
-            if (retvalue=matchfile2dirperms (upath, vol, did) != AFP_OK) {
+            if ((retvalue=matchfile2dirperms (upath, vol, did)) != AFP_OK) {
                 return retvalue;
             }
         }
index a64c8fd9f162cb9bcceb1d1e691d231106a20116..26613edda2093a61d699370c764cd9e03550a105 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: filedir.h,v 1.8 2002-08-29 18:57:26 didg Exp $
+ * $Id: filedir.h,v 1.9 2002-10-11 14:18:32 didg Exp $
  */
 
 #ifndef AFPD_FILEDIR_H
@@ -14,9 +14,10 @@ extern struct afp_options default_options;
 
 extern char            *ctoupath __P((const struct vol *, struct dir *,
                                 char *));
+extern char            *absupath __P((const struct vol *, struct dir *,
+                                char *));
 extern int             veto_file __P((const char *veto_str, const char *path));
 extern int             check_name __P((const struct vol *vol, char *name));
-extern int             check_access __P((char *name , int mode));
 
 /* FP functions */
 extern int     matchfile2dirperms __P((char *, struct vol *, int));
index dc4200e04e72fc7add56a89e403cd5ded94450c2..8330220f379ca5d4207c85ba4a37e45aa5ef4c57 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: fork.c,v 1.37 2002-10-05 14:04:47 didg Exp $
+ * $Id: fork.c,v 1.38 2002-10-11 14:18:32 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -48,6 +48,7 @@
 #include "volume.h"
 
 #define BYTELOCK_MAX 0x7FFFFFFFU
+#define BYTELOCK_MAXL 0x7FFFFFFFFFFFFFFFULL
 
 struct ofork           *writtenfork;
 extern int getmetadata(struct vol *vol,
@@ -62,42 +63,35 @@ char                *buf;
 int                    *buflen;
 const u_int16_t     attrbits;
 {
-#ifndef USE_LASTDID
-    struct stat                lst, *lstp;
-#endif /* !USE_LASTDID */
     struct stat                st;
     char               *upath;
-    u_int32_t          aint;
 
     struct adouble     *adp;
     struct dir         *dir;
     struct vol         *vol;
     
+
+    /* can only get the length of the opened fork */
+    if ( ( (bitmap & ((1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN))) 
+                  && (ofork->of_flags & AFPFORK_RSRC)) 
+        ||
+          ( (bitmap & ((1<<FILPBIT_RFLEN) | (1<<FILPBIT_EXTRFLEN))) 
+                  && (ofork->of_flags & AFPFORK_DATA))) {
+        return( AFPERR_BITMAP );
+    }
+
     if ( ad_hfileno( ofork->of_ad ) == -1 ) {
         adp = NULL;
     } else {
-        aint = ad_getentrylen( ofork->of_ad, ADEID_RFORK );
-        if ( ad_refresh( ofork->of_ad ) < 0 ) {
-            LOG(log_error, logtype_afpd, "getforkparams: ad_refresh: %s", strerror(errno) );
-            return( AFPERR_PARAM );
-        }
-        /* See afp_closefork() for why this is bad */
-        ad_setentrylen( ofork->of_ad, ADEID_RFORK, aint );
         adp = ofork->of_ad;
     }
 
-    /* can only get the length of the opened fork */
-    if (((bitmap & (1<<FILPBIT_DFLEN)) && (ofork->of_flags & AFPFORK_RSRC)) ||
-            ((bitmap & (1<<FILPBIT_RFLEN)) && (ofork->of_flags & AFPFORK_DATA))) {
-        return( AFPERR_BITMAP );
-    }
-
     vol = ofork->of_vol;
     dir = ofork->of_dir;
 
-    if ( bitmap & ( 1<<FILPBIT_DFLEN | 1<<FILPBIT_FNUM |
-                    (1 << FILPBIT_CDATE) | (1 << FILPBIT_MDATE) |
-                    (1 << FILPBIT_BDATE))) {
+    if ( bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) | 
+                    (1<<FILPBIT_FNUM) | (1 << FILPBIT_CDATE) | 
+                    (1 << FILPBIT_MDATE) | (1 << FILPBIT_BDATE))) {
         if ( ad_dfileno( ofork->of_ad ) == -1 ) {
             upath = mtoupath(vol, ofork->of_name);
             if (movecwd(vol, dir) < 0)
@@ -235,9 +229,10 @@ int                ibuflen, *rbuflen;
     u_int32_t           did;
     u_int16_t          vid, bitmap, access, ofrefnum, attrbits = 0;
     char               fork, *path, *upath;
-    struct stat         st;
+    struct stat         *st;
     u_int16_t           bshort;
-
+    struct path         *s_path;
+    
     ibuf++;
     fork = *ibuf++;
     memcpy(&vid, ibuf, sizeof( vid ));
@@ -266,36 +261,34 @@ int               ibuflen, *rbuflen;
         return AFPERR_VLOCK;
     }
 
-    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
-        return( AFPERR_NOOBJ );
+    if (( s_path = cname( vol, dir, &ibuf )) == NULL ) {
+        return AFPERR_NOOBJ;
     }
 
-    if ( fork == OPENFORK_DATA ) {
-        eid = ADEID_DFORK;
-        adflags = ADFLAGS_DF|ADFLAGS_HF;
-    } else {
-        eid = ADEID_RFORK;
-        adflags = ADFLAGS_HF;
+    if (*s_path->m_name == '\0') {
+       /* it's a dir ! */
+       return  AFPERR_BADTYPE;
     }
 
-    upath = mtoupath(vol, path);
+    /* stat() data fork st is set because it's not a dir */
+    switch ( s_path->st_errno ) {
+    case 0:
+        break;
+    case ENOENT:
+        return AFPERR_NOOBJ;
+    case EACCES:
+        return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS;
+    default:
+        LOG(log_error, logtype_afpd, "afp_openfork: ad_open: %s", strerror(errno) );
+        return AFPERR_PARAM;
+    }
+    /* FIXME should we check first ? */
+    upath = s_path->u_name;
     if (check_access(upath, access ) < 0) {
         return AFPERR_ACCESS;
     }
 
-    /* stat() data fork */
-    if (stat(upath, &st) < 0) {
-        switch ( errno ) {
-        case ENOENT:
-            return AFPERR_NOOBJ;
-        case EACCES:
-            return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS;
-        default:
-            LOG(log_error, logtype_afpd, "afp_openfork: ad_open: %s", strerror(errno) );
-            return AFPERR_PARAM;
-        }
-    }
-
+    st   = &s_path->st;
     /* XXX: this probably isn't the best way to do this. the already
        open bits should really be set if the fork is opened by any
        program, not just this one. however, that's problematic to do
@@ -303,15 +296,24 @@ int               ibuflen, *rbuflen;
        ad_open so that we can keep file locks together.
        FIXME: add the fork we are opening? 
     */
-    if ((opened = of_findname(upath, &st))) {
+    if ((opened = of_findname(s_path))) {
         attrbits = ((opened->of_ad->ad_df.adf_refcount > 0) ? ATTRBIT_DOPEN : 0);
         attrbits |= ((opened->of_ad->ad_hf.adf_refcount > opened->of_ad->ad_df.adf_refcount)? ATTRBIT_ROPEN : 0);
                    
         adsame = opened->of_ad;
     }
 
+    if ( fork == OPENFORK_DATA ) {
+        eid = ADEID_DFORK;
+        adflags = ADFLAGS_DF|ADFLAGS_HF;
+    } else {
+        eid = ADEID_RFORK;
+        adflags = ADFLAGS_HF;
+    }
+
+    path = s_path->m_name;
     if (( ofork = of_alloc(vol, curdir, path, &ofrefnum, eid,
-                           adsame, &st)) == NULL ) {
+                           adsame, st)) == NULL ) {
         return( AFPERR_NFILE );
     }
 
@@ -556,13 +558,58 @@ afp_setfork_err:
  */
 #define ENDBIT(a)  ((a) & 0x80)
 #define UNLOCKBIT(a) ((a) & 0x01)
-int afp_bytelock(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj      *obj;
+
+static off_t get_off_t(ibuf, is64)
+char   **ibuf;
+int     is64;
+{
+    u_int32_t             temp;
+    off_t                 ret;
+
+    memcpy(&temp, *ibuf, sizeof( temp ));
+    ret = ntohl(temp); /* ntohl is unsigned */
+    *ibuf += sizeof(temp);
+
+    if (is64) {
+        memcpy(&temp, *ibuf, sizeof( temp ));
+        *ibuf += sizeof(temp);
+        ret = ntohl(temp)| (ret << 32);
+    }
+    return ret;
+}
+
+/* ---------------------- */
+static int set_off_t(offset, rbuf, is64)
+off_t   offset;
+char   *rbuf;
+int     is64;
+{
+    u_int32_t  temp;
+    int        ret;
+
+    ret = 0;
+    if (is64) {
+        temp = htonl(offset >> 32);
+        memcpy(rbuf, &temp, sizeof( temp ));
+        ret = sizeof( temp );
+        offset &= 0xffffffff;
+    }
+    temp = htonl(offset);
+    memcpy(rbuf, &temp, sizeof( temp ));
+    ret += sizeof( temp );
+
+    return ret;
+}
+
+/* ---------------------- */
+static int byte_lock(obj, ibuf, ibuflen, rbuf, rbuflen, is64 )
+AFPObj  *obj;
 char   *ibuf, *rbuf;
-int            ibuflen, *rbuflen;
+int    ibuflen, *rbuflen;
+int     is64;
 {
     struct ofork       *ofork;
-    int32_t             offset, length;
+    off_t               offset, length;
     int                 eid;
     u_int16_t          ofrefnum;
     u_int8_t            flags;
@@ -588,20 +635,30 @@ int               ibuflen, *rbuflen;
     } else
         return AFPERR_PARAM;
 
-    memcpy(&offset, ibuf, sizeof( offset ));
-    offset = ntohl(offset);
-    ibuf += sizeof(offset);
-
-    memcpy(&length, ibuf, sizeof( length ));
-    length = ntohl(length);
-    if (length == 0xFFFFFFFF)
-        length = BYTELOCK_MAX;
-    else if (length <= 0) {
-        return AFPERR_PARAM;
-    } else if ((length >= AD_FILELOCK_BASE) &&
-               (ad_hfileno(ofork->of_ad) == -1))
-        return AFPERR_LOCK;
+    offset = get_off_t(&ibuf, is64);
+    length = get_off_t(&ibuf, is64);
 
+    if (is64) {
+        if (length == -1)
+            length = BYTELOCK_MAXL;
+        else if (length <= 0) {
+            return AFPERR_PARAM;
+        } else if ((length >= AD_FILELOCK_BASE) &&
+                   (ad_hfileno(ofork->of_ad) == -1)) {
+            return AFPERR_LOCK;
+        }
+    }
+    else {
+        if (length == 0xFFFFFFFF)
+            length = BYTELOCK_MAX;
+        else if (!length || (length & (1 << 31))) {
+            return AFPERR_PARAM;
+        } else if ((length >= AD_FILELOCK_BASE) &&
+                   (ad_hfileno(ofork->of_ad) == -1)) {
+            return AFPERR_LOCK;
+        }
+    }
+    
     if (ENDBIT(flags))
         offset += ad_size(ofork->of_ad, eid);
 
@@ -632,15 +689,31 @@ int               ibuflen, *rbuflen;
             break;
         }
     }
-
-    offset = htonl(offset);
-    memcpy(rbuf, &offset, sizeof( offset ));
-    *rbuflen = sizeof( offset );
+    *rbuflen = set_off_t (offset, rbuf, is64);
     return( AFP_OK );
 }
-#undef UNLOCKBIT
 
+/* --------------------------- */
+int afp_bytelock(obj, ibuf, ibuflen, rbuf, rbuflen )
+AFPObj  *obj;
+char   *ibuf, *rbuf;
+int    ibuflen, *rbuflen;
+{
+   return byte_lock ( obj, ibuf, ibuflen, rbuf, rbuflen , 0);
+}
 
+/* --------------------------- */
+int afp_bytelock_ext(obj, ibuf, ibuflen, rbuf, rbuflen )
+AFPObj  *obj;
+char   *ibuf, *rbuf;
+int    ibuflen, *rbuflen;
+{
+   return byte_lock ( obj, ibuf, ibuflen, rbuf, rbuflen , 1);
+}
+
+#undef UNLOCKBIT
+
+/* --------------------------- */
 static __inline__ int crlf( of )
 struct ofork   *of;
 {
@@ -734,18 +807,19 @@ static __inline__ ssize_t read_file(struct ofork *ofork, int eid,
  *
  * with dsi, should we check that reqcount < server quantum? 
 */
-int afp_read(obj, ibuf, ibuflen, rbuf, rbuflen)
+static int read_fork(obj, ibuf, ibuflen, rbuf, rbuflen, is64)
 AFPObj      *obj;
 char   *ibuf, *rbuf;
 int            ibuflen, *rbuflen;
+int is64;
 {
     struct ofork       *ofork;
     off_t              size;
-    int32_t            offset, saveoff, reqcount, savereqcount;
+    off_t              offset, saveoff, reqcount, savereqcount;
     int                        cc, err, eid, xlate = 0;
     u_int16_t          ofrefnum;
     u_char             nlmask, nlchar;
-
+    
     ibuf += 2;
     memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
     ibuf += sizeof( u_short );
@@ -760,17 +834,16 @@ int               ibuflen, *rbuflen;
         err = AFPERR_ACCESS;
         goto afp_read_err;
     }
+    offset   = get_off_t(&ibuf, is64);
+    reqcount = get_off_t(&ibuf, is64);
 
-    memcpy(&offset, ibuf, sizeof( offset ));
-    offset = ntohl( offset );
-    ibuf += sizeof( offset );
-    memcpy(&reqcount, ibuf, sizeof( reqcount ));
-    reqcount = ntohl( reqcount );
-    ibuf += sizeof( reqcount );
-
-    nlmask = *ibuf++;
-    nlchar = *ibuf++;
-
+    if (is64) {
+        nlmask = nlchar = 0;
+    }
+    else {
+        nlmask = *ibuf++;
+        nlchar = *ibuf++;
+    }
     /* if we wanted to be picky, we could add in the following
      * bit: if (afp_version == 11 && !(nlmask == 0xFF || !nlmask))
      */
@@ -824,7 +897,7 @@ int         ibuflen, *rbuflen;
 
         if (obj->options.flags & OPTION_DEBUG) {
             printf( "(read) reply: %d/%d, %d\n", *rbuflen,
-                    reqcount, dsi->clientID);
+                    (int) reqcount, dsi->clientID);
             bprint(rbuf, *rbuflen);
         }
         /* subtract off the offset */
@@ -901,6 +974,25 @@ afp_read_err:
     return err;
 }
 
+/* ---------------------- */
+int afp_read(obj, ibuf, ibuflen, rbuf, rbuflen)
+AFPObj  *obj;
+char   *ibuf, *rbuf;
+int    ibuflen, *rbuflen;
+{
+    return read_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 0);
+}
+
+/* ---------------------- */
+int afp_read_ext(obj, ibuf, ibuflen, rbuf, rbuflen)
+AFPObj  *obj;
+char   *ibuf, *rbuf;
+int    ibuflen, *rbuflen;
+{
+    return read_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 1);
+}
+
+/* ---------------------- */
 int afp_flush(obj, ibuf, ibuflen, rbuf, rbuflen )
 AFPObj      *obj;
 char   *ibuf, *rbuf;
@@ -950,7 +1042,8 @@ int flushfork( ofork )
 struct ofork   *ofork;
 {
     struct timeval tv;
-    int len, err = 0, doflush = 0;
+
+    int err = 0, doflush = 0;
 
     if ( ad_dfileno( ofork->of_ad ) != -1 &&
             fsync( ad_dfileno( ofork->of_ad )) < 0 ) {
@@ -959,32 +1052,21 @@ struct ofork     *ofork;
         err = -1;
     }
 
-    if ( ad_hfileno( ofork->of_ad ) != -1 ) {
+    if ( ad_hfileno( ofork->of_ad ) != -1 && 
+           (ofork->of_flags & AFPFORK_RSRC)) {
 
         /* read in the rfork length */
-        len = ad_getentrylen(ofork->of_ad, ADEID_RFORK);
         ad_refresh(ofork->of_ad);
 
         /* set the date if we're dirty */
-        if ((ofork->of_flags & AFPFORK_DIRTY) &&
-                (gettimeofday(&tv, NULL) == 0)) {
+        if ((ofork->of_flags & AFPFORK_DIRTY) && !gettimeofday(&tv, NULL)) {
             ad_setdate(ofork->of_ad, AD_DATE_MODIFY|AD_DATE_UNIX, tv.tv_sec);
             ofork->of_flags &= ~AFPFORK_DIRTY;
             doflush++;
         }
 
-        /* if we're actually flushing this fork, make sure to set the
-         * length. otherwise, just use the stored length */
-        if ((ofork->of_flags & AFPFORK_RSRC) &&
-                (len != ad_getentrylen(ofork->of_ad, ADEID_RFORK))) {
-            ad_setentrylen(ofork->of_ad, ADEID_RFORK, len);
-            doflush++;
-        }
-
-
-        /* flush the header (if it is a resource fork) */
-        if (ofork->of_flags & AFPFORK_RSRC)
-            if (doflush && (ad_flush(ofork->of_ad, ADFLAGS_HF) < 0))
+        /* flush the header */
+        if (doflush && ad_flush(ofork->of_ad, ADFLAGS_HF) < 0)
                 err = -1;
 
         if (fsync( ad_hfileno( ofork->of_ad )) < 0)
@@ -1005,7 +1087,7 @@ int               ibuflen, *rbuflen;
 {
     struct ofork       *ofork;
     struct timeval      tv;
-    int                        adflags, aint, doflush = 0;
+    int                        adflags, doflush = 0;
     u_int16_t          ofrefnum;
 
     *rbuflen = 0;
@@ -1025,26 +1107,19 @@ int             ibuflen, *rbuflen;
 
     if ( ad_hfileno( ofork->of_ad ) != -1 ) {
         adflags |= ADFLAGS_HF;
-
-        aint = ad_getentrylen( ofork->of_ad, ADEID_RFORK );
-        ad_refresh( ofork->of_ad );
-        if ((ofork->of_flags & AFPFORK_DIRTY) &&
-                (gettimeofday(&tv, NULL) == 0)) {
-            ad_setdate(ofork->of_ad, AD_DATE_MODIFY | AD_DATE_UNIX,
-                       tv.tv_sec);
-            doflush++;
-        }
-
         /*
          * Only set the rfork's length if we're closing the rfork.
          */
-        if ((ofork->of_flags & AFPFORK_RSRC) && aint !=
-                ad_getentrylen( ofork->of_ad, ADEID_RFORK )) {
-            ad_setentrylen( ofork->of_ad, ADEID_RFORK, aint );
-            doflush++;
-        }
-        if ( doflush ) {
-            ad_flush( ofork->of_ad, adflags );
+        if ((ofork->of_flags & AFPFORK_RSRC)) {
+            ad_refresh( ofork->of_ad );
+            if ((ofork->of_flags & AFPFORK_DIRTY) &&
+                      !gettimeofday(&tv, NULL)) {
+                ad_setdate(ofork->of_ad, AD_DATE_MODIFY | AD_DATE_UNIX,tv.tv_sec);
+               doflush++;
+            }
+            if ( doflush ) {
+                ad_flush( ofork->of_ad, adflags );
+            }
         }
     }
 
@@ -1097,13 +1172,14 @@ static __inline__ ssize_t write_file(struct ofork *ofork, int eid,
 /* FPWrite. NOTE: on an error, we always use afp_write_err as
  * the client may have sent us a bunch of data that's not reflected 
  * in reqcount et al. */
-int afp_write(obj, ibuf, ibuflen, rbuf, rbuflen)
+static int write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, is64)
 AFPObj              *obj;
 char                *ibuf, *rbuf;
 int                 ibuflen, *rbuflen;
+int                 is64;
 {
     struct ofork       *ofork;
-    int32_t            offset, saveoff, reqcount;
+    off_t              offset, saveoff, reqcount;
     int                        endflag, eid, xlate = 0, err = AFP_OK;
     u_int16_t          ofrefnum;
     ssize_t             cc;
@@ -1114,12 +1190,9 @@ int                 ibuflen, *rbuflen;
     ibuf++;
     memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
     ibuf += sizeof( ofrefnum );
-    memcpy(&offset, ibuf, sizeof( offset ));
-    offset = ntohl( offset );
-    ibuf += sizeof( offset );
-    memcpy(&reqcount, ibuf, sizeof( reqcount ));
-    reqcount = ntohl( reqcount );
-    ibuf += sizeof( reqcount );
+
+    offset   = get_off_t(&ibuf, is64);
+    reqcount = get_off_t(&ibuf, is64);
 
     if (( ofork = of_find( ofrefnum )) == NULL ) {
         LOG(log_error, logtype_afpd, "afp_write: of_find");
@@ -1164,8 +1237,7 @@ int                 ibuflen, *rbuflen;
 
     if (!reqcount) { /* handle request counts of 0 */
         err = AFP_OK;
-        offset = htonl(offset);
-        memcpy(rbuf, &offset, sizeof(offset));
+        *rbuflen = set_off_t (offset, rbuf, is64);
         goto afp_write_err;
     }
 
@@ -1267,13 +1339,7 @@ int                 ibuflen, *rbuflen;
     if ( ad_hfileno( ofork->of_ad ) != -1 )
         ofork->of_flags |= AFPFORK_DIRTY;
 
-    offset = htonl( offset );
-#if defined(__GNUC__) && defined(HAVE_GCC_MEMCPY_BUG)
-    bcopy(&offset, rbuf, sizeof(offset));
-#else /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
-    memcpy(rbuf, &offset, sizeof(offset));
-#endif /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
-    *rbuflen = sizeof(offset);
+    *rbuflen = set_off_t (offset, rbuf, is64);
     return( AFP_OK );
 
 afp_write_err:
@@ -1286,7 +1352,25 @@ afp_write_err:
     return err;
 }
 
+/* ---------------------------- */
+int afp_write(obj, ibuf, ibuflen, rbuf, rbuflen)
+AFPObj              *obj;
+char                *ibuf, *rbuf;
+int                 ibuflen, *rbuflen;
+{
+    return write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 0);
+}
+
+/* ---------------------------- */
+int afp_write_ext(obj, ibuf, ibuflen, rbuf, rbuflen)
+AFPObj              *obj;
+char                *ibuf, *rbuf;
+int                 ibuflen, *rbuflen;
+{
+    return write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 1);
+}
 
+/* ---------------------------- */
 int afp_getforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
 AFPObj      *obj;
 char   *ibuf, *rbuf;
@@ -1312,6 +1396,13 @@ int              ibuflen, *rbuflen;
     attrbits = ((ofork->of_ad->ad_df.adf_refcount > 0) ? ATTRBIT_DOPEN : 0);
     attrbits |= ((ofork->of_ad->ad_hf.adf_refcount > ofork->of_ad->ad_df.adf_refcount) ? ATTRBIT_ROPEN : 0);
 
+    if ( ad_hfileno( ofork->of_ad ) != -1 ) {
+        if ( ad_refresh( ofork->of_ad ) < 0 ) {
+            LOG(log_error, logtype_afpd, "getforkparams: ad_refresh: %s", strerror(errno) );
+            return( AFPERR_PARAM );
+        }
+    }
+
     if (( ret = getforkparams( ofork, bitmap,
                                rbuf + sizeof( u_short ), &buflen, attrbits )) != AFP_OK ) {
         return( ret );
index d1bb770fced6d15c599cd8e403b50fe72a97aa63..5140312b0c7ac312d6378707a487ec2ef19cf315 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: fork.h,v 1.5 2002-09-05 14:52:07 didg Exp $
+ * $Id: fork.h,v 1.6 2002-10-11 14:18:34 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -59,14 +59,14 @@ extern struct ofork *of_alloc    __P((struct vol *, struct dir *,
                                                       struct stat *));
 extern void         of_dealloc   __P((struct ofork *));
 extern struct ofork *of_find     __P((const u_int16_t));
-extern struct ofork *of_findname __P((const char *, struct stat *));
+extern struct ofork *of_findname __P((struct path *));
 extern int          of_rename    __P((const struct vol *,
                                           struct ofork *,
                                           struct dir *, const char *,
                                           struct dir *, const char *));
 extern int          of_flush     __P((const struct vol *));
 extern void         of_pforkdesc __P((FILE *));
-
+extern int          of_stat      __P((struct path *));
 /* in fork.c */
 extern int          flushfork    __P((struct ofork *));
 
@@ -81,4 +81,7 @@ extern int    afp_flushfork __P((AFPObj *, char *, int, char *, int *));
 extern int     afp_flush __P((AFPObj *, char *, int, char *, int *));
 extern int     afp_closefork __P((AFPObj *, char *, int, char *, int *));
 
+extern int     afp_bytelock_ext __P((AFPObj *, char *, int, char *, int *));
+extern int     afp_read_ext __P((AFPObj *, char *, int, char *, int *));
+extern int     afp_write_ext __P((AFPObj *, char *, int, char *, int *));
 #endif
index 2925977c2705d266c4a36a583571ad615f29cd56..abfa5ec03c3c321de33407024719a886326c946f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ofork.c,v 1.19 2002-09-06 02:57:49 didg Exp $
+ * $Id: ofork.c,v 1.20 2002-10-11 14:18:34 didg Exp $
  *
  * Copyright (c) 1996 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -270,23 +270,34 @@ struct ofork *of_find(const u_int16_t ofrefnum )
     return( oforks[ ofrefnum % nforks ] );
 }
 
-/* --------------------------
-*/
+/* -------------------------- */
+int of_stat  (struct path *path)
+{
+int ret;
+    path->st_errno = 0;
+    path->st_valid = 1;
+    if ((ret = stat(path->u_name, &path->st)) < 0)
+       path->st_errno = errno;
+   return ret;
+}
+
+
+/* -------------------------- */
 struct ofork *
-            of_findname(const char *name, struct stat *st)
+            of_findname(struct path *path)
 {
     struct ofork *of;
     struct file_key key;
-    struct stat buffer;
-    char   *p;
     
-    if (st == NULL) {
-        st = &buffer;
-        if (stat(name, st) < 0)
-            return NULL;
+    if (!path->st_valid) {
+       of_stat(path);
     }
-    key.dev = st->st_dev;
-    key.inode = st->st_ino;
+       
+    if (path->st_errno)
+        return NULL;
+
+    key.dev = path->st.st_dev;
+    key.inode = path->st.st_ino;
 
     for (of = ofork_table[hashfn(&key)]; of; of = of->next) {
         if (key.dev == of->key.dev && key.inode == of->key.inode ) {
index ebb21d9c91c48e67eb0db49dde7de52b61bdd53c..7ff5ea82fd7f7db115ec2eee6623f996bbecfe9c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: volume.c,v 1.37 2002-10-10 20:27:36 jmarcus Exp $
+ * $Id: volume.c,v 1.38 2002-10-11 14:18:35 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -601,7 +601,6 @@ int                 user;
             LOG(log_error, logtype_afpd, "setextmap: calloc: %s", strerror(errno) );
             return;
         }
-
     }
     ext++;
     for ( em = extmap, cnt = 0; em->em_ext; em++, cnt++) {
@@ -1215,14 +1214,14 @@ int             ibuflen, *rbuflen;
     }
 
     if (( volume->v_flags & AFPVOL_OPEN  ) == 0 ) {
-        if ((dir = dirnew(strlen(volume->v_name) + 1)) == NULL) {
+        /* FIXME unix name != mac name */
+        if ((dir = dirnew(volume->v_name, volume->v_name) ) == NULL) {
             LOG(log_error, logtype_afpd, "afp_openvol: malloc: %s", strerror(errno) );
             ret = AFPERR_MISC;
             goto openvol_err;
         }
         dir->d_did = DIRDID_ROOT;
         dir->d_color = DIRTREE_COLOR_BLACK; /* root node is black */
-        strcpy( dir->d_name, volume->v_name );
         volume->v_dir = volume->v_root = dir;
         volume->v_flags |= AFPVOL_OPEN;
     }
index d9b4f18dc5fafcb2b22ed46860727f8da114648e..95dea94e78ac72c7dd400b1beb58953dbbb37dcf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: adouble.h,v 1.10 2002-09-07 19:19:00 didg Exp $
+ * $Id: adouble.h,v 1.11 2002-10-11 14:18:35 didg Exp $
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
  *
 #ifndef _ATALK_ADOUBLE_H
 #define _ATALK_ADOUBLE_H
 
+/* ------------------- 
+ * need pread() and pwrite()
+*/
+#ifdef HAVE_PREAD
+
+#ifndef HAVE_PWRITE
+#undef HAVE_PREAD
+#endif
+
+#endif
+
+#ifdef HAVE_PWRITE
+
+#ifndef HAVE_PREAD
+#undef HAVE_PWRITE
+#endif
+
+#endif
+
+#ifdef  HAVE_PREAD
+#define _XOPEN_SOURCE 500
+#endif
+
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif 
 
 #ifdef HAVE_FLOCK
 #include <sys/file.h>
 #define LOCK_UN 8
 extern int flock (int /*fd*/, int /*operation*/);
 #endif
+
+#ifdef HAVE_FCNTL_H  
 #include <fcntl.h>
+#endif
+
 #include <sys/cdefs.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/mman.h>
 #include <netatalk/endian.h>
 
-
 /* XXX: this is the wrong place to put this. 
- * NOTE: as of 2.2.1, linux can't do a sendfile from a socket. */
+ * NOTE: as of 2.2.1, linux can't do a sendfile from a socket. 
+ * and it doesn't have 64 bits sendfile
+ */
 #ifdef SENDFILE_FLAVOR_LINUX
+
+#if _FILE_OFFSET_BITS == 64 
+
+#undef SENDFILE_FLAVOR_LINUX
+
+#else
 #define HAVE_SENDFILE_READ
 #define HAVE_SENDFILE_WRITE
 #include <asm/unistd.h>
+
 #ifdef __NR_sendfile
-static inline int sendfile(int fdout, int fdin, off_t *off, size_t count)
+#ifndef ATACC
+static __inline__ int sendfile(int fdout, int fdin, off_t *off, size_t count)
 {
+#if _FILE_OFFSET_BITS == 64 
+  return syscall(__NR_sendfile64, fdout, fdin, off, count);
+#else
   return syscall(__NR_sendfile, fdout, fdin, off, count);
+#endif
 }
+#else
+extern int sendfile __P((int , int , off_t *, size_t ));
+#endif /* ATACC */
+
 #else
 #include <sys/sendfile.h>
 #endif
 #endif
+#endif /* SENDFILE_FLAVOR_LINUX */
 
 #ifdef SENDFILE_FLAVOR_BSD
 #define HAVE_SENDFILE_READ
@@ -172,7 +219,11 @@ typedef struct adf_lock_t {
 
 struct ad_fd {
     int                 adf_fd;
+
+#ifndef HAVE_PREAD
     off_t       adf_off;
+#endif
+
     int                 adf_flags;
     adf_lock_t   *adf_lock;
     int          adf_refcount, adf_lockcount, adf_lockmax;
@@ -187,7 +238,10 @@ struct adouble {
     struct ad_entry    ad_eid[ ADEID_MAX ];
     struct ad_fd       ad_df, ad_hf;
     int                 ad_flags, ad_inited;
-    int             ad_refcount; /* used in afpd/ofork.c */
+    int                 ad_refcount; /* used in afpd/ofork.c */
+    off_t               ad_rlen;     /* ressource fork len with AFP 3.0
+                                        the header parameter size is too small.
+                                     */
 #ifdef USE_MMAPPED_HEADERS
     char                *ad_data;
 #else
@@ -288,16 +342,17 @@ extern int ad_fcntl_tmplock __P((struct adouble *, const u_int32_t /*eid*/,
 #endif
 
 /* ad_open.c */
-extern char *ad_dir   __P((char *));
-extern char *ad_path  __P((char *, int));
-extern int ad_mode    __P((char *, int));
-extern int ad_mkdir   __P((char *, int));
-extern int ad_open    __P((char *, int, int, int, struct adouble *)); 
+extern char *ad_dir   __P((const char *));
+extern char *ad_path  __P((const char *, int));
+extern int ad_mode    __P((const char *, int));
+extern int ad_mkdir   __P((const char *, int));
+extern int ad_open    __P((const char *, int, int, int, struct adouble *)); 
 extern int ad_refresh __P((struct adouble *));
 
 /* extend header to RW if R or W (W if R for locking),
  */ 
-static inline mode_t ad_hf_mode (mode_t mode)
+#ifndef ATACC
+static __inline__ mode_t ad_hf_mode (mode_t mode)
 {
 #ifndef USE_FLOCK_LOCKS
     /* fnctl lock need write access */
@@ -318,12 +373,21 @@ static inline mode_t ad_hf_mode (mode_t mode)
 
     return mode;
 }
+#else
+extern mode_t ad_hf_mode __P((mode_t ));
+#endif
 
 /* ad_read.c/ad_write.c */
 extern ssize_t ad_read __P((struct adouble *, const u_int32_t, 
                            const off_t, char *, const size_t));
+extern ssize_t ad_pread __P((struct ad_fd *, void *, size_t, off_t));
+
 extern ssize_t ad_write __P((struct adouble *, const u_int32_t, off_t,
                             const int, const char *, const size_t));
+
+extern ssize_t adf_pread  __P((struct ad_fd *, void *, size_t, off_t));
+extern ssize_t adf_pwrite __P((struct ad_fd *, const void *, size_t, off_t));
+
 extern int ad_dtruncate __P((struct adouble *, const size_t));
 extern int ad_rtruncate __P((struct adouble *, const size_t));
 
index fd569df5c86b6376e417a1e03a65855a1f86e274..d36710186a4c15f2fd442b36a186f58b6392d293 100644 (file)
@@ -59,7 +59,7 @@ typedef struct ASP {
     char               child, inited, *commands;
     char                cmdbuf[ASP_CMDMAXSIZ];
     char                data[ASP_DATAMAXSIZ];  
-    int                 cmdlen, datalen;
+    unsigned int        cmdlen, datalen;
     size_t             read_count, write_count;
 } *ASP;
 
index 63509c1f57596e426645961493c053dbd9021558..80d08dbc79ca605996e079ce5892a3d589ebc6da 100644 (file)
@@ -62,7 +62,8 @@ typedef struct DSI {
   u_int32_t attn_quantum, datasize, server_quantum;
   u_int16_t serverID, clientID;
   u_int8_t *status, commands[DSI_CMDSIZ], data[DSI_DATASIZ];
-  int statuslen, datalen, cmdlen;
+  int statuslen;
+  unsigned int datalen, cmdlen;
   size_t read_count, write_count;
   /* inited = initialized?, child = a child?, noreply = send reply? */
   char child, inited, noreply;
@@ -142,7 +143,7 @@ extern void dsi_close __P((DSI *));
 extern size_t dsi_stream_write __P((DSI *, void *, const size_t));
 extern size_t dsi_stream_read __P((DSI *, void *, const size_t));
 extern int dsi_stream_send __P((DSI *, void *, size_t));
-extern int dsi_stream_receive __P((DSI *, void *, const int, int *));
+extern int dsi_stream_receive __P((DSI *, void *, const size_t, size_t *));
 
 /* client writes -- dsi_write.c */
 extern size_t dsi_writeinit __P((DSI *, void *, const size_t));
index c5d1beb18efae47899db84131678368332d89840..14ca97b4f6aec6e137e83a49515e14bdf4ec50c9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ad_flush.c,v 1.4 2002-09-29 17:39:59 didg Exp $
+ * $Id: ad_flush.c,v 1.5 2002-10-11 14:18:36 didg Exp $
  *
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
 #include "config.h"
 #endif /* HAVE_CONFIG_H */
 
+#include <atalk/adouble.h>
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif /* HAVE_FCNTL_H */
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-#include <sys/types.h>
-#include <sys/mman.h>
 #include <errno.h>
 
-#include <netatalk/endian.h>
-#include <atalk/adouble.h>
-
 #include "ad_private.h"
 
 /* rebuild the header */
@@ -98,41 +89,25 @@ int ad_flush( ad, adflags )
     struct adouble     *ad;
     int                        adflags;
 {
-#ifndef USE_MMAPPED_HEADERS
     int len;
-#endif /* ! USE_MMAPPED_HEADERS */
 
     if (( adflags & ADFLAGS_HF ) && ( ad->ad_hf.adf_flags & O_RDWR )) {
        /* sync our header */
+        if (ad->ad_rlen > 0xffffffff) {
+            ad_setentrylen(ad, ADEID_RFORK, 0xffffffff);
+        }
+        else {
+            ad_setentrylen(ad, ADEID_RFORK, ad->ad_rlen);
+        }
         ad_rebuild_header(ad);
-
-#ifdef USE_MMAPPED_HEADERS
-       /* now sync it */
-#ifdef MS_SYNC
-       msync(ad->ad_data, ad_getentryoff(ad, ADEID_RFORK),
-             MS_SYNC | MS_INVALIDATE);
-#else
-       msync(ad->ad_data, ad_getentryoff(ad, ADEID_RFORK));
-#endif /* MS_SYNC */
-
-#else /* USE_MMAPPED_HEADERS */
-       if ( ad->ad_hf.adf_off != 0 ) {
-           if ( lseek( ad->ad_hf.adf_fd, 0L, SEEK_SET ) < 0L ) {
-               return( -1 );
-           }
-           ad->ad_hf.adf_off = 0;
-       }
-
-       /* now flush it out */
        len = ad_getentryoff(ad, ADEID_RFORK);
-       if (write( ad->ad_hf.adf_fd, ad->ad_data, len) != len) {
+       /* now flush it out */
+        if (adf_pwrite(&ad->ad_hf, ad->ad_data, len, 0) != len) {
            if ( errno == 0 ) {
                errno = EIO;
            }
            return( -1 );
        }
-       ad->ad_hf.adf_off = len;
-#endif /* USE_MMAPPED_HEADERS */
     }
 
     return( 0 );
@@ -146,7 +121,7 @@ int ad_close( ad, adflags )
     int                        err = 0;
 
     if (( adflags & ADFLAGS_DF ) && ad->ad_df.adf_fd != -1 &&
-       !(--ad->ad_df.adf_refcount)) {
+           !(--ad->ad_df.adf_refcount)) {
        if ( close( ad->ad_df.adf_fd ) < 0 ) {
            err = -1;
        }
@@ -155,11 +130,7 @@ int ad_close( ad, adflags )
     }
 
     if (( adflags & ADFLAGS_HF ) && ad->ad_hf.adf_fd != -1 &&
-       !(--ad->ad_hf.adf_refcount)) {
-#ifdef USE_MMAPPED_HEADERS
-        if (ad->ad_data != MAP_FAILED)
-         munmap(ad->ad_data, ad_getentryoff(ad, ADEID_RFORK));
-#endif /* USE_MMAPPED_HEADERS */
+           !(--ad->ad_hf.adf_refcount)) {
        if ( close( ad->ad_hf.adf_fd ) < 0 ) {
            err = -1;
        }
index 3625c4829abc92167771d4d3f78554ea00856c6e..9be9af32a30b8b129785189852da32b20d902c95 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ad_open.c,v 1.20 2002-10-10 20:27:36 jmarcus Exp $
+ * $Id: ad_open.c,v 1.21 2002-10-11 14:18:37 didg Exp $
  *
  * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu)
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
@@ -217,12 +217,6 @@ static __inline__ int ad_v1tov2(struct adouble *ad, const char *path)
   
   off = ad->ad_eid[ADEID_RFORK].ade_off;
 
-#ifdef USE_MMAPPED_HEADERS
-  /* okay, unmap our old ad header and point it to our local copy */
-  munmap(ad->ad_data, off);
-  ad->ad_data = buf;
-#endif /* USER_MMAPPED_HEADERS */
-
   /* move the RFORK. this assumes that the RFORK is at the end */
   memmove(buf + off + SHIFTDATA, buf + off, 
          ad->ad_eid[ADEID_RFORK].ade_len);
@@ -275,15 +269,6 @@ static __inline__ int ad_v1tov2(struct adouble *ad, const char *path)
   close(fd);
   ad_tmplock(ad, ADEID_RFORK, ADLOCK_CLR, 0, 0);
 
-#ifdef USE_MMAPPED_HEADERS
-  /* now remap our header */
-  ad->ad_data = mmap(NULL, ADEDOFF_RFORK_V2, PROT_READ | PROT_WRITE,
-                    (ad_getoflags(ad, ADFLAGS_HF) & O_RDWR) ? MAP_SHARED :
-                    MAP_PRIVATE, ad->ad_hf.adf_fd, 0);
-  if (ad->ad_data == MAP_FAILED)
-    goto bail_err;
-#endif /* USE_MMAPPED_HEADERS */
-
   return 0;
   
 bail_truncate:
@@ -297,9 +282,35 @@ bail_err:
 }
 #endif /* AD_VERSION == AD_VERSION2 */
 
+#ifdef ATACC
+mode_t ad_hf_mode (mode_t mode)
+{
+#ifndef USE_FLOCK_LOCKS
+    /* fnctl lock need write access */
+    if ((mode & S_IRUSR))
+        mode |= S_IWUSR;
+    if ((mode & S_IRGRP))
+        mode |= S_IWGRP;
+    if ((mode & S_IROTH))
+        mode |= S_IWOTH;
+#endif
+    /* if write mode set add read mode */
+    if ((mode & S_IWUSR))
+        mode |= S_IRUSR;
+    if ((mode & S_IWGRP))
+        mode |= S_IRGRP;
+    if ((mode & S_IWOTH))
+        mode |= S_IROTH;
+
+    return mode;
+}
+
+#endif
 
-/* read in the entries */
-static __inline__ void parse_entries(struct adouble *ad, char *buf,
+/* ------------------------------------- 
+  read in the entries 
+*/
+static void parse_entries(struct adouble *ad, char *buf,
                                    u_int16_t nentries)
 {
     u_int32_t          eid, len, off;
@@ -334,36 +345,26 @@ static __inline__ void parse_entries(struct adouble *ad, char *buf,
  * NOTE: we're assuming that the resource fork is kept at the end of
  *       the file. also, mmapping won't work for the hfs fs until it
  *       understands how to mmap header files. */
-static __inline__ int ad_header_read(struct adouble *ad)
+static int ad_header_read(struct adouble *ad, struct stat *hst)
 {
-#ifdef USE_MMAPPED_HEADERS
-    char                buf[AD_ENTRY_LEN*ADEID_MAX];
-#else /* USE_MMAPPED_HEADERS */
     char                *buf = ad->ad_data;
-#endif /* USE_MMAPPED_HEADERS */
     u_int16_t           nentries;
     int                 len;
+    ssize_t             header_len;
     static int          warning = 0;
+    struct stat         st;
 
     /* read the header */
-    if ( ad->ad_hf.adf_off != 0 ) {
-      if ( lseek( ad->ad_hf.adf_fd, 0L, SEEK_SET ) < 0L ) {
-               return( -1 );
-      }
-      ad->ad_hf.adf_off = 0;
+    if ((header_len = adf_pread( &ad->ad_hf, buf, sizeof(ad->ad_data), 0)) < 0) {
+       return -1;
     }
-
-    if (read( ad->ad_hf.adf_fd, buf, AD_HEADER_LEN) != AD_HEADER_LEN) {
-       if ( errno == 0 ) {
-           errno = EIO;
-       }
-       return( -1 );
+    if (header_len < AD_HEADER_LEN) {
+        errno = EIO;
+        return -1;
     }
-    ad->ad_hf.adf_off = AD_HEADER_LEN;
 
     memcpy(&ad->ad_magic, buf, sizeof( ad->ad_magic ));
-    memcpy(&ad->ad_version, buf + ADEDOFF_VERSION, 
-          sizeof( ad->ad_version ));
+    memcpy(&ad->ad_version, buf + ADEDOFF_VERSION, sizeof( ad->ad_version ));
 
     /* tag broken v1 headers. just assume they're all right. 
      * we detect two cases: null magic/version
@@ -378,8 +379,7 @@ static __inline__ int ad_header_read(struct adouble *ad)
       ad->ad_magic = AD_MAGIC;
       ad->ad_version = AD_VERSION1;
 
-    } else if ((ad->ad_magic == AD_MAGIC) && 
-              (ad->ad_version == AD_VERSION1)) {
+    } else if (ad->ad_magic == AD_MAGIC && ad->ad_version == AD_VERSION1) {
       if (!warning) {
        LOG(log_debug, logtype_default, "notice: fixing up byte-swapped v1 magic/version.");
        warning++;
@@ -407,66 +407,49 @@ static __inline__ int ad_header_read(struct adouble *ad)
     /* read in all the entry headers. if we have more than the 
      * maximum, just hope that the rfork is specified early on. */
     len = nentries*AD_ENTRY_LEN;
-#ifdef USE_MMAPPED_HEADERS
-    if (len > sizeof(buf))
-      len = sizeof(buf);
-#else /* USE_MMAPPED_HEADERS */
+
     if (len + AD_HEADER_LEN > sizeof(ad->ad_data))
       len = sizeof(ad->ad_data) - AD_HEADER_LEN;
+
     buf += AD_HEADER_LEN;
-#endif /* USE_MMAPPED_HEADERS */
-    if (read(ad->ad_hf.adf_fd, buf, len) != len) {
-        if (errno == 0)
-           errno = EIO;
+    if (len > header_len - AD_HEADER_LEN) {
+        errno = EIO;
        LOG(log_debug, logtype_default, "ad_header_read: can't read entry info.");
        return -1;
     }
-    ad->ad_hf.adf_off += len;
 
     /* figure out all of the entry offsets and lengths. if we aren't
      * able to read a resource fork entry, bail. */
     parse_entries(ad, buf, nentries);
     if (!ad_getentryoff(ad, ADEID_RFORK)
-#ifndef USE_MMAPPED_HEADERS
        || (ad_getentryoff(ad, ADEID_RFORK) > sizeof(ad->ad_data))
-#endif /* ! USE_MMAPPED_HEADERS */
        ) {
       LOG(log_debug, logtype_default, "ad_header_read: problem with rfork entry offset."); 
       return -1;
     }
 
-    /* read/mmap up to the beginning of the resource fork. */
-#ifdef USE_MMAPPED_HEADERS
-    ad->ad_data = mmap(NULL, ad_getentryoff(ad, ADEID_RFORK),
-                      PROT_READ | PROT_WRITE,
-                      (ad_getoflags(ad, ADFLAGS_HF) & O_RDWR) ? MAP_SHARED :
-                      MAP_PRIVATE, ad->ad_hf.adf_fd, 0);
-    if (ad->ad_data == MAP_FAILED) 
-      return -1;
-#else /* USE_MMAPPED_HEADERS */
-    buf += len;
-    len = ad_getentryoff(ad, ADEID_RFORK) - ad->ad_hf.adf_off;
-    if (read(ad->ad_hf.adf_fd, buf, len) != len) {
-        if (errno == 0)
-           errno = EIO;
+    if (ad_getentryoff(ad, ADEID_RFORK) > header_len) {
+       errno = EIO;
        LOG(log_debug, logtype_default, "ad_header_read: can't read in entries.");
        return -1;
     }
-#endif /* USE_MMAPPED_HEADERS */
     
+    if (hst == NULL) {
+        hst = &st;
+        if (fstat(ad->ad_hf.adf_fd, &st) < 0) {
+           return 1; /* fail silently */
+        }
+    }
+    ad->ad_rlen = hst->st_size - ad_getentryoff(ad, ADEID_RFORK);
+
     /* fix up broken dates */
     if (ad->ad_version == AD_VERSION1) {
-      struct stat st;
       u_int32_t aint;
       
-      if (fstat(ad->ad_hf.adf_fd, &st) < 0) {
-       return 1; /* fail silently */
-      }
-      
       /* check to see if the ad date is wrong. just see if we have
       * a modification date in the future. */
       if (((ad_getdate(ad, AD_DATE_MODIFY | AD_DATE_UNIX, &aint)) == 0) &&
-         (aint > TIMEWARP_DELTA + st.st_mtime)) {
+         (aint > TIMEWARP_DELTA + hst->st_mtime)) {
        ad_setdate(ad, AD_DATE_MODIFY | AD_DATE_UNIX, aint - AD_DATE_DELTA);
        ad_getdate(ad, AD_DATE_CREATE | AD_DATE_UNIX, &aint);
        ad_setdate(ad, AD_DATE_CREATE | AD_DATE_UNIX, aint - AD_DATE_DELTA);
@@ -488,7 +471,7 @@ static __inline__ int ad_header_read(struct adouble *ad)
  */
 char *
 ad_path( path, adflags )
-    char       *path;
+    const char *path;
     int                adflags;
 {
     static char        pathbuf[ MAXPATHLEN + 1];
@@ -528,7 +511,7 @@ ad_path( path, adflags )
 
 char 
 *ad_dir(path)
-    char               *path;
+    const char         *path;
 {
     static char                modebuf[ MAXPATHLEN + 1];
     char               *slash;
@@ -554,7 +537,7 @@ char
 
 int
 ad_mode( path, mode )
-    char               *path;
+    const char         *path;
     int                        mode;
 {
     struct stat                stbuf;
@@ -580,7 +563,7 @@ ad_mode( path, mode )
  */
 int
 ad_mkdir( path, mode )
-    char               *path;
+    const char         *path;
     int                        mode;
 {
 #ifdef DEBUG
@@ -590,34 +573,36 @@ ad_mkdir( path, mode )
 }
 
 
+static int new_rfork(const char *path, struct adouble *ad, int adflags);
+
+#ifdef  HAVE_PREAD
+#define AD_SET(a) 
+#else 
+#define AD_SET(a) a = 0
+#endif
 /*
  * It's not possible to open the header file O_RDONLY -- the read
  * will fail and return an error. this refcounts things now. 
  */
 int ad_open( path, adflags, oflags, mode, ad )
-    char               *path;
+    const char         *path;
     int                        adflags, oflags, mode;
     struct adouble     *ad;
 {
-    const struct entry  *eid;
     struct stat         st;
     char               *slash, *ad_p;
     int                        hoflags, admode;
-    u_int16_t           ashort;
 
     if (ad->ad_inited != AD_INITED) {
         ad_dfileno(ad) = -1;
         ad_hfileno(ad) = -1;
        adf_lock_init(&ad->ad_df);
        adf_lock_init(&ad->ad_hf);
-#ifdef USE_MMAPPED_HEADERS
-       ad->ad_data = MAP_FAILED;
-#endif /* USE_MMAPPED_HEADERS */
         ad->ad_inited = AD_INITED;
         ad->ad_refcount = 1;
     }
 
-    if (adflags & ADFLAGS_DF) { 
+    if ((adflags & ADFLAGS_DF)) { 
         if (ad_dfileno(ad) == -1) {
          hoflags = (oflags & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
          admode = ad_mode( path, mode ); 
@@ -628,8 +613,9 @@ int ad_open( path, adflags, oflags, mode, ad )
              }
          }
          if ( ad->ad_df.adf_fd < 0)
-               return -1;      
-         ad->ad_df.adf_off = 0;
+               return -1;
+
+         AD_SET(ad->ad_df.adf_off);
          ad->ad_df.adf_flags = hoflags;
        } 
         else {
@@ -644,215 +630,178 @@ int ad_open( path, adflags, oflags, mode, ad )
        ad->ad_df.adf_refcount++;
     }
 
-    if (adflags & ADFLAGS_HF) {
-        if (ad_hfileno(ad) == -1) {
-         ad_p = ad_path( path, adflags );
-
-         hoflags = oflags & ~O_CREAT;
-         hoflags = (hoflags & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
-         if (( ad->ad_hf.adf_fd = open( ad_p, hoflags, 0 )) < 0 ) {
-            if (errno == EACCES && !(oflags & O_RDWR)) {
-                hoflags = oflags & ~O_CREAT;
-                ad->ad_hf.adf_fd = open( ad_p, hoflags, 0 );
-            }    
-          }
-         if ( ad->ad_hf.adf_fd < 0 ) {
-           if (errno == ENOENT && (oflags & O_CREAT) ) {
-             /*
-              * We're expecting to create a new adouble header file,
-              * here.
-              * if ((oflags & O_CREAT) ==> (oflags & O_RDWR)
-              */
-             admode = ad_hf_mode(ad_mode( ad_p, mode )); 
-             errno = 0;
-             if (( ad->ad_hf.adf_fd = open( ad_p, oflags,
-                                            admode )) < 0 ) {
+    if (!(adflags & ADFLAGS_HF)) 
+        return 0;
+        
+    if (ad_hfileno(ad) != -1) { /* the file is already open */
+        if ((oflags & ( O_RDWR | O_WRONLY)) &&             
+               !(ad->ad_hf.adf_flags & ( O_RDWR | O_WRONLY))) {
+           if (adflags & ADFLAGS_DF) {
+                /* don't call with ADFLAGS_HF because we didn't open ressource fork */
+               ad_close( ad, ADFLAGS_DF );
+           }
+            errno == EACCES;
+           return -1;
+       }
+       ad_refresh(ad);
+       ad->ad_hf.adf_refcount++;
+       return 0;
+    }
+
+    ad_p = ad_path( path, adflags );
+
+    hoflags = oflags & ~O_CREAT;
+    hoflags = (hoflags & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
+    if (( ad->ad_hf.adf_fd = open( ad_p, hoflags, 0 )) < 0 ) {
+        if (errno == EACCES && !(oflags & O_RDWR)) {
+            hoflags = oflags & ~O_CREAT;
+            ad->ad_hf.adf_fd = open( ad_p, hoflags, 0 );
+        }    
+    }
+
+    if ( ad->ad_hf.adf_fd < 0 ) { 
+        if (errno == ENOENT && (oflags & O_CREAT) ) {
+           /*
+            * We're expecting to create a new adouble header file,
+            * here.
+            * if ((oflags & O_CREAT) ==> (oflags & O_RDWR)
+            */
+           admode = ad_hf_mode(ad_mode( ad_p, mode )); 
+           errno = 0;
+           if (( ad->ad_hf.adf_fd = open( ad_p, oflags,admode )) < 0 ) {
                /*
                 * Probably .AppleDouble doesn't exist, try to
                 * mkdir it.
                 */
-               if ((errno == ENOENT) && 
-                   ((adflags & ADFLAGS_NOADOUBLE) == 0)) {
-                 if (( slash = strrchr( ad_p, '/' )) == NULL ) {
-                   ad_close( ad, adflags );
-                   return( -1 );
-                 }
-                 *slash = '\0';
-                 errno = 0;
-                 if ( ad_mkdir( ad_p, 0777 ) < 0 ) {
-                   ad_close( ad, adflags );
-                   return( -1 );
-                 }
-                 *slash = '/';
-                 if (( ad->ad_hf.adf_fd = 
-                       open( ad_p, oflags, ad_mode( ad_p, mode) )) < 0 ) {
-                   ad_close( ad, adflags );
-                   return( -1 );
-                 }
+               if (errno == ENOENT && (adflags & ADFLAGS_NOADOUBLE) == 0) {
+                   if (( slash = strrchr( ad_p, '/' )) == NULL ) {
+                       ad_close( ad, adflags );
+                       return( -1 );
+                   }
+                   *slash = '\0';
+                   errno = 0;
+                   if ( ad_mkdir( ad_p, 0777 ) < 0 ) {
+                       ad_close( ad, adflags );
+                       return( -1 );
+                   }
+                   *slash = '/';
+                   if (( ad->ad_hf.adf_fd = 
+                                  open( ad_p, oflags, ad_mode( ad_p, mode) )) < 0 ) {
+                       ad_close( ad, adflags );
+                       return( -1 );
+                   }
                } else {
                  ad_close( ad, adflags );
                  return( -1 );
                }
-             }
-             ad->ad_hf.adf_flags = oflags;
-           } else {
-             ad_close( ad, adflags );
-             return( -1 );
            }
-         } else if ((fstat(ad->ad_hf.adf_fd, &st) == 0) && 
-                    (st.st_size == 0)) {
-           /* for 0 length files, treat them as new. */
-           ad->ad_hf.adf_flags = (oflags & ~O_RDONLY) | O_RDWR;
-         } else {
-           ad->ad_hf.adf_flags = hoflags;
-         }
-         ad->ad_hf.adf_off = 0;
+           ad->ad_hf.adf_flags = oflags;
+       } else {
+           ad_close( ad, adflags );
+           return( -1 );
+       }
+    } else if (fstat(ad->ad_hf.adf_fd, &st) == 0 && st.st_size == 0) {
+       /* for 0 length files, treat them as new. */
+       ad->ad_hf.adf_flags = (oflags & ~(O_RDONLY | O_WRONLY)) | O_RDWR | O_TRUNC;
+    } else {
+        ad->ad_hf.adf_flags = hoflags;
+    }
+    AD_SET(ad->ad_hf.adf_off);
          
-         /*
-          * This is a new adouble header file. Initialize the structure,
-          * instead of reading it.
-          */
-         memset(ad->ad_eid, 0, sizeof( ad->ad_eid ));
-         if ( ad->ad_hf.adf_flags & ( O_TRUNC | O_CREAT )) {
-           struct stat st;
-
-           ad->ad_magic = AD_MAGIC;
-           ad->ad_version = AD_VERSION;
-           memset(ad->ad_filler, 0, sizeof( ad->ad_filler ));
-
-#ifdef USE_MMAPPED_HEADERS
-           /* truncate the header file and mmap it. */
-           ftruncate(ad->ad_hf.adf_fd, AD_DATASZ);
-           ad->ad_data = mmap(NULL, AD_DATASZ, PROT_READ | PROT_WRITE,
-                              MAP_SHARED, ad->ad_hf.adf_fd, 0);
-           if (ad->ad_data == MAP_FAILED) {
-             ad_close(ad, adflags);
-             return -1;
-           }       
-#else /* USE_MMAPPED_HEADERS */
-           memset(ad->ad_data, 0, sizeof(ad->ad_data));
-#endif /* USE_MMAPPED_HEADERS */
-
-           eid = entry_order;
-           while (eid->id) {
-             ad->ad_eid[eid->id].ade_off = eid->offset;
-             ad->ad_eid[eid->id].ade_len = eid->len;
-             eid++;
-           }
-           
-           /* put something sane in the directory finderinfo */
-           if (adflags & ADFLAGS_DIR) {
-             /* set default view */
-             ashort = htons(FINDERINFO_CLOSEDVIEW);
-             memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRVIEWOFF, 
-                    &ashort, sizeof(ashort));
-           } else {
-             /* set default creator/type fields */
-             memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRTYPEOFF,
-                    "TEXT", 4);
-             memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRCREATOFF,
-                    "UNIX", 4);
-           }
+    memset(ad->ad_eid, 0, sizeof( ad->ad_eid ));
+    if ((ad->ad_hf.adf_flags & ( O_TRUNC | O_CREAT ))) {
+        /*
+         * This is a new adouble header file. Initialize the structure,
+         * instead of reading it.
+        */
+        if (new_rfork(path, ad, adflags) < 0) {
+            ad_close(ad, adflags);
+           return -1;
+       }
+    } else {
+           /* Read the adouble header in and parse it.*/
+       if ((ad_header_read( ad , &st) < 0)
+#if AD_VERSION == AD_VERSION2
+               || (ad_v1tov2(ad, ad_p) < 0)
+#endif /* AD_VERSION == AD_VERSION2 */
+        ) {
+            ad_close( ad, adflags );
+           return( -1 );
+       }
+    }
+    ad->ad_hf.adf_refcount++;
+    return 0 ;
+}
 
-           /* make things invisible */
-           if ((*path == '.') && strcmp(path, ".") && strcmp(path, "..")) {
-             ashort = htons(ATTRBIT_INVISIBLE);
-             ad_setattr(ad, ashort);
-             ashort = htons(FINDERINFO_INVISIBLE);
-             memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF,
-                    &ashort, sizeof(ashort));
-           }
+/* ----------------------------------- */
+static int new_rfork(const char *path, struct adouble *ad, int adflags)
+{
+#if 0
+    struct timeval      tv;
+#endif    
+    const struct entry  *eid;
+    u_int16_t           ashort;
+    struct stat         st;
 
-           /*if (gettimeofday(&tv, NULL) < 0) {
-             ad_close(ad, adflags);
-             return -1;
-           }*/
+    ad->ad_magic = AD_MAGIC;
+    ad->ad_version = AD_VERSION;
 
-           if (stat(path, &st) < 0) {
-               ad_close(ad, adflags);
-               return -1;
-           }
+    memset(ad->ad_filler, 0, sizeof( ad->ad_filler ));
+    memset(ad->ad_data, 0, sizeof(ad->ad_data));
+
+    eid = entry_order;
+    while (eid->id) {
+        ad->ad_eid[eid->id].ade_off = eid->offset;
+       ad->ad_eid[eid->id].ade_len = eid->len;
+       eid++;
+    }
            
-           /* put something sane in the date fields */
-           ad_setdate(ad, AD_DATE_CREATE | AD_DATE_UNIX, st.st_mtime);
-           ad_setdate(ad, AD_DATE_MODIFY | AD_DATE_UNIX, st.st_mtime);
-           ad_setdate(ad, AD_DATE_ACCESS | AD_DATE_UNIX, st.st_mtime);
-           ad_setdate(ad, AD_DATE_BACKUP, AD_DATE_START);
+    /* put something sane in the directory finderinfo */
+    if (adflags & ADFLAGS_DIR) {
+        /* set default view */
+       ashort = htons(FINDERINFO_CLOSEDVIEW);
+       memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRVIEWOFF, 
+                    &ashort, sizeof(ashort));
+    } else {
+        /* set default creator/type fields */
+       memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRTYPEOFF,"TEXT", 4);
+       memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRCREATOFF,"UNIX", 4);
+    }
 
-         } else {
-           /*
-            * Read the adouble header in and parse it.
-            */
-           if ((ad_header_read( ad ) < 0)
-#if AD_VERSION == AD_VERSION2
-               || (ad_v1tov2(ad, ad_p) < 0)
-#endif /* AD_VERSION == AD_VERSION2 */
-               ) {
-             ad_close( ad, adflags );
-             return( -1 );
-           }
-         }
-       }
-       else { /* already open */
-            if ((oflags & ( O_RDWR | O_WRONLY)) &&             
-               !(ad->ad_hf.adf_flags & ( O_RDWR | O_WRONLY))) {
-               if (adflags & ADFLAGS_DF) {
-                   /* don't call with ADFLAGS_HF because we didn't open ressource fork */
-                   ad_close( ad, ADFLAGS_DF );
-                }
-                 errno == EACCES;
-                return -1;
-           }
-       }
-       ad->ad_hf.adf_refcount++;
+    /* make things invisible */
+    if ((*path == '.') && strcmp(path, ".") && strcmp(path, "..")) {
+        ashort = htons(ATTRBIT_INVISIBLE);
+       ad_setattr(ad, ashort);
+       ashort = htons(FINDERINFO_INVISIBLE);
+       memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF,
+                    &ashort, sizeof(ashort));
+    }
+
+#if 0
+    if (gettimeofday(&tv, NULL) < 0) {
+       return -1;
+    } 
+#endif
+    
+    if (stat(path, &st) < 0) {
+       return -1;
     }
-       
-    return( 0 );
+           
+    /* put something sane in the date fields */
+    ad_setdate(ad, AD_DATE_CREATE | AD_DATE_UNIX, st.st_mtime);
+    ad_setdate(ad, AD_DATE_MODIFY | AD_DATE_UNIX, st.st_mtime);
+    ad_setdate(ad, AD_DATE_ACCESS | AD_DATE_UNIX, st.st_mtime);
+    ad_setdate(ad, AD_DATE_BACKUP, AD_DATE_START);
+    return 0;
 }
 
 /* to do this with mmap, we need the hfs fs to understand how to mmap
    header files. */
 int ad_refresh(struct adouble *ad)
 {
-#ifdef USE_MMAPPED_HEADERS
-  off_t off;
-#endif /* USE_MMAPPED_HEADERS */
 
   if (ad->ad_hf.adf_fd < -1)
     return -1;
 
-#ifdef USE_MMAPPED_HEADERS
-  if (ad->ad_data == MAP_FAILED)
-    return -1;
-  
-  /* re-read the header */
-  off = ad_getentryoff(ad, ADEID_RFORK);
-  memcpy(&nentries, ad->ad_data + ADEDOFF_NENTRIES, sizeof(nentries));
-  nentries = ntohs(nentries);
-  parse_entries(ad, ad->ad_data + AD_HEADER_LEN, nentries);
-
-  /* check to see if something screwy happened */
-  if (!ad_getentryoff(ad, ADEID_RFORK))
-    return -1;
-
-  /* if there's a length discrepancy, remap the header. this shouldn't
-   * really ever happen. */
-  if (off != ad_getentryoff(ad, ADEID_RFORK)) {
-    char *buf = ad->ad_data;
-    buf = ad->ad_data;
-    ad->ad_data = mmap(NULL, ad_getentryoff(ad, ADEID_RFORK), 
-                      PROT_READ | PROT_WRITE,
-                      (ad_getoflags(ad, ADFLAGS_HF) & O_RDWR) ? 
-                      MAP_SHARED : MAP_PRIVATE, ad->ad_hf.adf_fd, 0);
-    if (ad->ad_data == MAP_FAILED) {
-      ad->ad_data = buf;
-      return -1;
-    }
-    munmap(buf, off);
-  }
-  return 0;
-
-#else /* USE_MMAPPED_HEADERS */
-  return ad_header_read(ad);
-#endif /* USE_MMAPPED_HEADERS */
+  return ad_header_read(ad, NULL);
 }
index 35bcc197026c35bf87412196e99f4f2da47a2e8b..ae707cb682cddc2c8cb65758808edfa733171682 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ad_read.c,v 1.3 2001-06-29 14:14:46 rufustfirefly Exp $
+ * $Id: ad_read.c,v 1.4 2002-10-11 14:18:37 didg Exp $
  *
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
 #include "config.h"
 #endif /* HAVE_CONFIG_H */
 
+#include <atalk/adouble.h>
 #include <string.h>
-#include <sys/types.h>
 #include <sys/param.h>
-#include <atalk/adouble.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif /* HAVE_UNISTD_H */
 
 #ifndef MIN
 #define MIN(a,b)       ((a)<(b)?(a):(b))
 #endif /* ! MIN */
 
-/* XXX: this would probably benefit from pread. 
- *      locks have to be checked before each stream of consecutive 
+ssize_t adf_pread(struct ad_fd *ad_fd, void *buf, size_t count, off_t offset)
+{
+    ssize_t            cc;
+
+#ifndef  HAVE_PREAD
+    if ( ad_fd->adf_off != offset ) {
+        if ( lseek( ad_fd->adf_fd, offset, SEEK_SET ) < 0 ) {
+               return -1;
+       }
+       ad_fd->adf_off = offset;
+    }
+    if (( cc = read( ad_fd.adf_fd, buf, count )) < 0 ) {
+        return -1;
+    }
+    ad_fd->adf_off += cc;
+#else
+   cc = pread(ad_fd->adf_fd, buf, count, offset );
+#endif
+    return cc;
+}
+
+/* XXX: locks have to be checked before each stream of consecutive 
  *      ad_reads to prevent a denial in the middle from causing
  *      problems. */
 ssize_t ad_read( ad, eid, off, buf, buflen)
@@ -55,56 +71,30 @@ ssize_t ad_read( ad, eid, off, buf, buflen)
     /* We're either reading the data fork (and thus the data file)
      * or we're reading anything else (and thus the header file). */
     if ( eid == ADEID_DFORK ) {
-       if ( ad->ad_df.adf_off != off ) {
-           if ( lseek( ad->ad_df.adf_fd, (off_t) off, SEEK_SET ) < 0 ) {
-               return( -1 );
-           }
-           ad->ad_df.adf_off = off;
-       }
-       if (( cc = read( ad->ad_df.adf_fd, buf, buflen )) < 0 ) {
-           return( -1 );
-       }
-       ad->ad_df.adf_off += cc;
+        cc = adf_pread(&ad->ad_df, buf, buflen, off);
     } else {
-        cc = ad->ad_eid[eid].ade_off + off;
-
-#ifdef USE_MMAPPED_HEADERS
-       if (eid != ADEID_RFORK) {
-         memcpy(buf, ad->ad_data + cc, buflen);
-         cc = buflen;
-         goto ad_read_done;
-       }
-#endif /* USE_MMAPPED_HEADERS */       
-       if ( ad->ad_hf.adf_off != cc ) {
-         if ( lseek( ad->ad_hf.adf_fd, (off_t) cc, SEEK_SET ) < 0 ) {
-             return( -1 );
-         }
-         ad->ad_hf.adf_off = cc;
-       }
-         
-       if (( cc = read( ad->ad_hf.adf_fd, buf, buflen )) < 0 ) {
+        off_t r_off;
+        
+        r_off = ad_getentryoff(ad, eid) + off;
+       
+       if (( cc = adf_pread( &ad->ad_hf, buf, buflen, r_off )) < 0 ) {
          return( -1 );
        }
-         
-#ifndef USE_MMAPPED_HEADERS
        /*
         * We've just read in bytes from the disk that we read earlier
         * into ad_data. If we're going to write this buffer out later,
         * we need to update ad_data.
+        * FIXME : always false?
         */
-       if (ad->ad_hf.adf_off < ad_getentryoff(ad, ADEID_RFORK)) {
+       if (r_off < ad_getentryoff(ad, ADEID_RFORK)) {
            if ( ad->ad_hf.adf_flags & O_RDWR ) {
-             memcpy(buf, ad->ad_data + ad->ad_hf.adf_off,
-                    MIN(sizeof( ad->ad_data ) - ad->ad_hf.adf_off, cc));
+             memcpy(buf, ad->ad_data + r_off,
+                    MIN(sizeof( ad->ad_data ) - r_off, cc));
            } else {
-             memcpy(ad->ad_data + ad->ad_hf.adf_off, buf,
-                    MIN(sizeof( ad->ad_data ) - ad->ad_hf.adf_off, cc));
+             memcpy(ad->ad_data + r_off, buf,
+                    MIN(sizeof( ad->ad_data ) - r_off, cc));
            }
        }
-       ad->ad_hf.adf_off += cc;
-#else /* ! USE_MMAPPED_HEADERS */
-ad_read_done:
-#endif /* ! USE_MMAPPED_HEADERS */
     }
 
     return( cc );
index 9b431d0e403f5b14d4866ebea3e79825cb79eb70..35a9bccc0b0aa15b3b75ab4846d0bd7762cf5dd3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ad_sendfile.c,v 1.4 2002-01-04 04:45:48 sibaz Exp $
+ * $Id: ad_sendfile.c,v 1.5 2002-10-11 14:18:38 didg Exp $
  *
  * Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu)
  * All rights reserved. See COPYRIGHT.
 
 static int _ad_sendfile_dummy;
 
+#ifdef ATACC
+
+#if defined(HAVE_SENDFILE_READ)
+#ifdef __NR_sendfile
+int sendfile(int fdout, int fdin, off_t *off, size_t count)
+{
+#if _FILE_OFFSET_BITS == 64 
+#error sendfile
+  return syscall(__NR_sendfile64, fdout, fdin, off, count);
+#else
+  return syscall(__NR_sendfile, fdout, fdin, off, count);
+#endif
+}
+#endif
+#endif
+#endif
+
 #if defined(HAVE_SENDFILE_READ) || defined(HAVE_SENDFILE_WRITE)
 static __inline__ int ad_sendfile_init(const struct adouble *ad, 
                                       const int eid, off_t *off,
index 83e6df7beef48474c6a2146766fee79ffc3c8228..5a63fc442f6c1779105ce1bb2338b2f246ef78dd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ad_size.c,v 1.4 2002-01-04 04:45:48 sibaz Exp $
+ * $Id: ad_size.c,v 1.5 2002-10-11 14:18:38 didg Exp $
  *
  * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
  * All rights reserved. See COPYRIGHT.
@@ -30,6 +30,8 @@ off_t ad_size(const struct adouble *ad, const u_int32_t eid)
       return 0;
     return st.st_size;
   }  
-
+#if 0
   return ad_getentrylen(ad, eid);
+#endif
+  return ad->ad_rlen;  
 } 
index d680db5ac72894d0781f7d07082e1cfdc8db7910..52b33ea4ffa3db7fb2128d2c658061714a2117c3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ad_write.c,v 1.3 2001-06-29 14:14:46 rufustfirefly Exp $
+ * $Id: ad_write.c,v 1.4 2002-10-11 14:18:39 didg Exp $
  *
  * Copyright (c) 1990,1995 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -9,28 +9,44 @@
 #include "config.h"
 #endif /* HAVE_CONFIG_H */
 
+#include <atalk/adouble.h>
+
 #include <string.h>
-#include <sys/types.h>
 #include <sys/param.h>
-#include <sys/stat.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif /* HAVE_FCNTL_H */
 #include <errno.h>
 
-#include <atalk/adouble.h>
 
 #ifndef MIN
 #define MIN(a,b)       ((a)<(b)?(a):(b))
 #endif /* ! MIN */
 
-/* XXX: this would benefit from pwrite. 
- *      locking has to be checked before each stream of consecutive
+/* XXX: locking has to be checked before each stream of consecutive
  *      ad_writes to prevent a lock in the middle from causing problems. 
  */
+
+ssize_t adf_pwrite(struct ad_fd *ad_fd, const void *buf, size_t count, off_t offset)
+{
+    ssize_t            cc;
+
+#ifndef  HAVE_PWRITE
+    if ( ad_fd->adf_off != off ) {
+       if ( lseek( ad_fd->adf_fd, offset, SEEK_SET ) < 0 ) {
+           return -1;
+       }
+       ad_fd->adf_off = offset;
+    }
+    cc = write( ad_fd->adf_fd, buf, count );
+    if ( cc < 0 ) {
+        return -1;
+    }
+    ad_fd->adf_off += cc;
+#else
+   cc = pwrite(ad_fd->adf_fd, buf, count, offset );
+#endif
+    return cc;
+}
+
+
 ssize_t ad_write( ad, eid, off, end, buf, buflen )
     struct adouble     *ad;
     const u_int32_t    eid;
@@ -41,7 +57,7 @@ ssize_t ad_write( ad, eid, off, end, buf, buflen )
 {
     struct stat                st;
     ssize_t            cc;
-
+    
     if ( eid == ADEID_DFORK ) {
        if ( end ) {
            if ( fstat( ad->ad_df.adf_fd, &st ) < 0 ) {
@@ -49,56 +65,30 @@ ssize_t ad_write( ad, eid, off, end, buf, buflen )
            }
            off = st.st_size - off;
        }
+       cc = adf_pwrite(&ad->ad_df, buf, buflen, off);
+    } else if ( eid == ADEID_RFORK ) {
+        off_t    r_off;
 
-       if ( ad->ad_df.adf_off != off ) {
-           if ( lseek( ad->ad_df.adf_fd, (off_t) off, SEEK_SET ) < 0 ) {
+       if ( end ) {
+           if ( fstat( ad->ad_df.adf_fd, &st ) < 0 ) {
                return( -1 );
            }
-           ad->ad_df.adf_off = off;
-       }
-       cc = write( ad->ad_df.adf_fd, buf, buflen );
-       if ( cc < 0 ) {
-           return( -1 );
+           off = st.st_size - off -ad_getentryoff(ad, eid);
        }
-       ad->ad_df.adf_off += cc;
-    } else {
-       if ( end ) {
-           off = ad->ad_eid[ eid ].ade_len - off;
-       }
-       cc = ad->ad_eid[eid].ade_off + off;
-
-#ifdef USE_MMAPPED_HEADERS
-       if (eid != ADEID_RFORK) {
-         memcpy(ad->ad_data + cc, buf, buflen);
-         cc = buflen;
-         goto ad_write_done;
-       }         
-#endif /* ! USE_MMAPPED_HEADERS */
-
-       if ( ad->ad_hf.adf_off != cc ) {
-         if ( lseek( ad->ad_hf.adf_fd, (off_t) cc, SEEK_SET ) < 0 ) {
-             return( -1 );
-         }
-         ad->ad_hf.adf_off = cc;
-       }
-         
-       if ((cc = write( ad->ad_hf.adf_fd, buf, buflen )) < 0)
-         return( -1 );
-       ad->ad_hf.adf_off += cc;
-       
-#ifndef USE_MMAPPED_HEADERS
-       /* sync up our internal buffer */
-       if (ad->ad_hf.adf_off < ad_getentryoff(ad, ADEID_RFORK))
-         memcpy(ad->ad_data + ad->ad_hf.adf_off, buf,
-                MIN(sizeof(ad->ad_data) - ad->ad_hf.adf_off, cc));
-#else /* ! USE_MMAPPED_HEADERS */  
-ad_write_done:
-#endif /* ! USE_MMAPPED_HEADERS */
-         if ( ad->ad_eid[ eid ].ade_len < off + cc ) {
-           ad->ad_eid[ eid ].ade_len = off + cc;
-         }
+       r_off = ad_getentryoff(ad, eid) + off;
+       cc = adf_pwrite(&ad->ad_hf, buf, buflen, r_off);
+
+       /* sync up our internal buffer  FIXME always false? */
+       if (r_off < ad_getentryoff(ad, ADEID_RFORK)) {
+           memcpy(ad->ad_data + r_off, buf, MIN(sizeof(ad->ad_data) -r_off, cc));
+        }
+        if ( ad->ad_rlen  < r_off + cc ) {
+             ad->ad_rlen = r_off + cc;
+        }
+    }
+    else {
+        return -1; /* we don't know how to write if it's not a ressource or data fork */
     }
-
     return( cc );
 }
 
@@ -119,7 +109,9 @@ int ad_rtruncate( ad, size )
        errno = err;
        return( -1 );
     }
+    ad->ad_rlen = size;    
 
+#if 0
     ad->ad_eid[ ADEID_RFORK ].ade_len = size;
     if ( lseek( ad->ad_hf.adf_fd, ad->ad_eid[ADEID_RFORK].ade_off, 
                SEEK_SET ) < 0 ) {
@@ -130,6 +122,7 @@ int ad_rtruncate( ad, size )
     }
 
     ad->ad_hf.adf_off = ad->ad_eid[ADEID_RFORK].ade_off;
+#endif
     ad_tmplock(ad, ADEID_RFORK, ADLOCK_CLR, 0, 0);
     return( 0 );
 }
@@ -147,6 +140,7 @@ int ad_dtruncate(ad, size)
       err = errno;
       ad_tmplock(ad, ADEID_DFORK, ADLOCK_CLR, 0, 0);
       errno = err;
+      return -1;
     } else 
       ad_tmplock(ad, ADEID_DFORK, ADLOCK_CLR, 0, 0);
 
index 891df2e2a43517533b11a0694d8f662690af2008..54b6d456c78bb9e0dd204e0c9cebe48f4f794812 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: dsi_stream.c,v 1.8 2002-02-02 21:09:13 jmarcus Exp $
+ * $Id: dsi_stream.c,v 1.9 2002-10-11 14:18:39 didg Exp $
  *
  * Copyright (c) 1998 Adrian Sun (asun@zoology.washington.edu)
  * All rights reserved. See COPYRIGHT.
@@ -96,7 +96,7 @@ int dsi_stream_send(DSI *dsi, void *buf, size_t length)
   sigset_t oldset;
 #ifdef USE_WRITEV
   struct iovec iov[2];
-  size_t  towrite;
+  size_t towrite;
   ssize_t len;
 #endif /* USE_WRITEV */
 
@@ -170,8 +170,8 @@ int dsi_stream_send(DSI *dsi, void *buf, size_t length)
 /* read data. function on success. 0 on failure. data length gets
  * stored in length variable. this should really use size_t's, but
  * that would require changes elsewhere. */
-int dsi_stream_receive(DSI *dsi, void *buf, const int ilength,
-                      int *rlength)
+int dsi_stream_receive(DSI *dsi, void *buf, const size_t ilength,
+                      size_t *rlength)
 {
   char block[DSI_BLOCKSIZ];
 
index 5777351d09aecfa322d8c42c8ff37b4b46f0d19e..f3340ef75345a5bbfa0e5d0e1a8cc604be9f948b 100644 (file)
@@ -12,4 +12,5 @@ libutil_la_SOURCES = \
        module.c        \
        server_child.c  \
        server_lock.c   \
+       strcasestr.c    \
        strdicasecmp.c
diff --git a/libatalk/util/strcasestr.c b/libatalk/util/strcasestr.c
new file mode 100644 (file)
index 0000000..31e65be
--- /dev/null
@@ -0,0 +1,124 @@
+/* Return the offset of one string within another.
+   Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/*
+ * My personal strstr() implementation that beats most other algorithms.
+ * Until someone tells me otherwise, I assume that this is the
+ * fastest implementation of strstr() in C.
+ * I deliberately chose not to comment it.  You should have at least
+ * as much fun trying to understand it, as I had to write it :-).
+ *
+ * Stephen R. van den Berg, berg@pool.informatik.rwth-aachen.de        */
+/* added strcasestr support, davidm@lineo.com */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifndef HAVE_STRCASESTR 
+
+#if  defined HAVE_STRING_H
+# include <string.h>
+#endif
+
+typedef unsigned chartype;
+
+#include <ctype.h>
+#define VAL(x) tolower(x)
+#define FUNC strcasestr
+#undef strcasestr
+
+char * FUNC ( const char *phaystack, const char *pneedle)
+{
+       register const unsigned char *haystack, *needle;
+       register chartype b, c;
+
+       haystack = (const unsigned char *) phaystack;
+       needle = (const unsigned char *) pneedle;
+
+       b = *needle;
+       if (b != '\0') {
+               haystack--;                             /* possible ANSI violation */
+               do {
+                       c = *++haystack;
+                       if (c == '\0')
+                               goto ret0;
+               }
+               while (VAL(c) != VAL(b));
+
+               c = *++needle;
+               if (c == '\0')
+                       goto foundneedle;
+               ++needle;
+               goto jin;
+
+               for (;;) {
+                       register chartype a;
+                       register const unsigned char *rhaystack, *rneedle;
+
+                       do {
+                               a = *++haystack;
+                               if (a == '\0')
+                                       goto ret0;
+                               if (VAL(a) == VAL(b))
+                                       break;
+                               a = *++haystack;
+                               if (a == '\0')
+                                       goto ret0;
+                 shloop:}
+                       while (VAL(a) != VAL(b));
+
+                 jin:a = *++haystack;
+                       if (a == '\0')
+                               goto ret0;
+
+                       if (VAL(a) != VAL(c))
+                               goto shloop;
+
+                       rhaystack = haystack-- + 1;
+                       rneedle = needle;
+                       a = *rneedle;
+
+                       if (VAL(*rhaystack) == VAL(a))
+                               do {
+                                       if (a == '\0')
+                                               goto foundneedle;
+                                       ++rhaystack;
+                                       a = *++needle;
+                                       if (VAL(*rhaystack) != VAL(a))
+                                               break;
+                                       if (a == '\0')
+                                               goto foundneedle;
+                                       ++rhaystack;
+                                       a = *++needle;
+                               }
+                               while (VAL(*rhaystack) == VAL(a));
+
+                       needle = rneedle;       /* took the register-poor approach */
+
+                       if (a == '\0')
+                               break;
+               }
+       }
+  foundneedle:
+       return (char *) haystack;
+  ret0:
+       return 0;
+}
+#endif