//!
//! Function description.
//!
//! @param[in] file
//! @param[in] file_updated
//!
//! @return
//!
//! @see
//!
//! @pre List of pre-conditions
//!
//! @post List of post conditions
//!
//! @note
//!
int atomic_file_get(atomic_file * file, int *file_updated)
{
    int port = 0;
    int fd = 0;
    int ret = 0;
    int rc = 0;
    char *hash = NULL;
    char type[32] = "";
    char hostname[512] = "";
    char path[MAX_PATH] = "";
    char tmpsource[MAX_PATH] = "";
    char tmppath[MAX_PATH] = "";

    if (!file || !file_updated) {
        return (1);
    }

    ret = 0;
    *file_updated = 0;

    snprintf(file->tmpfile, MAX_PATH, "%s", file->tmpfilebase);
    fd = safe_mkstemp(file->tmpfile);
    if (fd < 0) {
        LOGERROR("cannot open tmpfile '%s'\n", file->tmpfile);
        return (1);
    }
    chmod(file->tmpfile, 0644);
    close(fd);

    snprintf(tmpsource, MAX_PATH, "%s", file->source);
    type[0] = tmppath[0] = path[0] = hostname[0] = '\0';
    port = 0;

    tokenize_uri(tmpsource, type, hostname, &port, tmppath);
    snprintf(path, MAX_PATH, "/%s", tmppath);

    if (!strcmp(type, "http")) {
        rc = http_get_timeout(file->source, file->tmpfile, 0, 0, 10, 15);
        if (rc) {
            LOGERROR("http client failed to fetch file URL=%s\n", file->source);
            ret = 1;
        }
    } else if (!strcmp(type, "file")) {
        if (!strlen(path) || copy_file(path, file->tmpfile)) {
            LOGERROR("could not copy source file (%s) to dest file (%s)\n", path, file->tmpfile);
            ret = 1;
        }
    } else {
        LOGWARN("BUG: incompatible URI type (only support http, file): (%s)\n", type);
        ret = 1;
    }

    if (!ret) {
        if (file->tosort) {
            rc = atomic_file_sort_tmpfile(file);
            if (rc) {
                LOGWARN("could not sort tmpfile (%s) inplace\n", file->tmpfile);
            }
        }
        // do checksum - only copy if file has changed
        hash = file2md5str(file->tmpfile);
        if (!hash) {
            LOGERROR("could not compute hash of tmpfile (%s)\n", file->tmpfile);
            ret = 1;
        } else {
            if (file->currhash)
                EUCA_FREE(file->currhash);
            file->currhash = hash;
            if (check_file(file->dest) || strcmp(file->currhash, file->lasthash)) {
                // hashes are different, put new file in place
                LOGINFO("source and destination file contents have changed, triggering update of dest (%s)\n", file->dest);
                LOGDEBUG("renaming file %s -> %s\n", file->tmpfile, file->dest);
                if (rename(file->tmpfile, file->dest)) {
                    LOGERROR("could not rename local copy to dest (%s -> %s)\n", file->tmpfile, file->dest);
                    ret = 1;
                } else {
                    EUCA_FREE(file->lasthash);
                    file->lasthash = strdup(file->currhash);
                    *file_updated = 1;
                }
            }
        }
    }

    unlink(file->tmpfile);
    return (ret);
}
//!
//! Function description.
//!
//! @param[in] file
//! @param[in] file_updated
//!
//! @return
//!
//! @see
//!
//! @pre List of pre-conditions
//!
//! @post List of post conditions
//!
//! @note
//!
int atomic_file_get(atomic_file * file, boolean * file_updated)
{
    int port = 0;
    int fd = 0;
    int ret = 0;
    int rc = 0;
    char *hash = NULL;
    char type[32] = "";
    char hostname[512] = "";
    char path[EUCA_MAX_PATH] = "";
    char tmpsource[EUCA_MAX_PATH] = "";
    char tmppath[EUCA_MAX_PATH] = "";

    if (!file || !file_updated) {
        return (1);
    }

    ret = 0;
    *file_updated = FALSE;

    snprintf(file->tmpfile, EUCA_MAX_PATH, "%s", file->tmpfilebase);
    fd = safe_mkstemp(file->tmpfile);
    if (fd < 0) {
        LOGERROR("cannot open tmpfile '%s': check permissions\n", file->tmpfile);
        return (1);
    }
    if (chmod(file->tmpfile, 0600)) {
        LOGWARN("chmod failed: was able to create tmpfile '%s', but could not change file permissions\n", file->tmpfile);
    }
    close(fd);

    snprintf(tmpsource, EUCA_MAX_PATH, "%s", file->source);
    type[0] = tmppath[0] = path[0] = hostname[0] = '\0';
    port = 0;

    tokenize_uri(tmpsource, type, hostname, &port, tmppath);
    snprintf(path, EUCA_MAX_PATH, "/%s", tmppath);

    if (!strcmp(type, "http")) {
        rc = http_get_timeout(file->source, file->tmpfile, 0, 0, 10, 15, NULL);
        if (rc) {
            LOGERROR("http client failed to fetch file URL=%s: check http server status\n", file->source);
            ret = 1;
        }
    } else if (!strcmp(type, "file")) {
        if (!strlen(path) || copy_file(path, file->tmpfile)) {
            LOGERROR("could not copy source file (%s) to dest file (%s): check permissions\n", path, file->tmpfile);
            ret = 1;
        }
    } else {
        LOGWARN("BUG: incompatible URI type (%s) passed to routine (only supports http, file)\n", type);
        ret = 1;
    }

    if (!ret) {
        if (file->dosort) {
            rc = atomic_file_sort_tmpfile(file);
            if (rc) {
                LOGWARN("could not sort tmpfile (%s) inplace: continuing without sort\n", file->tmpfile);
            }
        }
        // do checksum - only copy if file has changed
        hash = file2md5str(file->tmpfile);
        if (!hash) {
            LOGERROR("could not compute hash of tmpfile (%s): check permissions\n", file->tmpfile);
            ret = 1;
        } else {
            if (file->currhash)
                EUCA_FREE(file->currhash);
            file->currhash = hash;
            if (check_file(file->dest) || strcmp(file->currhash, file->lasthash)) {
                // hashes are different, put new file in place
                LOGDEBUG("update triggered due to file update (%s)\n", file->dest);
                LOGDEBUG("source and destination file contents have become different, triggering update of dest (%s)\n", file->dest);
                LOGDEBUG("renaming file %s -> %s\n", file->tmpfile, file->dest);
                if (rename(file->tmpfile, file->dest)) {
                    LOGERROR("could not rename (move) source file '%s' to dest file '%s': check permissions\n", file->tmpfile, file->dest);
                    ret = 1;
                } else {
                    EUCA_FREE(file->lasthash);
                    file->lasthash = strdup(file->currhash);
                    *file_updated = TRUE;
                }
            }
        }
    }

    unlink(file->tmpfile);
    return (ret);
}