diff options
Diffstat (limited to 'splitfits.c')
-rw-r--r-- | splitfits.c | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/splitfits.c b/splitfits.c new file mode 100644 index 0000000..4e2a1eb --- /dev/null +++ b/splitfits.c @@ -0,0 +1,280 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <unistd.h> + +#define SPLITFITS_BLOCK 2880 + +struct SplitFITS { + FILE *handle; + char *path_origin; + char *path_header; + char *path_data; + size_t header_size; + size_t data_size; +}; + +int splitfits_header_write(struct SplitFITS **ctx) { + char *block; + FILE *fp; + size_t count = 0; + size_t bytes; + + fp = fopen((*ctx)->path_header, "w+b"); + if (fp == NULL) { + perror((*ctx)->path_header); + return 1; + } + fseek((*ctx)->handle, 0, SEEK_SET); + + block = calloc(SPLITFITS_BLOCK + 1, sizeof(char)); + + while (1) { + memset(block, ' ', SPLITFITS_BLOCK); + bytes = fread(block, sizeof(char), SPLITFITS_BLOCK, (*ctx)->handle); + + if (strstr(block, "END ") != NULL) { + break; + } + + if (bytes == 0) { + break; + } + + if (fwrite(block, sizeof(char), SPLITFITS_BLOCK, fp) == 0) { + perror("short write"); + return 1; + } + count++; + } + + (*ctx)->header_size = SPLITFITS_BLOCK * (count); + + fclose(fp); + free(block); + return 0; +} + +int splitfits_data_write(struct SplitFITS **ctx) { + char *block; + FILE *fp; + fp = fopen((*ctx)->path_data, "w+b"); + + size_t size = 0; + fseek((*ctx)->handle, 0, SEEK_END); + size = ftell((*ctx)->handle) - (*ctx)->header_size; + fseek((*ctx)->handle, (*ctx)->header_size, SEEK_SET); + + block = calloc(SPLITFITS_BLOCK + 1, sizeof(char)); + + while (fread(block, sizeof(char), SPLITFITS_BLOCK, (*ctx)->handle) != 0) { + if (fwrite(block, sizeof(char), SPLITFITS_BLOCK, fp) == 0) { + perror("short write"); + return 1; + } + } + + (*ctx)->data_size = size; + + fclose(fp); + free(block); + return 0; +} + +int splitfits_split(struct SplitFITS **ctx) { + if (splitfits_header_write(ctx) != 0 || splitfits_data_write(ctx) != 0) { + return 1; + } + return 0; +} + +void splitfits_free(struct SplitFITS *ctx) { + free(ctx->path_origin); + free(ctx->path_data); + free(ctx->path_header); + fclose(ctx->handle); + free(ctx); +} + +void splitfits_show(struct SplitFITS *ctx) { + printf("%s:\n", ctx->path_origin); + printf("\t%-20s (%zu bytes)\n", ctx->path_header, ctx->header_size); + printf("\t%-20s (%zu bytes)\n", ctx->path_data, ctx->data_size); +} + +int splitfits_combine(const char *headerfile, const char *datafile) { + FILE *handle[] = { + fopen(headerfile, "rb"), + fopen(datafile, "rb"), + }; + FILE *fp; + size_t handle_count; + char *suffix; + char tempfile[PATH_MAX]; + char outfile[PATH_MAX]; + + handle_count = sizeof(handle) / sizeof(FILE *); + sprintf(tempfile, "%s.tmp_XXXXXX", __FUNCTION__); + + if (mkstemp(tempfile) < 0) { + perror(tempfile); + return 1; + } + + fp = fopen(tempfile, "w+b"); + if (fp == NULL) { + perror("could not open temporary file for writing"); + return 1; + } + + char block[2] = {0, 0}; + size_t bytes = 0; + for (size_t i = 0; i < handle_count; i++) { + while (1) { + bytes = fread(block, sizeof(char), 1, handle[i]); + if (bytes) { + fwrite(block, sizeof(char), 1, fp); + } else { + break; + } + } + fclose(handle[i]); + } + rewind(fp); + + strcpy(outfile, headerfile); + suffix = strstr(outfile, "_hdr.txt"); + if (suffix == NULL) { + fprintf(stderr, "%s: does not have the correct suffix (_hdr.txt)\n"); + return 1; + } + + *suffix = '\0'; + strcat(suffix, ".fits"); + + printf("Writing: %s\n", outfile); + + FILE *ofp; + ofp = fopen(outfile, "w+b"); + if (ofp == NULL) { + perror(outfile); + return 1; + } + + while (fread(block, sizeof(char), 1, fp) != 0) { + fwrite(block, sizeof(char), 1, ofp); + } + + fclose(ofp); + fclose(fp); + remove(tempfile); + return 0; +} + +struct SplitFITS *splitfits(const char *_filename) { + struct SplitFITS *ctx; + char *filename; + char *ext; + + ctx = calloc(1, sizeof(struct SplitFITS)); + if (ctx == NULL) { + perror("calloc"); + exit(1); + } + + ctx->handle = fopen(_filename, "r+b"); + if (ctx->handle == NULL) { + perror(_filename); + exit(1); + } + + ctx->path_origin = strdup(_filename); + filename = strdup(_filename); + + ctx->path_header = calloc(PATH_MAX, sizeof(char)); + ext = strrchr(filename, '.'); + + if (ext == NULL) { + fprintf(stderr, "%s: has no file extension\n", ctx->path_origin); + } else { + *ext = '\0'; + } + + strcpy(ctx->path_header, filename); + strcat(ctx->path_header, "_hdr.txt"); + + ctx->path_data = calloc(PATH_MAX, sizeof(char)); + strcpy(ctx->path_data, filename); + strcat(ctx->path_data, "_data.bin"); + + free(filename); + return ctx; +} + +int main(int argc, char *argv[]) { + int bad_files; + char *prog; + + prog = strrchr(argv[0], '/'); + if (prog == NULL) { + prog = argv[0]; + } else { + prog++; + } + + if (argc < 2) { + printf("usage: %s {[-c HEADER_FILE DATA_FILE] | FILE(s)}", prog); + exit(1); + } + + if (strcmp(argv[1], "-c") == 0) { + int combine; + const char *header_file = argv[2]; + const char *data_file = argv[3]; + + if (argc < 4) { + fprintf(stderr, "-c requires two arguments (HEADER FILE and DATA_FILE)"); + exit(1); + } + + if (access(header_file, F_OK) != 0) { + fprintf(stderr, "%s: header file does not exist\n", header_file); + exit(1); + } + + if (access(data_file, F_OK) != 0) { + fprintf(stderr, "%s: data file does not exist\n", header_file); + exit(1); + } + + combine = splitfits_combine(header_file, data_file); + exit(combine); + } + + bad_files = 0; + for (size_t i = 1; i < argc; i++) { + if (access(argv[i], F_OK) != 0) { + fprintf(stderr, "%s: does not exist", argv[i]); + bad_files = 1; + } + } + + if (bad_files) { + fprintf(stderr, "Exiting...\n"); + exit(1); + } + + for (size_t i = 1; i < argc; i++) { + struct SplitFITS *fits; + fits = splitfits(argv[i]); + + if (splitfits_split(&fits) != 0) { + fprintf(stderr, "%s: split failed\n", fits->path_origin); + } + + splitfits_show(fits); + splitfits_free(fits); + } + return 0; +} |