/* FD stream context */
typedef struct {
const SilcStreamOps *ops;
+ SilcStack stack;
SilcSchedule schedule;
SilcStreamNotifier notifier;
void *notifier_context;
int fd1;
int fd2;
- int error;
} *SilcFDStream;
/* Create file descriptor stream */
-SilcStream silc_fd_stream_create(int fd)
+SilcStream silc_fd_stream_create(int fd, SilcStack stack)
{
- if (fd < 1)
+ if (fd < 1) {
+ silc_set_errno_reason(SILC_ERR_BAD_FD, "Bad file descriptor %d", fd);
return NULL;
- return silc_fd_stream_create2(fd, 0);
+ }
+ return silc_fd_stream_create2(fd, 0, stack);
}
/* Create stream with two file descriptors */
-SilcStream silc_fd_stream_create2(int read_fd, int write_fd)
+SilcStream silc_fd_stream_create2(int read_fd, int write_fd, SilcStack stack)
{
SilcFDStream stream;
- if (read_fd < 1)
- return NULL;
+ if (stack)
+ stack = silc_stack_alloc(0, stack);
- stream = silc_calloc(1, sizeof(*stream));
- if (!stream)
+ stream = silc_scalloc(stack, 1, sizeof(*stream));
+ if (!stream) {
+ silc_stack_free(stack);
return NULL;
+ }
SILC_LOG_DEBUG(("Creating new fd stream %p", stream));
stream->ops = &silc_fd_stream_ops;
stream->fd1 = read_fd;
stream->fd2 = write_fd;
+ stream->stack = stack;
return stream;
}
/* Create by opening file */
-SilcStream silc_fd_stream_file(const char *filename,
- SilcBool reading, SilcBool writing)
+SilcStream silc_fd_stream_file(const char *filename, SilcBool reading,
+ SilcBool writing, SilcStack stack)
{
- int fd, flags = 0;
- SilcStream stream;
+ const char *read_file = NULL, *write_file = NULL;
- if (!filename)
+ if (!filename) {
+ silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
return NULL;
+ }
- SILC_LOG_DEBUG(("Creating new fd stream for file `%s'", filename));
-
- if (reading)
- flags |= O_RDONLY;
if (writing)
- flags |= O_CREAT | O_WRONLY;
- if (reading && writing)
- flags = O_CREAT | O_RDWR;
+ write_file = filename;
+ if (reading)
+ read_file = filename;
- fd = silc_file_open(filename, flags);
- if (fd < 0)
- return NULL;
+ return silc_fd_stream_file2(read_file, write_file, stack);
+}
+
+/* Create by opening two files */
+
+SilcStream silc_fd_stream_file2(const char *read_file, const char *write_file,
+ SilcStack stack)
+{
+ SilcStream stream;
+ int fd1 = 0, fd2 = 0;
- stream = silc_fd_stream_create(fd);
- if (!stream)
- silc_file_close(fd);
+ SILC_LOG_DEBUG(("Creating new fd stream for reading `%s' and writing `%s'",
+ read_file ? read_file : "(none)",
+ write_file ? write_file : "(none)"));
+
+ if (write_file) {
+ fd2 = silc_file_open(write_file, O_CREAT | O_WRONLY);
+ if (fd2 < 0) {
+ silc_file_close(fd1);
+ return NULL;
+ }
+ }
+
+ if (read_file) {
+ fd1 = silc_file_open(read_file, O_RDONLY);
+ if (fd1 < 0)
+ return NULL;
+ }
+
+ stream = silc_fd_stream_create2(fd1, fd2, stack);
+ if (!stream) {
+ silc_file_close(fd1);
+ silc_file_close(fd2);
+ }
return stream;
}
return TRUE;
}
-/* Return errno */
-
-int silc_fd_stream_get_error(SilcStream stream)
-{
- SilcFDStream fd_stream = stream;
-
- if (!SILC_IS_FD_STREAM(fd_stream))
- return 0;
-
- return fd_stream->error;
-}
-
/* Read */
int silc_fd_stream_read(SilcStream stream, unsigned char *buf,
SILC_LOG_DEBUG(("Could not read immediately, will do it later"));
silc_schedule_set_listen_fd(fd_stream->schedule, fd_stream->fd1,
SILC_TASK_READ, FALSE);
+ silc_set_errno_posix(errno);
return -1;
}
SILC_LOG_DEBUG(("Cannot read from fd: %d:%s",
fd_stream->fd1, strerror(errno)));
silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd1);
- fd_stream->error = errno;
+ silc_set_errno_posix(errno);
return -2;
}
SILC_LOG_DEBUG(("Could not write immediately, will do it later"));
silc_schedule_set_listen_fd(fd_stream->schedule, fd_stream->fd2,
SILC_TASK_READ | SILC_TASK_WRITE, FALSE);
+ silc_set_errno_posix(errno);
return -1;
}
SILC_LOG_DEBUG(("Cannot write to fd: %s", strerror(errno)));
silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd2);
- fd_stream->error = errno;
+ silc_set_errno_posix(errno);
return -2;
}
void silc_fd_stream_destroy(SilcStream stream)
{
+ SilcFDStream fd_stream = stream;
+ SilcStack stack = fd_stream->stack;
+
silc_fd_stream_close(stream);
- silc_free(stream);
+ silc_sfree(stack, stream);
+ silc_stack_free(stack);
}
/* Sets stream notification callback for the stream */
silc_fd_stream_io, stream);
silc_schedule_set_listen_fd(schedule, fd_stream->fd1,
SILC_TASK_READ, FALSE);
- silc_file_set_nonblock(fd_stream->fd1);;
+ silc_file_set_nonblock(fd_stream->fd1);
if (fd_stream->fd2 < 1)
fd_stream->fd2 = fd_stream->fd1;
}