Commit 82adb5ff authored by Mikhail Karpenko's avatar Mikhail Karpenko

Add free disk space detection

parent 28233c9b
...@@ -19,11 +19,12 @@ ...@@ -19,11 +19,12 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/uio.h>
#include <errno.h> #include <errno.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/uio.h>
#include <sys/stat.h>
#include <string.h> #include <string.h>
#include "camogm_ogm.h" #include "camogm_ogm.h"
...@@ -799,9 +800,6 @@ void camogm_set_prefix(camogm_state *state, const char * p, path_type type) ...@@ -799,9 +800,6 @@ void camogm_set_prefix(camogm_state *state, const char * p, path_type type)
} else { } else {
D0(fprintf(debug_file, "WARNING: raw device write initiated\n")); D0(fprintf(debug_file, "WARNING: raw device write initiated\n"));
state->rawdev_op = 1; state->rawdev_op = 1;
/* debug code follows */
state->rawdev.end_pos = 20971520; // 20Mib size
/* end of debug code */
} }
} }
} }
...@@ -997,7 +995,7 @@ void camogm_status(camogm_state *state, char * fn, int xml) ...@@ -997,7 +995,7 @@ void camogm_status(camogm_state *state, char * fn, int xml)
char *_active = is_chn_active(state, chn) ? "yes" : "no"; char *_active = is_chn_active(state, chn) ? "yes" : "no";
fprintf(f, fprintf(f,
"\t<sensor_port_%d>\n" \ "\t<sensor_port_%d>\n" \
"\t\t<channel_active>\"%s\"<\channel_active>\n" \ "\t\t<channel_active>\"%s\"</channel_active>\n" \
"\t\t<compressor_state>\"%s\"</compressor_state>\n" \ "\t\t<compressor_state>\"%s\"</compressor_state>\n" \
"\t\t<frame_size>%d</frame_size>\n" \ "\t\t<frame_size>%d</frame_size>\n" \
"\t\t<frames_skip>%d</frames_skip>\n" \ "\t\t<frames_skip>%d</frames_skip>\n" \
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#define CAMOGM_FRAME_MALLOC 7 ///< can not allocate memory #define CAMOGM_FRAME_MALLOC 7 ///< can not allocate memory
#define CAMOGM_TOO_EARLY 8 ///< too early to start, waiting for particular timestamp #define CAMOGM_TOO_EARLY 8 ///< too early to start, waiting for particular timestamp
#define CAMOGM_FRAME_OTHER 9 ///< other errors #define CAMOGM_FRAME_OTHER 9 ///< other errors
#define CAMOGM_NO_SPACE 10 ///< no free space left on current file system
#define CAMOGM_FORMAT_NONE 0 ///< no video output #define CAMOGM_FORMAT_NONE 0 ///< no video output
#define CAMOGM_FORMAT_OGM 1 ///< output as Ogg Media file #define CAMOGM_FORMAT_OGM 1 ///< output as Ogg Media file
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <errno.h> #include <errno.h>
#include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <string.h> #include <string.h>
......
...@@ -40,6 +40,8 @@ ...@@ -40,6 +40,8 @@
#include <fcntl.h> #include <fcntl.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <errno.h> #include <errno.h>
#include <string.h>
#include <unistd.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include "camogm_kml.h" #include "camogm_kml.h"
......
...@@ -43,6 +43,10 @@ ...@@ -43,6 +43,10 @@
#include <fcntl.h> #include <fcntl.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <errno.h> #include <errno.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include "camogm_mov.h" #include "camogm_mov.h"
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <errno.h> #include <errno.h>
#include <string.h>
#include "camogm_ogm.h" #include "camogm_ogm.h"
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <time.h> #include <time.h>
#include <ctype.h> #include <ctype.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <sys/statvfs.h>
#include "camogm_read.h" #include "camogm_read.h"
...@@ -42,6 +43,8 @@ ...@@ -42,6 +43,8 @@
#define PHY_BLK_SZ 4096 #define PHY_BLK_SZ 4096
/** @brief Include or exclude file start and stop markers from resulting file. This must be set to 1 for JPEG files */ /** @brief Include or exclude file start and stop markers from resulting file. This must be set to 1 for JPEG files */
#define INCLUDE_MARKERS 1 #define INCLUDE_MARKERS 1
/** @brief The amount of free disk space in bytes that should be left on the device during copying from raw device buffer to this disk */
#define FREE_SIZE_LIMIT 10485760
/** @brief File starting marker on a raw device. It corresponds to SOI JPEG marker */ /** @brief File starting marker on a raw device. It corresponds to SOI JPEG marker */
static unsigned char elphelst[] = {0xff, 0xd8}; static unsigned char elphelst[] = {0xff, 0xd8};
/** @brief File ending marker on a raw device. It corresponds to EOI JPEG marker */ /** @brief File ending marker on a raw device. It corresponds to EOI JPEG marker */
...@@ -249,8 +252,6 @@ static int find_marker(const unsigned char * restrict buff_ptr, ssize_t buff_sz, ...@@ -249,8 +252,6 @@ static int find_marker(const unsigned char * restrict buff_ptr, ssize_t buff_sz,
*/ */
static void ifd_byte_order(struct ifd_entry *ifd) static void ifd_byte_order(struct ifd_entry *ifd)
{ {
unsigned long offset;
ifd->tag = __be16_to_cpu(ifd->tag); ifd->tag = __be16_to_cpu(ifd->tag);
ifd->format = __be16_to_cpu(ifd->format); ifd->format = __be16_to_cpu(ifd->format);
ifd->len = __be32_to_cpu(ifd->len); ifd->len = __be32_to_cpu(ifd->len);
...@@ -281,12 +282,12 @@ static void hdr_byte_order(struct tiff_hdr *hdr) ...@@ -281,12 +282,12 @@ static void hdr_byte_order(struct tiff_hdr *hdr)
* @param[out] buff buffer for the string * @param[out] buff buffer for the string
* @return The number of bytes placed to the read buffer * @return The number of bytes placed to the read buffer
*/ */
static size_t exif_get_text(camogm_state *state, struct ifd_entry *ifd, unsigned char *buff) static size_t exif_get_text(camogm_state *state, struct ifd_entry *ifd, char *buff)
{ {
size_t j = 0; size_t j = 0;
size_t sz = ifd->len * exif_data_fmt[ifd->format]; size_t sz = ifd->len * exif_data_fmt[ifd->format];
uint64_t curr_pos = state->rawdev.file_start + TIFF_HDR_OFFSET + ifd->offset; uint64_t curr_pos = state->rawdev.file_start + TIFF_HDR_OFFSET + ifd->offset;
unsigned char read_buff[MAX_EXIF_SIZE] = {0}; char read_buff[MAX_EXIF_SIZE] = {0};
lseek64(state->rawdev.rawdev_fd, curr_pos, SEEK_SET); lseek64(state->rawdev.rawdev_fd, curr_pos, SEEK_SET);
read(state->rawdev.rawdev_fd, read_buff, sz); read(state->rawdev.rawdev_fd, read_buff, sz);
...@@ -379,7 +380,7 @@ static int make_fname(camogm_state *state, char *name) ...@@ -379,7 +380,7 @@ static int make_fname(camogm_state *state, char *name)
// assemble file name from collected Exif fields // assemble file name from collected Exif fields
if (ifd_page_num.len != 0) { if (ifd_page_num.len != 0) {
sz = sprintf(name, "%02u_", ifd_page_num.offset); sz = sprintf(name, "%02lu_", ifd_page_num.offset);
} }
if (ifd_date_time.len != 0) { if (ifd_date_time.len != 0) {
sz += exif_get_text(state, &ifd_date_time, name + sz); sz += exif_get_text(state, &ifd_date_time, name + sz);
...@@ -402,19 +403,53 @@ static int make_fname(camogm_state *state, char *name) ...@@ -402,19 +403,53 @@ static int make_fname(camogm_state *state, char *name)
return 0; return 0;
} }
void dump_vfs(struct statvfs *vfs)
{
fprintf(debug_file, "vfs.f_bsize = %lu\n", vfs->f_bsize);
fprintf(debug_file, "vfs.f_frsize = %lu\n", vfs->f_frsize);
fprintf(debug_file, "vfs.f_blocks = %lu\n", vfs->f_blocks);
fprintf(debug_file, "vfs.f_bfree = %lu\n", vfs->f_bfree);
fprintf(debug_file, "vfs.f_bavail = %lu\n", vfs->f_bavail);
fprintf(debug_file, "vfs.f_files = %lu\n", vfs->f_files);
fprintf(debug_file, "vfs.f_ffree= %lu\n", vfs->f_ffree);
fprintf(debug_file, "vfs.f_favail = %lu\n", vfs->f_favail);
fprintf(debug_file, "vfs.f_fsid = %lu\n", vfs->f_fsid);
fprintf(debug_file, "vfs.f_flag = %lu\n", vfs->f_flag);
fprintf(debug_file, "vfs.f_namemax = %lu\n", vfs->f_namemax);
}
/** /**
* @brief Create new file name string and open a file * @brief Create new file name, check free space on disk and open a file
* @param[in] f_op pointer to a structure holding information about currently opened file * @param[in] f_op pointer to a structure holding information about currently opened file
* @return \e FILE_OK if file was successfully opened and \e FILE_OPEN_ERR otherwise * @return \e FILE_OK if file was successfully opened and negative error code otherwise
*/ */
static int start_new_file(struct file_opts *f_op) static int start_new_file(struct file_opts *f_op)
{ {
int ret; int ret;
int err; int err;
struct statvfs vfs;
uint64_t free_size = 0;
char file_name[ELPHEL_PATH_MAX] = {0}; char file_name[ELPHEL_PATH_MAX] = {0};
memset(&vfs, 0, sizeof(struct statvfs));
ret = statvfs(f_op->state->path_prefix, &vfs);
if (ret != 0) {
D0(fprintf(debug_file, "Unable to get free size on disk, statvfs() returned %d\n", ret));
return -CAMOGM_FRAME_FILE_ERR;
}
free_size = (uint64_t)vfs.f_bsize * (uint64_t)vfs.f_bfree;
// statvfs can return irrelevant values in some fields for unsupported file systems,
// thus free_size is checked to be equal to non-zero value
if (free_size > 0 && free_size < FREE_SIZE_LIMIT) {
fprintf(debug_file, "free_size = %llu; vfs.f_bsize = %lu; vfs.f_bfree = %lu; vfs.f_bsize * vfs.f_bfree = %llu\n",
free_size, vfs.f_bsize, vfs.f_bfree, vfs.f_bsize * vfs.f_bfree);
dump_vfs(&vfs);
return -CAMOGM_NO_SPACE;
}
make_fname(f_op->state, file_name); make_fname(f_op->state, file_name);
if ((f_op->fh = fopen(file_name, "w")) == NULL) { sprintf(f_op->state->path, "%s%s", f_op->state->path_prefix, file_name);
if ((f_op->fh = fopen(f_op->state->path, "w")) == NULL) {
err = errno; err = errno;
D0(fprintf(debug_file, "Error opening %s for writing\n", file_name)); D0(fprintf(debug_file, "Error opening %s for writing\n", file_name));
D0(fprintf(debug_file, "%s\n", strerror(err))); D0(fprintf(debug_file, "%s\n", strerror(err)));
...@@ -502,13 +537,15 @@ static int write_buffer(struct file_opts *f_op, unsigned char *from, unsigned ch ...@@ -502,13 +537,15 @@ static int write_buffer(struct file_opts *f_op, unsigned char *from, unsigned ch
} }
break; break;
case WRITE_START: case WRITE_START:
if (start_new_file(f_op) == FILE_OK) { if ((ret = start_new_file(f_op)) == FILE_OK) {
len = fwrite(from, sz, 1, f_op->fh); len = fwrite(from, sz, 1, f_op->fh);
if (len != 1) { if (len != 1) {
perror(__func__); perror(__func__);
ret = FILE_WR_ERR; ret = FILE_WR_ERR;
} }
} else { } else {
if (ret == -CAMOGM_NO_SPACE)
D0(fprintf(debug_file, "No free space left on the disk\n"));
f_op->fh = NULL; f_op->fh = NULL;
ret = FILE_OPEN_ERR; ret = FILE_OPEN_ERR;
} }
...@@ -700,7 +737,6 @@ int camogm_read(camogm_state *state) ...@@ -700,7 +737,6 @@ int camogm_read(camogm_state *state)
save_to = next_chunk.iov_base + next_chunk.iov_len; save_to = next_chunk.iov_base + next_chunk.iov_len;
} else { } else {
fprintf(stderr, "process MATCH_PARTIAL: match not found\n"); fprintf(stderr, "process MATCH_PARTIAL: match not found\n");
// file_op = write_buffer(&f_opts, save_from, save_to);
save_from = next_chunk.iov_base; save_from = next_chunk.iov_base;
save_to = next_chunk.iov_base + next_chunk.iov_len; save_to = next_chunk.iov_base + next_chunk.iov_len;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment