+Changes in 2.2alpha3
+====================
+
+* FIX: afpd: various fixes
+* FIX: Any daemon did not run if atalkd doesn't exist (redhat/debian)
+
+Changes in 2.2alpha2
+====================
+
+* FIX: afpd: fix compilation error when ACL support is not available
+* FIX: Ensure Appletalk manpages and config files are distributed
+
+Changes in 2.2alpha1
+====================
+
+* NEW: ad utility: ad cp
+* NEW: ad utility: ad rm
+* NEW: ad utility: ad mv
+* NEW: afpd: dynamic directoy and CNID cache (new config option -dircachesize)
+* NEW: afpd: POSIX 1e ACL support
+* NEW: afpd: automagic Zeroconf registration with avahi, registering both
+ the service _afpovertcp._tcp and TimeMachine volumes with _adisk._tcp.
+* UPD: afpd: ACLs usable (though not visible on the client side) without common
+ directory service, by mapping ACLs to UARight
+* UPD: afpd: performance improvements for ACL access calculations
+* UPD: AppleTalk is disabled by default at configuration time. If needed
+ use configure switch --enable-ddp.
+* FIX: afpd: Solaris 10 compatibilty fix: don't use SO_SNDTIMEO/SO_RCVTIMEO,
+ use non-blocking IO and select instead.
+* FIX: cnid_dbd: Solaris 10 compatibilty fix: don't use SO_SNDTIMEO/SO_RCVTIMEO,
+ use non-blocking IO and select instead.
+* REM: afile/achfile/apple_cp/apple_mv/apple_rm: use ad
+
Changes in 2.1.5
================
* UPD: afpd: support newlines in -loginmesg with \n escaping syntax
* UPD: afpd: support for changed chmod semantics on ZFS with ACLs
in onnv145+
- * FIX: afpd: fix leaking resource when moving objects on the server
+ * FIX: afpd: fix leaking ressource when moving objects on the server
+ * FIX: afpd: backport Solaris 10 compatibilty fix from 2.2: don't use
+ SO_SNDTIMEO/SO_RCVTIMEO, use non-blocking IO and select instead.
+ * FIX: cnid_dbd: backport Solaris 10 compatibilty fix from 2.2: don't
+ use SO_SNDTIMEO/SO_RCVTIMEO, use non-blocking IO and select instead.
Changes in 2.1.4
================
* FIX: afpd: Better handling of symlinks in combination with ACLs and EAs.
Fixes bug 3074076.
* FIX: dbd: Adding a file with the CNID from it's adouble file did
- not work in case that CNID was alread occupied in the database
+ not work in case that CNID was already occupied in the database
* FIX: macusers: add support for Solaris
* NEW: cnid_metad: use a PID lockfile
* NEW: afpd: prevent log flooding
Changes in 2.1-beta2
====================
+
* NEW: afpd: static generated AFP signature stored in afp_signature.conf,
cf man 5 afp_signature.conf
* NEW: afpd: clustering support: new per volume option "cnidserver".
/*
- $Id: acl_mappings.h,v 1.1 2009-02-02 11:55:00 franklahm Exp $
Copyright (c) 2008,2009 Frank Lahm <franklahm@gmail.com>
This program is free software; you can redistribute it and/or modify
#ifndef ACL_MAPPINGS
#define ACL_MAPPINGS
+#ifdef HAVE_SOLARIS_ACLS
#include <sys/acl.h>
+#endif
+
#include "acls.h"
/*
* Stuff for mapping between ACL implementations
*/
+ /* Solaris 10u8 still hasn't got ACE_INHERITED_ACE */
+ #ifndef ACE_INHERITED_ACE
+ #define ACE_INHERITED_ACE 0x0080
+ #endif
+
struct ace_rights_map {
u_int32_t from;
u_int32_t to;
};
+#ifdef HAVE_SOLARIS_ACLS
struct ace_rights_map nfsv4_to_darwin_rights[] = {
{ACE_READ_DATA, DARWIN_ACE_READ_DATA},
{ACE_WRITE_DATA, DARWIN_ACE_WRITE_DATA},
{DARWIN_ACE_FLAGS_INHERITED, ACE_INHERITED_ACE},
{0,0}
};
+#endif /* HAVE_SOLARIS_ACLS */
#endif /* ACL_MAPPINGS */
/*
- * $Id: cnid_metad.c,v 1.22 2009-11-16 02:04:47 didg Exp $
- *
* Copyright (C) Joerg Lenneis 2003
- * All Rights Reserved. See COPYING.
+ * Copyright (C) Frank Lahm 2009, 2010
*
+ * All Rights Reserved. See COPYING.
*/
/*
Result:
via TCP socket
4. afpd -------> cnid_dbd
+
+ cnid_metad and cnid_dbd have been converted to non-blocking IO in 2010.
*/
#include <errno.h>
#include <string.h>
#include <signal.h>
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
-#endif
-#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
-#endif
-#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>
-#endif
#include <sys/un.h>
#define _XPG4_2 1
#include <sys/socket.h>
if (rqstfd <= 0)
continue;
- ret = readt(rqstfd, &len, sizeof(int), 4);
- /* TODO: Check out read errors, broken pipe etc. in libatalk. Is
- SIGIPE ignored there? Answer: Ignored for dsi, but not for asp ... */
- ret = readt(rqstfd, &len, sizeof(int), 1, 5);
++ ret = readt(rqstfd, &len, sizeof(int), 1, 4);
++
if (!ret) {
/* already close */
goto loop_end;
goto loop_end;
}
- actual_len = read(rqstfd, dbdir, len);
+ actual_len = readt(rqstfd, dbdir, len, 1);
if (actual_len < 0) {
LOG(log_severe, logtype_cnid, "Read(2) error : %s", strerror(errno));
goto loop_end;
/*
- * $Id: comm.c,v 1.6 2009-10-19 08:09:07 didg Exp $
- *
* Copyright (C) Joerg Lenneis 2003
+ * Copyright (C) Frank Lahm 2010
+ *
* All Rights Reserved. See COPYING.
*/
#include <stdlib.h>
#include <string.h>
#include <errno.h>
-
-#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif
-
#include <sys/param.h>
-#define _XPG4_2 1
-#include <sys/socket.h>
-
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-
-#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
-#endif
-
-#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>
-#endif
-
-#ifdef HAVE_SYS_SOCKET_H
+#define _XPG4_2 1
#include <sys/socket.h>
-#endif
-
#include <sys/select.h>
-
#include <assert.h>
#include <time.h>
#include <atalk/logger.h>
+#include <atalk/util.h>
#include <atalk/cnid_dbd_private.h>
#include "db_param.h"
if (!cur_fd)
return 0;
+
+ LOG(log_maxdebug, logtype_cnid, "comm_rcv: got data on fd %u", cur_fd);
+
+ if (setnonblock(cur_fd, 1) != 0) {
+ LOG(log_error, logtype_cnid, "comm_rcv: setnonblock: %s", strerror(errno));
+ return -1;
+ }
+
nametmp = rqst->name;
- if ((b = readt(cur_fd, rqst, sizeof(struct cnid_dbd_rqst), CNID_DBD_TIMEOUT))
- if ((b = readt(cur_fd, rqst, sizeof(struct cnid_dbd_rqst), 1, 5))
++ if ((b = readt(cur_fd, rqst, sizeof(struct cnid_dbd_rqst), 1, CNID_DBD_TIMEOUT))
!= sizeof(struct cnid_dbd_rqst)) {
if (b)
LOG(log_error, logtype_cnid, "error reading message header: %s", strerror(errno));
return 0;
}
rqst->name = nametmp;
- if (rqst->namelen && readt(cur_fd, rqst->name, rqst->namelen, CNID_DBD_TIMEOUT)
- if (rqst->namelen && readt(cur_fd, rqst->name, rqst->namelen, 1, 5) != rqst->namelen) {
++ if (rqst->namelen && readt(cur_fd, rqst->name, rqst->namelen, 1, CNID_DBD_TIMEOUT)
+ != rqst->namelen) {
LOG(log_error, logtype_cnid, "error reading message name: %s", strerror(errno));
invalidate_fd(cur_fd);
return 0;
needs zero terminated strings. */
rqst->name[rqst->namelen] = '\0';
+ LOG(log_maxdebug, logtype_cnid, "comm_rcv: got %u bytes", b + rqst->namelen);
+
return 1;
}
/*
- * $Id: usockfd.c,v 1.6 2009-11-05 14:38:07 franklahm Exp $
- *
* Copyright (C) Joerg Lenneis 2003
* All Rights Reserved. See COPYING.
*/
socklen_t size;
fd_set readfds;
int ret;
- struct timeval tv;
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);
strerror(errno));
return -1;
}
- if (setnonblock(fd, 1) != 0) {
- LOG(log_error, logtype_cnid, "setnonblock: %s", strerror(errno));
- return -1;
- }
return fd;
} else
return 0;
-/*
- * $Id: util.h,v 1.21 2010-02-28 22:29:16 didg Exp $
- */
-
/*!
* @file
* Netatalk utility functions
#define EXITERR_CONF 2 /* error in config files/cmd line parameters */
#define EXITERR_SYS 3 /* local system error */
+/* Print a SBT and exit */
+#define AFP_PANIC(why) \
+ do { \
+ netatalk_panic(why); \
+ abort(); \
+ } while(0);
+
+/* LOG assert errors */
+#ifndef NDEBUG
+#define AFP_ASSERT(b) \
+ do { \
+ if (!(b)) { \
+ AFP_PANIC(#b); \
+ } \
+ } while(0);
+#else
+#define AFP_ASSERT(b)
+#endif /* NDEBUG */
+
+#define STRCMP(a,b,c) (strcmp(a,c) b 0)
#ifdef WITH_SENDFILE
extern ssize_t sys_sendfile (int __out_fd, int __in_fd, off_t *__offset,size_t __count);
extern void bprint (char *, int);
extern int strdiacasecmp (const char *, const char *);
extern int strndiacasecmp (const char *, const char *, size_t);
-extern pid_t server_lock (char * /*program*/, char * /*file*/,
- int /*debug*/);
+extern pid_t server_lock (char * /*program*/, char * /*file*/, int /*debug*/);
extern void fault_setup (void (*fn)(void *));
+extern void netatalk_panic(const char *why);
#define server_unlock(x) (unlink(x))
/* strlcpy and strlcat are used by pam modules */
******************************************************************/
extern int setnonblock(int fd, int cmd);
- extern ssize_t readt(int socket, void *data, const size_t length, int timeout);
+ extern ssize_t readt(int socket, void *data, const size_t length, int setnonblocking, int timeout);
extern const char *getip_string(const struct sockaddr *sa);
extern unsigned int getip_port(const struct sockaddr *sa);
extern void apply_ip_mask(struct sockaddr *ai, int maskbits);
*****************************************************************/
extern const char *getcwdpath(void);
+extern char *stripped_slashes_basename(char *p);
extern int lchdir(const char *dir);
#endif /* _ATALK_UTIL_H */
if ((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
LOG(log_info, logtype_default, "tsock_getfd: socket CNID server %s:: %s",
host, strerror(errno));
- continue;
+ continue;
}
attr = 1;
sock = -1;
return -1;
}
-
+
if (connect(sock, p->ai_addr, p->ai_addrlen) == -1) {
if (errno == EINPROGRESS) {
struct timeval tv;
strerror(errno));
}
close(sock);
- sock=-1;
+ sock = -1;
continue;
}
} else {
continue;
}
}
-
+
/* We've got a socket */
break;
}
static int write_vec(int fd, struct iovec *iov, ssize_t towrite, int vecs)
{
ssize_t len;
+ int slept = 0;
+ int sleepsecs;
while (1) {
if (((len = writev(fd, iov, vecs)) == -1 && errno == EINTR))
continue;
+ if ((! slept) && len == -1 && errno == EAGAIN) {
+ sleepsecs = 5;
+ while ((sleepsecs = sleep(sleepsecs)));
+ slept = 1;
+ continue;
+ }
+
if (len == towrite) /* wrote everything out */
break;
int len;
struct iovec iov[2];
- LOG(log_debug, logtype_cnid, "init_tsock: BEGIN. Opening volume '%s', CNID Server: %s/%s",
+ LOG(log_debug, logtype_cnid, "init_tsock: BEGIN. Opening volume '%s', CNID Server: %s/%s",
db->db_dir, db->cnidserver, db->cnidport);
if ((fd = tsock_getfd(db->cnidserver, db->cnidport)) < 0)
db->db_dir, strerror(errno));
return -1;
}
-
+
LOG(log_maxdebug, logtype_cnid, "send_packet: {done}");
return 0;
}
stored = 0;
while (stored < length) {
- len = read(socket, (u_int8_t *) data + stored, length - stored);
+ len = readt(socket, (u_int8_t *) data + stored, length - stored, 0, 5);
if (len == -1) {
switch (errno) {
case EINTR:
memcpy(db->client_stamp, stamp, ADEDLEN_PRIVSYN);
memcpy(db->stamp, stamp, ADEDLEN_PRIVSYN);
}
- LOG(log_debug, logtype_cnid, "transmit: attached to '%s', stamp: '%08lx'.",
+ LOG(log_debug, logtype_cnid, "transmit: attached to '%s', stamp: '%08lx'.",
db->db_dir, *(uint64_t *)stamp);
}
if (!dbd_rpc(db, rqst, rply)) {
/*
- $Id: socket.c,v 1.6 2010-01-05 19:05:52 franklahm Exp $
Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
This program is free software; you can redistribute it and/or modify
#include <stdlib.h>
#include <string.h>
#include <errno.h>
+ #include <sys/time.h>
+ #include <time.h>
#include <atalk/logger.h>
/*!
* non-blocking drop-in replacement for read with timeout using select
*
- * @param socket (r) must be nonblocking !
- * @param data (rw) buffer for the read data
- * @param lenght (r) how many bytes to read
- * @param timeout (r) number of seconds to try reading
+ * @param socket (r) socket, if in blocking mode, pass "setnonblocking" arg as 1
+ * @param data (rw) buffer for the read data
+ * @param lenght (r) how many bytes to read
+ * @param setnonblocking (r) when non-zero this func will enable and disable non blocking
+ * io mode for the socket
+ * @param timeout (r) number of seconds to try reading
*
* @returns number of bytes actually read or -1 on fatal error
*/
- ssize_t readt(int socket, void *data, const size_t length, int timeout)
+ ssize_t readt(int socket, void *data, const size_t length, int setnonblocking, int timeout)
{
size_t stored;
ssize_t len;
- struct timeval tv;
+ struct timeval now, end, tv;
fd_set rfds;
int ret;
stored = 0;
+ if (setnonblocking) {
+ if (setnonblock(socket, 1) != 0)
+ return -1;
+ }
+
+ /* Calculate end time */
+ (void)gettimeofday(&now, NULL);
+ end = now;
+ end.tv_sec += timeout;
+
while (stored < length) {
len = read(socket, (char *) data + stored, length - stored);
if (len == -1) {
case EINTR:
continue;
case EAGAIN:
- tv.tv_usec = 0;
- tv.tv_sec = timeout;
-
FD_ZERO(&rfds);
FD_SET(socket, &rfds);
+ tv.tv_usec = 0;
+ tv.tv_sec = timeout;
+
while ((ret = select(socket + 1, &rfds, NULL, NULL, &tv)) < 1) {
switch (ret) {
case 0:
- LOG(log_warning, logtype_cnid, "select timeout 1s");
- return stored;
+ LOG(log_warning, logtype_afpd, "select timeout %d s", timeout);
+ goto exit;
+
default: /* -1 */
- LOG(log_error, logtype_cnid, "select: %s", strerror(errno));
- return -1;
+ if (errno == EINTR) {
+ (void)gettimeofday(&now, NULL);
+ if (now.tv_sec >= end.tv_sec && now.tv_usec >= end.tv_usec) {
+ LOG(log_warning, logtype_afpd, "select timeout %d s", timeout);
+ goto exit;
+ }
+ if (now.tv_usec > end.tv_usec) {
+ tv.tv_usec = 1000000 + end.tv_usec - now.tv_usec;
+ tv.tv_sec = end.tv_sec - now.tv_sec - 1;
+ } else {
+ tv.tv_usec = end.tv_usec - now.tv_usec;
+ tv.tv_sec = end.tv_sec - now.tv_sec;
+ }
+ FD_ZERO(&rfds);
+ FD_SET(socket, &rfds);
+ continue;
+ }
+ LOG(log_error, logtype_afpd, "select: %s", strerror(errno));
+ stored = -1;
+ goto exit;
}
- }
+ } /* while (select) */
continue;
- }
- LOG(log_error, logtype_cnid, "read: %s", strerror(errno));
- return -1;
- }
+ } /* switch (errno) */
+ LOG(log_error, logtype_afpd, "read: %s", strerror(errno));
+ stored = -1;
+ goto exit;
+ } /* (len == -1) */
else if (len > 0)
stored += len;
else
break;
+ } /* while (stored < length) */
+
+ exit:
+ if (setnonblocking) {
+ if (setnonblock(socket, 0) != 0)
+ return -1;
}
+
return stored;
}