+#ifdef HAVE_DIRFD
+ DIR *dp;
+#endif
+ int dfd;
+ struct vol *vol;
+ struct dir *dir;
+ u_int32_t did;
+ u_int16_t vid;
+
+ *rbuflen = 0;
+ ibuf += 2;
+
+ memcpy( &vid, ibuf, sizeof( vid ));
+ ibuf += sizeof( vid );
+ if (NULL == (vol = getvolbyvid( vid )) ) {
+ return( AFPERR_PARAM );
+ }
+
+ memcpy( &did, ibuf, sizeof( did ));
+ ibuf += sizeof( did );
+
+ /*
+ * Here's the deal:
+ * if it's CNID 2 our only choice to meet the specs is call sync.
+ * For any other CNID just sync that dir. To my knowledge the
+ * intended use of FPSyncDir is to sync the volume so all we're
+ * ever going to see here is probably CNID 2. Anyway, we' prepared.
+ */
+
+ if ( ntohl(did) == 2 ) {
+ sync();
+ } else {
+ if (NULL == ( dir = dirlookup( vol, did )) ) {
+ return afp_errno; /* was AFPERR_NOOBJ */
+ }
+
+ if (movecwd( vol, dir ) < 0 )
+ return ( AFPERR_NOOBJ );
+
+ /*
+ * Assuming only OSens that have dirfd also may require fsyncing directories
+ * in order to flush metadata e.g. Linux.
+ */
+
+#ifdef HAVE_DIRFD
+ if (NULL == ( dp = opendir( "." )) ) {
+ switch( errno ) {
+ case ENOENT :
+ return( AFPERR_NOOBJ );
+ case EACCES :
+ return( AFPERR_ACCESS );
+ default :
+ return( AFPERR_PARAM );
+ }
+ }
+
+ LOG(log_debug, logtype_afpd, "afp_syncdir: dir: '%s'", dir->d_u_name);
+
+ dfd = dirfd( dp );
+ if ( fsync ( dfd ) < 0 )
+ LOG(log_error, logtype_afpd, "afp_syncdir(%s): %s",
+ dir->d_u_name, strerror(errno) );
+ closedir(dp); /* closes dfd too */
+#endif
+
+ if ( -1 == (dfd = open(vol->ad_path(".", ADFLAGS_DIR), O_RDWR))) {
+ switch( errno ) {
+ case ENOENT:
+ return( AFPERR_NOOBJ );
+ case EACCES:
+ return( AFPERR_ACCESS );
+ default:
+ return( AFPERR_PARAM );
+ }
+ }
+
+ LOG(log_debug, logtype_afpd, "afp_syncdir: ad-file: '%s'",
+ vol->ad_path(".", ADFLAGS_DIR) );
+
+ if ( fsync(dfd) < 0 )
+ LOG(log_error, logtype_afpd, "afp_syncdir(%s): %s",
+ vol->ad_path(dir->d_u_name, ADFLAGS_DIR), strerror(errno) );
+ close(dfd);
+ }
+
+ return ( AFP_OK );
+}
+
+int afp_createdir(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
+{
+ struct adouble ad;
+ struct vol *vol;
+ struct dir *dir;
+ char *upath;