예제 #1
0
/* `fopen()' wrapper.  */
FILE *zfile_fopen(const char *name, const char *mode)
{
    char *tmp_name;
    FILE *stream;
    enum compression_type type;
    int write_mode = 0;

    if (!zinit_done) {
        zinit();
    }

    if (name == NULL || name[0] == 0) {
        return NULL;
    }

    /* Do we want to write to this file?  */
    if ((strchr(mode, 'w') != NULL) || (strchr(mode, '+') != NULL)) {
        write_mode = 1;
    }

    /* Check for write permissions.  */
    if (write_mode && ioutil_access(name, IOUTIL_ACCESS_W_OK) < 0) {
        return NULL;
    }

    type = try_uncompress(name, &tmp_name, write_mode);
    if (type == COMPR_NONE) {
        stream = fopen(name, mode);
        if (stream == NULL) {
            return NULL;
        }
        zfile_list_add(NULL, name, type, write_mode, stream, NULL);
        return stream;
    } else if (*tmp_name == '\0') {
        errno = EACCES;
        return NULL;
    }

    /* Open the uncompressed version of the file.  */
    stream = fopen(tmp_name, mode);
    if (stream == NULL) {
        return NULL;
    }

    zfile_list_add(tmp_name, name, type, write_mode, stream, NULL);

    /* now we don't need the archdep_tmpnam allocation any more */
    lib_free(tmp_name);

    return stream;
}
예제 #2
0
static void command_directory_get(vdrive_t *vdrive, bufinfo_t *bufinfo,
                                  BYTE *data, unsigned int secondary)
{
    int i, l, f, statrc;
    unsigned int blocks;
    char *direntry;
    unsigned int filelen, isdir;
    fileio_info_t *finfo = NULL;
    unsigned int format = 0;
    char *buf;

    buf = (char *)lib_malloc(ioutil_maxpathlen());

    bufinfo->bufp = bufinfo->name;

    if (fsdevice_convert_p00_enabled[(vdrive->unit) - 8])
        format |= FILEIO_FORMAT_P00;
    if (!fsdevice_hide_cbm_files_enabled[vdrive->unit - 8])
        format |= FILEIO_FORMAT_RAW;

    /*
     * Find the next directory entry and return it as a CBM
     * directory line.
     */

    /* first test if dirmask is needed - maybe this should be
       replaced by some regex functions... */
    f = 1;
    do {
        BYTE *p;
        finfo = NULL; /* iAN CooG 31/08 */

        direntry = ioutil_readdir(bufinfo->ioutil_dir);

        if (direntry == NULL)
            break;

        finfo = fileio_open(direntry, bufinfo->dir, format,
                            FILEIO_COMMAND_READ | FILEIO_COMMAND_FSNAME,
                            FILEIO_TYPE_PRG);

        if (finfo == NULL)
            continue;

        bufinfo->type = finfo->type;

        if (bufinfo->dirmask[0] == '\0')
            break;

        l = strlen(bufinfo->dirmask);

        for (p = finfo->name, i = 0;
            *p && bufinfo->dirmask[i] && i < l; i++) {
            if (bufinfo->dirmask[i] == '?') {
                p++;
            } else if (bufinfo->dirmask[i] == '*') {
                if (!(bufinfo->dirmask[i + 1])) {
                    f = 0;
                    break;
                } /* end mask */
                while (*p && (*p != bufinfo->dirmask[i + 1]))
                    p++;
            } else {
                if (*p != bufinfo->dirmask[i])
                    break;
                p++;
            }
            if ((!*p) && (!(bufinfo->dirmask[i + 1]))) {
                f = 0;
                break;
            }
        }
        if (f > 0)
            fileio_close(finfo);
    } while (f);

    if (direntry != NULL) {
        BYTE *p = bufinfo->name;

        strcpy(buf, bufinfo->dir);
        strcat(buf, FSDEV_DIR_SEP_STR);
        strcat(buf, direntry);

        /* Line link, Length and spaces */

        *p++ = 1;
        *p++ = 1;

        statrc = ioutil_stat(buf, &filelen, &isdir);
        if (statrc == 0)
            blocks = (filelen + 253) / 254;
        else
            blocks = 0;   /* this file can't be opened */

        if (blocks > 0xffff)
            blocks = 0xffff; /* Limit file size to 16 bits.  */

        SET_LO_HI(p, blocks);

        if (blocks < 10)
            *p++ = ' ';
        if (blocks < 100)
            *p++ = ' ';
        if (blocks < 1000)
            *p++ = ' ';

        /*
         * Filename
         */

        *p++ = '"';

        for (i = 0; finfo->name[i] && (*p = finfo->name[i]); ++i, ++p);

        *p++ = '"';
        for (; i < 16; i++)
            *p++ = ' ';

        if (isdir != 0) {
            *p++ = ' '; /* normal file */
            *p++ = 'D';
            *p++ = 'I';
            *p++ = 'R';
        } else {
            if (blocks)
                *p++ = ' '; /* normal file */
            else
                *p++ = '*'; /* splat file */
            switch(bufinfo->type) {
              case CBMDOS_FT_DEL:
                *p++ = 'D';
                *p++ = 'E';
                *p++ = 'L';
                break;
              case CBMDOS_FT_SEQ:
                *p++ = 'S';
                *p++ = 'E';
                *p++ = 'Q';
                break;
              case CBMDOS_FT_PRG:
                *p++ = 'P';
                *p++ = 'R';
                *p++ = 'G';
                break;
              case CBMDOS_FT_USR:
                *p++ = 'U';
                *p++ = 'S';
                *p++ = 'R';
                break;
              case CBMDOS_FT_REL:
                *p++ = 'R';
                *p++ = 'E';
                *p++ = 'L';
                break;
            }
        }

        if (ioutil_access(buf, IOUTIL_ACCESS_W_OK))
            *p++ = '<'; /* read-only file */

        *p = '\0';        /* to allow strlen */

        /* some (really very) old programs rely on the directory
           entry to be 32 Bytes in total (incl. nullbyte) */
        l = strlen((char *)(bufinfo->name + 4)) + 4;
        while (l < 31) {
            *p++ = ' ';
            l++;
        }

        *p++ = '\0';

        bufinfo->buflen = (int)(p - bufinfo->name);

    } else {
        BYTE *p = bufinfo->name;

        /* EOF => End file */

        *p++ = 1;
        *p++ = 1;
        *p++ = 0;
        *p++ = 0;
        memcpy(p, "BLOCKS FREE.", 12);
        p += 12;
        memset(p, ' ', 13);
        p += 13;

        memset(p, 0, 3);
        bufinfo->buflen = 32;
        bufinfo->eof++;
    }

    if (finfo != NULL) /* iAN CooG 31/08 */
        fileio_close(finfo);

    lib_free(buf);
}
예제 #3
0
char *findpath(const char *cmd, const char *syspath, int mode)
{
    char *pd = NULL;
    char *c, *buf;
    size_t maxpathlen;

    maxpathlen = (size_t)ioutil_maxpathlen();

    buf = lib_malloc(maxpathlen);

    buf[0] = '\0'; /* this will (and needs to) stay '\0' */

    if (strchr(cmd, FSDEV_DIR_SEP_CHR)) {
        size_t l;
        int state;
        const char *ps;

        if (archdep_path_is_relative(cmd)) {
            if (ioutil_getcwd(buf + 1, (int)maxpathlen - 128) == NULL)
                goto fail;

            l = strlen(buf + 1);
        } else {
            l = 0;
        }

        if (l + strlen(cmd) >= maxpathlen - 5)
            goto fail;

        ps = cmd;
        pd = buf + l; /* buf + 1 + l - 1 */

#if !defined (__MSDOS__) && !defined (WIN32) && !defined (__OS2__)
        if (*pd++ != '/')
            *pd++ = '/';
#else
        pd++;
#endif

        state = 1;

        /* delete extra `/./', '/../' and '//':s from the path */
        while (*ps) {
            switch (state) {
              case 0:
                if (*ps == '/')
                    state = 1;
                else
                    state = 0;
                break;
              case 1:
                if (*ps == '.') {
                    state = 2;
                    break;
                }
                if (*ps == '/')
                    pd--;
                else
                    state = 0;
                break;
              case 2:
                if (*ps == '/') {
                    state = 1;
                    pd -= 2;
                    break;
                }
                if (*ps == '.')
                    state = 3;
                else
                    state = 0;
                break;
              case 3:
                if (*ps != '/') {
                    state = 0;
                    break;
                }
                state = 1;
                pd -= 4;
                while (*pd != '/' && *pd != '\0')
                    pd--;
                if (*pd == '\0')
                    pd++;
                state = 1;
                break;
            }
            *pd++ = *ps++;

        }

        *pd = '\0';
        pd = buf + 1;
    } else {
        const char *path = syspath;
        const char *s;
        size_t cl = strlen(cmd) + 1;

        for (s = path; s; path = s + 1) {
            char * p;
            int l;

            s = strchr(path, ARCHDEP_FINDPATH_SEPARATOR_CHAR);
            l = s ? (int)(s - path) : (int)strlen(path);

            if (l + cl > maxpathlen - 5)
                continue;

            memcpy(buf + 1, path, l);

            p = buf + l;  /* buf + 1 + l - 1 */

            if (*p++ != '/')
                *p++ = '/';

            memcpy(p, cmd, cl);

            for (c = buf + 1; *c != '\0'; c++)
#if defined (__MSDOS__) || defined (WIN32) || defined (__OS2__)
                if (*c == '/')
                    *c = '\\';
#else
                if (*c == '\\')
                    *c ='/';
#endif
            if (ioutil_access(buf + 1, mode) == 0) {
                pd = p /* + cl*/ ;
                break;
            }
        }
    }


    if (pd) {
        char *tmpbuf;
#if 0
        do pd--;
        while (*pd != '/'); /* there is at least one '/' */

        if (*(pd - 1) == '\0')
            pd++;
        *pd = '\0';
#endif

        tmpbuf = lib_stralloc(buf + 1);
        lib_free(buf);
        return tmpbuf;
    }
 fail:
    lib_free(buf);
    return NULL;
}
예제 #4
0
/* Compress `src' into `dest' using algorithm `type'.  */
static int zfile_compress(const char *src, const char *dest,
                          enum compression_type type)
{
    char *dest_backup_name;
    int retval;

