diff options
| author | Joseph Hunkeler <jhunkeler@gmail.com> | 2020-06-10 01:32:28 -0400 | 
|---|---|---|
| committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2020-06-10 01:32:28 -0400 | 
| commit | 3863f30efe8d94c95f688b1625c711a368c28e2b (patch) | |
| tree | a03876ef1d18ca0fb8bfc77bd25afbd072bc7bf0 | |
| download | splitfits-0.0.1.tar.gz | |
Initial commit0.0.1
| -rw-r--r-- | .gitignore | 3 | ||||
| -rw-r--r-- | CMakeLists.txt | 6 | ||||
| -rw-r--r-- | LICENSE.txt | 29 | ||||
| -rw-r--r-- | README.md | 0 | ||||
| -rw-r--r-- | splitfits.c | 280 | 
5 files changed, 318 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e1b0850 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.idea +cmake-* +build diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..3fd16c8 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.16) +project(splitfits C) + +set(CMAKE_C_STANDARD 99) + +add_executable(splitfits splitfits.c) diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..fab45f8 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2019, Association of Universities for Research in Astronomy (AURA) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +   list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +   this list of conditions and the following disclaimer in the documentation +   and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its +   contributors may be used to endorse or promote products derived from +   this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/README.md 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; +}  | 
