* Autores: Leandro Lucarella <llucare@fi.uba.ar>
*----------------------------------------------------------------------------
*
- * $Id: bufford.c 624 2004-05-30 20:18:04Z llucare $
+ * $Id$
*
*/
free(vfp);
return 0;
}
- if (!(vfp->name = strdup(path))) /* no hay más memoria */
+ if (!(vfp->name = str_dup(path))) /* no hay más memoria */
{
- PERR("vfopen: no se pudo hacer strdup!");
+ PERR("vfopen: no se pudo hacer str_dup!");
free(vfp);
return 0;
}
/* Abrimos primer archivo de los volumenes. */
vfp->currvol = -1;
+ vfp->lastvol = 0;
if (vfvol_open_next(vfp)) /* no se pudo abrir el primer volumen. */
{
PERR("vfopen: no se pudo abrir archivo inicial!");
free(vfp);
return 0;
}
- /* todo ok. */
- vfp->room = vfp->volsize;
- vfp->lastvol = 0;
- return vfp;
+ return vfp; /* todo ok. */
}
int vfclose(VFILE* vfp)
return ret;
}
+int vfeof(VFILE* vfp)
+{
+ return vfp->lastvol && feof(vfp->fp);
+}
+
int vfgetc(VFILE* vfp)
{
int c;
{
/* Si no es multivolumen o hay lugar, agrego y salgo. */
if (!vfp->volsize || vfp->room--) return fputc(c, vfp->fp);
+ PERR("vfputc: Necesito otro volumen!\n");
/* Si no hay lugar, abro otro volumen. */
if (vfvol_close(vfp)) return EOF; /* error al cerrar. */
if (vfvol_open_next(vfp)) return EOF; /* error al abrir. */
- vfp->room = vfp->volsize;
+ vfp->room--; /* resto de nuevo el espacio porque al abrirlo lo resetea. */
return fputc(c, vfp->fp);
}
size_t vfread(void* ptr, size_t size, size_t nmemb, VFILE* vfp)
{
- return 0;
+ int c;
+ size_t i = 0;
+ size_t total = size * nmemb;
+ /* leo uno a uno y si hay error salgo. */
+ while (i < total)
+ {
+ if ((c = vfgetc(vfp)) == EOF)
+ {
+ PERR("vfread: EOF");
+ break;
+ }
+ else ((char*)ptr)[i++] = c;
+ }
+ return i / size;
}
size_t vfwrite(const void *ptr, size_t size, size_t nmemb, VFILE* vfp)
{
- return 0;
+ size_t i = 0;
+ size_t total = size * nmemb;
+ /* escribo uno a uno y si hay error salgo. */
+ while (i < total && (vfputc(((char*)ptr)[i++], vfp)) != EOF);
+ return i / size;
}
int vfvol_close(VFILE* vfp)
{
- /* Si es de escritura tengo que guardar la cabecera. */
- if (vfp->mode == VFWRITE)
+ int ret = 0;
+ if (vfp->fp)
{
- int ret;
- PERR("vfvol_close: modo == VFWRITE");
- /* Me posiciono al principio del archivo. */
- if ((ret = fseek(vfp->fp, 0l, SEEK_SET))) return ret; /* fseek error. */
- /* Guardo cabecera para indicar si es el último volumen o no. */
- if ((ret = fputc(vfp->lastvol, vfp->fp))) return ret; /* fputc error. */
+ /* Si es de escritura y el último guardo la cabecera. */
+ if (vfp->mode == VFWRITE && vfp->lastvol)
+ {
+ int ret;
+ PERR("vfvol_close: modo == VFWRITE");
+ /* Me posiciono al principio del archivo. */
+ if ((ret = fseek(vfp->fp, 0l, SEEK_SET)))
+ {
+ PERR("vfvol_close: fseek error");
+ return ret; /* fseek error. */
+ }
+ /* Guardo cabecera para indicar si es el último volumen o no. */
+ if ((ret = fputc(vfp->lastvol, vfp->fp)) == EOF)
+ {
+ PERR("vfvol_close: fputc error");
+ return ret; /* fputc error. */
+ }
+ }
+ ret = fclose(vfp->fp);
+ vfp->fp = 0;
}
- return fclose(vfp->fp);
+ return ret;
}
int vfvol_open_next(VFILE* vfp)
if (volname) free(volname);
/* Si es para lectura, me fijo si es el últio a leer. */
if (vfp->mode == VFREAD) vfp->lastvol = fgetc(vfp->fp);
- /* Si es para escritura, guardo header dummy (supongo que es el último). */
- if (vfp->mode == VFWRITE) return !fputc(1, vfp->fp);
+ /* Si es para escritura, guardo header por default (hay más volúmenes). */
+ if (vfp->mode == VFWRITE)
+ {
+ vfp->room = vfp->volsize; /* tengo todo el espacio disponible. */
+ return fputc(vfp->lastvol, vfp->fp) == EOF;
+ }
return 0;
}
+long vfsize(const char* path)
+{
+ VFILE* vfp = vfopen(path, "r", 0);
+ long size;
+ if (!vfp) return -1; /* error */
+ if (fseek(vfp->fp, 0l, SEEK_END) == -1)
+ {
+ vfclose(vfp);
+ return -1; /* error */
+ }
+ else
+ {
+ size = ftell(vfp->fp);
+ if (size == -1)
+ {
+ vfclose(vfp);
+ return -1; /* error */
+ }
+ }
+ while (!vfp->lastvol) /* mientras no sea el último volumen */
+ {
+ if (vfvol_open_next(vfp))
+ {
+ vfclose(vfp);
+ return -1; /* error */
+ }
+ if (fseek(vfp->fp, 0l, SEEK_END) == -1)
+ {
+ vfclose(vfp);
+ return -1; /* error */
+ }
+ else
+ {
+ long curr_size = ftell(vfp->fp);
+ if (curr_size == -1)
+ {
+ vfclose(vfp);
+ return -1; /* error */
+ }
+ size += curr_size;
+ }
+ if (vfvol_close(vfp))
+ {
+ vfclose(vfp);
+ return -1; /* error */
+ }
+ }
+ vfclose(vfp);
+ return size;
+}
+