Logo Search packages:      
Sourcecode: cbmconvert version File versions  Download package

enum RdStatus ReadNative ( FILE *  file,
const char *  filename,
write_file_t  writeCallback,
log_t  log 
)

Read a file in the native format of the host system

Parameters:
file the file input stream
filename host system name of the file
writeCallback function for writing the contained files
log Call-back function for diagnostic output
Returns:
status of the operation

Definition at line 60 of file read.c.

References ascii2petscii(), DEL, Errors, Filename::name, PATH_SEPARATOR, PRG, RdFail, RdNoSpace, RdOK, Filename::recordLength, REL, SEQ, Filename::type, USR, Warnings, WrFail, WrNoSpace, and WrOK.

{
  struct Filename name;
  const char* suffix = 0;
  unsigned i;
  byte_t* buf;
  enum WrStatus status;

  /* Get the file base name */
  for (i = strlen (filename); i && filename[i] != PATH_SEPARATOR; i--);

  if (filename[i] == PATH_SEPARATOR) filename += i + 1;

  if (!*filename) {
    filename = "null.prg";
    (*log) (Warnings, 0, "Null file name, changed to %s", filename);
  }

  i = strlen (filename);

  /* Determine the file type. */

  if (i >= 3 && filename[i - 2] == ',') {
    switch (filename[i - 1]) {
    case 'd': case 'D':
      name.type = DEL; break;
    case 's': case 'S':
      name.type = SEQ; break;
    case 'p': case 'P':
      name.type = PRG; break;
    case 'u': case 'U':
      name.type = USR; break;
    default:
      goto UnknownType;
    }
    suffix = &filename[i - 2];
  }
  else if (i >= 5 && (filename[i - 4] == '.' || filename[i - 4] == ',')) {
    suffix = &filename[i - 3];

    if (!strcmp (suffix, "del") || !strcmp (suffix, "DEL"))
      name.type = DEL;
    else if (!strcmp (suffix, "seq") || !strcmp (suffix, "SEQ"))
      name.type = SEQ;
    else if (!strcmp (suffix, "prg") || !strcmp (suffix, "PRG") ||
           !strcmp (suffix, "cvt") || !strcmp (suffix, "CVT"))
      name.type = PRG; /* CVT for GEOS Convert files */
    else if (!strcmp (suffix, "usr"))
      name.type = USR;
    else if (!strcmp (suffix, "rel") || !strcmp (suffix, "REL")) {
      name.type = REL;
      (*log) (Warnings, 0, "unknown record length");
    }
    else if (*suffix == 'l') {
      char* endptr = 0;
      unsigned int recordLength = strtoul (suffix + 1, &endptr, 16);
      if (*endptr)
      goto UnknownType;

      name.type = REL;
      name.recordLength = recordLength;
    }
    else
      goto UnknownType;

    suffix--;
  }
  else {
  UnknownType:
    (*log) (Warnings, 0, "Unknown type, defaulting to PRG");
    name.type = PRG;
    name.recordLength = 0;
    suffix = 0;
  }

  /* Copy the file name */
  if (suffix) {
    for (i = 0; i < suffix - filename && i < sizeof(name.name); i++)
      name.name[i] = ascii2petscii(filename[i]);

    /* Pad with shifted spaces */
    while (i < sizeof(name.name))
      name.name[i++] = 0xA0;
  }
  else {
    for (i = 0; filename[i] && i < sizeof(name.name); i++)
      name.name[i] = ascii2petscii(filename[i]);

    /* Pad with shifted spaces */
    while (i < sizeof(name.name))
      name.name[i++] = 0xA0;
  }

  /* Determine file length. */
  if (fseek (file, 0, SEEK_END)) {
  seekError:
    (*log) (Errors, 0, "fseek: %s", strerror(errno));
    return RdFail;
  }

  i = ftell (file);

  if (fseek (file, 0, SEEK_SET))
    goto seekError;

  if (!(buf = malloc (i))) {
    (*log) (Errors, 0, "Out of memory.");
    return RdFail;
  }

  if (1 != fread (buf, i, 1, file)) {
    (*log) (Errors, 0, "fread: %s", strerror(errno));
    free (buf);
    return RdFail;
  }

  status = (*writeCallback) (&name, buf, i);

  free (buf);

  switch (status) {
  case WrOK:
    return RdOK;
  case WrNoSpace:
    return RdNoSpace;
  case WrFail:
  default:
    return RdFail;
  }
}


Generated by  Doxygen 1.6.0   Back to index