    /* This shouldn't happen */
    if (type == COMPR_ARCHIVE) {
        log_error(zlog, "compress: trying to compress archive-file.");
        return -1;
    }

    /* This shouldn't happen */
    if (type == COMPR_ZIPCODE) {
        log_error(zlog, "compress: trying to compress zipcode-file.");
        return -1;
    }

    /* This shouldn't happen */
    if (type == COMPR_LYNX) {
        log_error(zlog, "compress: trying to compress lynx-file.");
        return -1;
    }

    /* This shouldn't happen */
    if (type == COMPR_TZX) {
        log_error(zlog, "compress: trying to compress tzx-file.");
        return -1;
    }

    /* Check whether `compression_type' is a known one.  */
    if (type != COMPR_GZIP && type != COMPR_BZIP) {
        log_error(zlog, "compress: unknown compression type");
        return -1;
    }

    /* If we have no write permissions for `dest', give up.  */
    if (ioutil_access(dest, IOUTIL_ACCESS_W_OK) < 0) {
        ZDEBUG(("compress: no write permissions for `%s'",
                dest));
        return -1;
    }

    if (ioutil_access(dest, IOUTIL_ACCESS_R_OK) < 0) {
        ZDEBUG(("compress: no read permissions for `%s'", dest));
        dest_backup_name = NULL;
    } else {
        /* If `dest' exists, make a backup first.  */
        dest_backup_name = archdep_make_backup_filename(dest);
        if (dest_backup_name != NULL) {
            ZDEBUG(("compress: making backup %s... ", dest_backup_name));
        }
#ifdef WIN32
        if (dest_backup_name != NULL) {
            ioutil_remove(dest_backup_name);
        }
#endif
        if (dest_backup_name != NULL
            && ioutil_rename(dest, dest_backup_name) < 0) {
            ZDEBUG(("failed."));
            log_error(zlog, "Could not make pre-compression backup.");
            return -1;
        } else {
            ZDEBUG(("OK."));
        }
    }

    switch (type) {
        case COMPR_GZIP:
            retval = compress_with_gzip(src, dest);
            break;
        case COMPR_BZIP:
            retval = compress_with_bzip(src, dest);
            break;
        default:
            retval = -1;
    }

    if (retval == -1) {
        /* Compression failed: restore original file.  */
#ifdef WIN32
        if (dest_backup_name != NULL) {
            ioutil_remove(dest);
        }
#endif
        if (dest_backup_name != NULL
            && ioutil_rename(dest_backup_name, dest) < 0) {
            log_error(zlog,
                      "Could not restore backup file after failed compression.");
        }
    } else {
        /* Compression succeeded: remove backup file.  */
        if (dest_backup_name != NULL
            && ioutil_remove(dest_backup_name) < 0) {
            log_error(zlog, "Warning: could not remove backup file.");
            /* Do not return an error anyway (no data is lost).  */
        }
    }

    if (dest_backup_name) {
        lib_free(dest_backup_name);
    }
    return retval;
}