* 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
================
/*
- $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
* 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;
if (rqstfd <= 0)
continue;
- ret = readt(rqstfd, &len, sizeof(int), 4);
+ ret = readt(rqstfd, &len, sizeof(int), 1, 4);
+
if (!ret) {
/* already close */
goto loop_end;
}
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, 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, CNID_DBD_TIMEOUT)
!= rqst->namelen) {
LOG(log_error, logtype_cnid, "error reading message name: %s", strerror(errno));
invalidate_fd(cur_fd);
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;
******************************************************************/
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);
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;
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)) {
#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;
}