#include "ustcomm.h"
#include "usterr.h"
+#include "share.h"
#define UNIX_PATH_MAX 108
-#define MSG_MAX 1000
+#define MSG_MAX 10000
/* FIXME: ustcomm blocks on message sending, which might be problematic in
* some cases. Fix the poll() usage so sends are buffered until they don't
// backtrace_symbols_fd(buffer, result, STDERR_FILENO);
//}
+static int mkdir_p(const char *path, mode_t mode)
+{
+ const char *path_p;
+ char *tmp;
+
+ int retval = 0;
+ int result;
+
+ tmp = malloc(strlen(path) + 1);
+ if (tmp == NULL)
+ return -1;
+
+ /* skip first / */
+ path_p = path+1;
+
+ for(;;) {
+ while (*path_p != '/') {
+ if(*path_p == 0)
+ break;
+ ++path_p;
+ }
+ if (*path_p == '/') {
+ strncpy(tmp, path, path_p - path);
+ tmp[path_p-path] = '\0';
+ if (tmp[path_p - path - 1] != '/') {
+ result = mkdir(tmp, mode);
+ if(result == -1) {
+ if (!(errno == EEXIST || errno == EACCES || errno == EROFS)) {
+ /* Then this is a real error */
+ retval = -1;
+ break;
+ }
+ }
+ }
+ /* pass / */
+ path_p++;
+ } else {
+ /* last component */
+ result = mkdir(path, mode);
+ if (result == -1)
+ retval = -1;
+ break;
+ }
+ }
+
+ free(tmp);
+ return retval;
+}
+
char *strdup_malloc(const char *s)
{
char *retval;
return 1;
}
+/* Send a message
+ *
+ * @fd: file descriptor to send to
+ * @msg: a null-terminated string containing the message to send
+ *
+ * Return value:
+ * -1: error
+ * 0: connection closed
+ * 1: success
+ */
+
static int send_message_fd(int fd, const char *msg)
{
int result;
- result = send(fd, msg, strlen(msg), MSG_NOSIGNAL);
+ /* Send including the final \0 */
+ result = patient_send(fd, msg, strlen(msg)+1, MSG_NOSIGNAL);
if(result == -1) {
- PERROR("send");
+ if(errno != EPIPE)
+ PERROR("send");
return -1;
}
else if(result == 0) {
return 0;
}
+ DBG("sent message \"%s\"", msg);
return 1;
}
}
/* returns 1 to indicate a message was received
- * returns 0 to indicate no message was received (cannot happen)
+ * returns 0 to indicate no message was received (end of stream)
* returns -1 to indicate an error
*/
-static int recv_message_fd(int fd, char **msg, struct ustcomm_source *src)
+#define RECV_INCREMENT 1
+#define RECV_INITIAL_BUF_SIZE 10
+
+static int recv_message_fd(int fd, char **msg)
{
int result;
+ int buf_alloc_size = 0;
+ char *buf = NULL;
+ int buf_used_size = 0;
- *msg = (char *) malloc(MSG_MAX+1);
+ buf = malloc(RECV_INITIAL_BUF_SIZE);
+ buf_alloc_size = RECV_INITIAL_BUF_SIZE;
- result = recv(fd, *msg, MSG_MAX, 0);
- if(result == -1) {
- PERROR("recv");
- return -1;
- }
+ for(;;) {
+ if(buf_used_size + RECV_INCREMENT > buf_alloc_size) {
+ char *new_buf;
+ buf_alloc_size *= 2;
+ new_buf = (char *) realloc(buf, buf_alloc_size);
+ if(new_buf == NULL) {
+ ERR("realloc returned NULL");
+ free(buf);
+ return -1;
+ }
+ buf = new_buf;
+ }
- (*msg)[result] = '\0';
-
- DBG("ustcomm_app_recv_message: result is %d, message is %s", result, (*msg));
+ /* FIXME: this is really inefficient; but with count>1 we would
+ * need a buffering mechanism */
+ result = recv(fd, buf+buf_used_size, RECV_INCREMENT, 0);
+ if(result == -1) {
+ free(buf);
+ if(errno != ECONNRESET)
+ PERROR("recv");
+ return -1;
+ }
+ if(result == 0) {
+ if(buf_used_size)
+ goto ret;
+ else {
+ free(buf);
+ return 0;
+ }
+ }
- if(src)
- src->fd = fd;
+ buf_used_size += result;
+
+ if(buf[buf_used_size-1] == 0) {
+ goto ret;
+ }
+ }
+
+ret:
+ *msg = buf;
+ DBG("received message \"%s\"", buf);
return 1;
+
}
int ustcomm_send_reply(struct ustcomm_server *server, char *msg, struct ustcomm_source *src)
for(idx=1; idx<n_fds; idx++) {
if(fds[idx].revents) {
- retval = recv_message_fd(fds[idx].fd, msg, src);
- if(**msg == 0) {
+ retval = recv_message_fd(fds[idx].fd, msg);
+ if(src)
+ src->fd = fds[idx].fd;
+
+ if(retval == 0) {
/* connection finished */
close(fds[idx].fd);
{
int result;
- result = send(conn->fd, req, strlen(req), MSG_NOSIGNAL);
- if(result == -1) {
- if(errno != EPIPE)
- PERROR("send");
- return -1;
- }
+ /* Send including the final \0 */
+ result = send_message_fd(conn->fd, req);
+ if(result != 1)
+ return result;
if(!reply)
return 1;
- *reply = (char *) malloc(MSG_MAX+1);
- result = recv(conn->fd, *reply, MSG_MAX, 0);
+ result = recv_message_fd(conn->fd, reply);
if(result == -1) {
- if(errno != ECONNRESET)
- PERROR("recv");
return -1;
}
else if(result == 0) {
return 0;
}
- (*reply)[result] = '\0';
-
return 1;
}
result = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
if(result == -1) {
- PERROR("connect");
+ PERROR("connect (path=%s)", path);
return -1;
}
}
else if(result == -1) {
/* ENOENT */
- char buf[200];
int result;
- result = snprintf(buf, sizeof(buf), "mkdir -p \"%s\"", dir);
- if(result >= sizeof(buf)) {
- ERR("snprintf buffer overflow");
- return -1;
- }
- result = system(buf);
+ result = mkdir_p(dir, 0777);
if(result != 0) {
- ERR("executing command %s", buf);
+ ERR("executing in recursive creation of directory %s", dir);
return -1;
}
}