diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile | 1 | ||||
-rw-r--r-- | src/file_list.c | 145 | ||||
-rw-r--r-- | src/file_list.h | 51 | ||||
-rw-r--r-- | src/writer.c | 96 | ||||
-rw-r--r-- | src/writer.h | 13 |
5 files changed, 218 insertions, 88 deletions
diff --git a/src/Makefile b/src/Makefile index e104c75..4046ec6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -37,6 +37,7 @@ C_OBJS := log.o \ slist.o \ string_list.o \ writer.o \ + file_list.o \ rharchive.o C_SRCS := $(C_OBJS:%.o=%.c) diff --git a/src/file_list.c b/src/file_list.c new file mode 100644 index 0000000..823c041 --- /dev/null +++ b/src/file_list.c @@ -0,0 +1,145 @@ +/* + * rharchive + * + * rharchive is a simple tcp connection proxy which combines the + * features of rinetd and 6tunnel. rharchive supports IPv4 and + * IPv6 and also supports connections from IPv6 to IPv4 + * endpoints and vice versa. + * + * + * Copyright (C) 2010-2011 Christian Pointner <equinox@helsinki.at> + * + * This file is part of rharchive. + * + * rharchive is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * rharchive is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with rharchive. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <time.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> + +#include "datatypes.h" +#include "file_list.h" +#include "slist.h" +#include "log.h" + +static void delete_file(void* element) +{ + file_t* deletee = (file_t*)element; + if(deletee->path_) free(deletee->path_); + if(deletee->fd_ >= 0) close(deletee->fd_); +} + +int file_list_init(file_list_t* list) +{ + return slist_init(list, &delete_file); +} + +void file_list_clear(file_list_t* list) +{ + slist_clear(list); +} + +file_t* file_list_add(file_list_t* list, struct tm* time, const char* type, const char* format, const char* dir, mode_t mode) +{ + if(!list) + return NULL; + + file_t* tmp = malloc(sizeof(file_t)); + if(!tmp) + return NULL; + + log_printf(INFO, "%s time: %02d:%02d:%02d on %d.%d.%d", type, time->tm_hour, time->tm_min, time->tm_sec, time->tm_mday, time->tm_mon+1, time->tm_year+1900); + + char name[256]; + strftime(name, sizeof(name), format, time); + asprintf(&(tmp->path_), "%s/%s", dir, name); + if(!tmp->path_) { + free(tmp); + return NULL; + } + + log_printf(INFO, "%s filename is: %s(.?)", type, tmp->path_); + tmp->fd_ = -1; + tmp->mode_ = mode; + + if(slist_add(list, tmp) == NULL) { + free(tmp->path_); + free(tmp); + return NULL; + } + + return tmp; +} + +int file_list_remove(file_list_t* list, int fd) +{ + if(!list) + return -1; + + slist_element_t* tmp = list->first_; + while(tmp) { + if(((file_t*)tmp->data_)->fd_ == fd) { + slist_remove(list, tmp); + break; + } + tmp = tmp->next_; + } +} + +int open_file(file_t* file) +{ + if(file->fd_ > 0) // file already open! + return -1; + + char* orig_path = file->path_; + int cnt = 0; + do { + file->fd_ = open(file->path_, O_WRONLY | O_CREAT | O_EXCL, file->mode_); + if(file->fd_ < 0) { + if(errno != EEXIST) { + // TODO: thread safe strerror + log_printf(ERROR, "can't open file '%s': %s", file->path_, strerror(errno)); + if(orig_path != file->path_) + free(orig_path); + return -1; + } + cnt++; + char* tmp; + asprintf(&tmp, "%s.%d", orig_path, cnt); + if(!tmp) { + if(orig_path != file->path_) + free(orig_path); + return -2; + } + + if(file->path_ != orig_path) + free(file->path_); + file->path_ = tmp; + } + fchmod(file->fd_, file->mode_); + } + while(file->fd_ < 0); + + if(orig_path != file->path_) + free(orig_path); + + return 0; +} diff --git a/src/file_list.h b/src/file_list.h new file mode 100644 index 0000000..fcef137 --- /dev/null +++ b/src/file_list.h @@ -0,0 +1,51 @@ +/* + * rharchive + * + * rharchive is a simple tcp connection proxy which combines the + * features of rinetd and 6tunnel. rharchive supports IPv4 and + * IPv6 and also supports connections from IPv6 to IPv4 + * endpoints and vice versa. + * + * + * Copyright (C) 2010-2011 Christian Pointner <equinox@helsinki.at> + * + * This file is part of rharchive. + * + * rharchive is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * rharchive is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with rharchive. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef RHARCHIVE_file_list_h_INCLUDED +#define RHARCHIVE_file_list_h_INCLUDED + +#include <sys/types.h> +#include <time.h> + +#include "slist.h" + +struct file_struct { + int fd_; + char* path_; + mode_t mode_; +}; +typedef struct file_struct file_t; + +typedef slist_t file_list_t; + +int file_list_init(file_list_t* list); +void file_list_clear(file_list_t* list); +file_t* file_list_add(file_list_t* list, struct tm* time, const char* type, const char* format, const char* dir, mode_t mode); +int file_list_remove(file_list_t* list, int fd); +int open_file(file_t* file); + +#endif diff --git a/src/writer.c b/src/writer.c index f89adfb..c767c5b 100644 --- a/src/writer.c +++ b/src/writer.c @@ -28,8 +28,6 @@ #include <gst/gst.h> #include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> #include <errno.h> #include <string.h> @@ -39,23 +37,7 @@ #include "datatypes.h" #include "log.h" - -static int compute_filname(struct tm* time, const char* type, file_t* file, const char* format, const char* dir, mode_t mode) -{ - log_printf(INFO, "%s time: %02d:%02d:%02d on %d.%d.%d", type, time->tm_hour, time->tm_min, time->tm_sec, time->tm_mday, time->tm_mon+1, time->tm_year+1900); - - char name[256]; - strftime(name, sizeof(name), format, time); - asprintf(&(file->path_), "%s/%s", dir, name); - if(!file->path_) - return -2; - - log_printf(INFO, "%s filename is: %s(.?)", type, file->path_); - file->fd_ = -1; - file->mode_ = mode; - - return 0; -} +#include "file_list.h" static int init_time_boundaries(writer_t* writer) { @@ -68,8 +50,8 @@ static int init_time_boundaries(writer_t* writer) struct tm bd_time; localtime_r(&(now.tv_sec), &bd_time); - int ret = compute_filname(&bd_time, "current", &(writer->current_), writer->name_format_, writer->output_dir_, writer->mode_); - if(ret) return ret; + writer->current_ = file_list_add(&(writer->files_), &bd_time, "current", writer->name_format_, writer->output_dir_, writer->mode_); + if(writer->current_ == NULL) return -2; bd_time.tm_sec = 0; bd_time.tm_min = 0; @@ -80,7 +62,10 @@ static int init_time_boundaries(writer_t* writer) struct timespec b = { T, 0 }; writer->next_boundary_ = b; - return compute_filname(&bd_time, "next", &(writer->next_), writer->name_format_, writer->output_dir_, writer->mode_); + writer->next_ = file_list_add(&(writer->files_), &bd_time, "next", writer->name_format_, writer->output_dir_, writer->mode_); + if(writer->next_ == NULL) return -2; + + return 0; } int writer_init(writer_t* writer, GMainLoop *loop, const char* name_format, mode_t mode, const char* output_dir, int interval, int offset) @@ -104,51 +89,12 @@ int writer_init(writer_t* writer, GMainLoop *loop, const char* name_format, mode writer->output_dir_ = output_dir; writer->interval_ = interval * GST_MSECOND; writer->offset_ = offset * GST_MSECOND; - writer->current_.path_ = NULL; - writer->next_.path_ = NULL; writer->clock_id_ = NULL; writer->thread_ = NULL; - return init_time_boundaries(writer); -} - -static int open_file(file_t* file) -{ - if(file->fd_ > 0) // file already open! - return -1; - - char* orig_path = file->path_; - int cnt = 0; - do { - file->fd_ = open(file->path_, O_WRONLY | O_CREAT | O_EXCL, file->mode_); - if(file->fd_ < 0) { - if(errno != EEXIST) { - // TODO: thread safe strerror - log_printf(ERROR, "can't open file '%s': %s", file->path_, strerror(errno)); - if(orig_path != file->path_) - free(orig_path); - return -1; - } - cnt++; - char* tmp; - asprintf(&tmp, "%s.%d", orig_path, cnt); - if(!tmp) { - if(orig_path != file->path_) - free(orig_path); - return -2; - } - - if(file->path_ != orig_path) - free(file->path_); - file->path_ = tmp; - } - fchmod(file->fd_, file->mode_); - } - while(file->fd_ < 0); - - if(orig_path != file->path_) - free(orig_path); + int ret = file_list_init(&(writer->files_)); + if(ret) return ret; - return 0; + return init_time_boundaries(writer); } static int check_boundaries(writer_t* writer) @@ -164,28 +110,24 @@ static int check_boundaries(writer_t* writer) localtime_r(&(now.tv_sec), &now_bd); log_printf(DEBUG, "boundary reached! it's now: %02d:%02d:%02d.%06d on %d.%d.%d", now_bd.tm_hour, now_bd.tm_min, now_bd.tm_sec, now.tv_nsec/1000, now_bd.tm_mday, now_bd.tm_mon+1, now_bd.tm_year+1900); - int ret = open_file(&(writer->next_)); + int ret = open_file(writer->next_); // if(ret) return ret; // TODO: stop writer on open_file error ??? // - add new file // - remove old file - writer->old_ = writer->current_; + int old_fd = writer->current_->fd_; writer->current_ = writer->next_; writer->next_boundary_.tv_sec += 3600; struct tm bd_time; localtime_r(&(writer->next_boundary_.tv_sec), &bd_time); - ret = compute_filname(&bd_time, "next", &(writer->next_), writer->name_format_, writer->output_dir_, writer->mode_); - if(ret) return ret; - + writer->next_ = file_list_add(&(writer->files_), &bd_time, "next", writer->name_format_, writer->output_dir_, writer->mode_); + if(writer->next_ == NULL) return -2; // - call post processing script from fd_removed callback - if(writer->old_.fd_ > 0) - close(writer->old_.fd_); - if(writer->old_.path_) - free(writer->old_.path_); + file_list_remove(&(writer->files_), old_fd); } return 0; @@ -220,7 +162,7 @@ int writer_start(writer_t* writer) if(!writer) return -1; - int ret = open_file(&(writer->current_)); + int ret = open_file(writer->current_); if(ret) return ret; @@ -245,11 +187,7 @@ void writer_stop(writer_t* writer) if(!writer) return; - if(writer->current_.path_) free(writer->current_.path_); - if(writer->current_.fd_ >= 0) close(writer->current_.fd_); - if(writer->next_.path_) free(writer->next_.path_); - if(writer->next_.fd_ >= 0) close(writer->next_.fd_); - + file_list_clear(&(writer->files_)); if(writer->clock_id_) { gst_clock_id_unschedule(writer->clock_id_); } diff --git a/src/writer.h b/src/writer.h index 93eff85..e732b28 100644 --- a/src/writer.h +++ b/src/writer.h @@ -33,12 +33,7 @@ #include <time.h> #include <sys/types.h> -struct file_struct { - int fd_; - char* path_; - mode_t mode_; -}; -typedef struct file_struct file_t; +#include "file_list.h" struct writer_struct { GMainLoop *loop_; @@ -51,9 +46,9 @@ struct writer_struct { mode_t mode_; GstClockTime interval_; GstClockTime offset_; - file_t old_; - file_t current_; - file_t next_; + file_list_t files_; + file_t* current_; + file_t* next_; struct timespec next_boundary_; }; typedef struct writer_struct writer_t; |