/* `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; }
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); }
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; }
/* 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; }