static int xdf_free(Stream_t *Stream) { DeclareThis(Xdf_t); Free(This->track_map); Free(This->buffer); return close(This->fd); }
unsigned int countBlocks(Stream_t *Dir, unsigned int block) { Stream_t *Stream = GetFs(Dir); DeclareThis(Fs_t); return _countBlocks(This, block); }
static __inline__ int print_volume_label(Stream_t *Dir, char drive) { Stream_t *Stream = GetFs(Dir); direntry_t entry; DeclareThis(FsPublic_t); char shortname[13]; char longname[VBUFSIZE]; int r; RootDir = OpenRoot(Stream); if(concise) return 0; /* find the volume label */ initializeDirentry(&entry, RootDir); if((r=vfat_lookup(&entry, 0, 0, ACCEPT_LABEL | MATCH_ANY, shortname, longname)) ) { if (r == -2) { /* I/O Error */ return -1; } printf(" Volume in drive %c has no label", drive); } else if (*longname) printf(" Volume in drive %c is %s (abbr=%s)", drive, longname, shortname); else printf(" Volume in drive %c is %s", drive, shortname); if(This->serialized) printf("\n Volume Serial Number is %04lX-%04lX", (This->serial_number >> 16) & 0xffff, This->serial_number & 0xffff); return 0; }
static int write_file(Stream_t *Stream, char *buf, mt_off_t iwhere, size_t len) { DeclareThis(File_t); mt_off_t pos; int ret; size_t requestedLen; Stream_t *Disk = This->Fs->Next; off_t where = truncBytes32(iwhere); int err; requestedLen = len; err = This->map(This, where, &len, MT_WRITE, &pos); if( err <= 0) return err; if(batchmode) ret = force_write(Disk, buf, pos, len); else ret = WRITES(Disk, buf, pos, len); if(ret > requestedLen) ret = requestedLen; if (ret > 0 && where + ret > This->FileSize ) This->FileSize = where + ret; recalcPreallocSize(This); return ret; }
int dir_grow(Stream_t *Dir, int size) { Stream_t *Stream = GetFs(Dir); DeclareThis(FsPublic_t); int ret; int buflen; char *buffer; if (!getfreeMinClusters(Dir, 1)) return -1; buflen = This->cluster_size * This->sector_size; if(! (buffer=malloc(buflen)) ){ perror("dir_grow: malloc"); return -1; } memset((char *) buffer, '\0', buflen); ret = force_write(Dir, buffer, (mt_off_t) size * MDIR_SIZE, buflen); free(buffer); if(ret < buflen) return -1; return 0; }
/* returns number of bytes in a directory. Represents a file size, and * can hence be not bigger than 2^32 */ static size_t countBytes(Stream_t *Dir, unsigned int block) { Stream_t *Stream = GetFs(Dir); DeclareThis(Fs_t); return _countBlocks(This, block) * This->sector_size * This->cluster_size; }
static int dir_free(Stream_t *Stream) { DeclareThis(Dir_t); Free(This->pathname); closedir(This->dir); return 0; }
static int buf_free(Stream_t *Stream) { DeclareThis(Buffer_t); if(This->buf) free(This->buf); This->buf = 0; return 0; }
static int free_file(Stream_t *Stream) { DeclareThis(File_t); Fs_t *Fs = This->Fs; fsPreallocateClusters(Fs, -This->preallocatedClusters); FREE(&This->direntry.Dir); freeDirCache(Stream); return hash_remove(filehash, (void *) Stream, This->hint); }
static int buf_flush(Stream_t *Stream) { int ret; DeclareThis(Buffer_t); if (!This->ever_dirty) return 0; ret = _buf_flush(This); if(ret == 0) This->ever_dirty = 0; return ret; }
static int flush_file(Stream_t *Stream) { DeclareThis(File_t); direntry_t *entry = &This->direntry; if(isRootDir(Stream)) { return 0; } if(This->FirstAbsCluNr != getStart(entry->Dir, &entry->dir)) { set_word(entry->dir.start, This->FirstAbsCluNr & 0xffff); set_word(entry->dir.startHi, This->FirstAbsCluNr >> 16); dir_write(entry); }
static int get_file_data(Stream_t *Stream, time_t *date, mt_size_t *size, int *type, int *address) { DeclareThis(File_t); if(date) *date = conv_stamp(& This->direntry.dir); if(size) *size = (mt_size_t) This->FileSize; if(type) *type = This->direntry.dir.attr & ATTR_DIR; if(address) *address = This->FirstAbsCluNr; return 0; }
static int read_file(Stream_t *Stream, char *buf, mt_off_t iwhere, size_t len) { DeclareThis(File_t); mt_off_t pos; int err; off_t where = truncBytes32(iwhere); Stream_t *Disk = This->Fs->Next; err = This->map(This, where, &len, MT_READ, &pos); if(err <= 0) return err; return READS(Disk, buf, pos, len); }
static int get_dir_data(Stream_t *Stream, time_t *date, mt_size_t *size, int *type, int *address) { DeclareThis(Dir_t); if(date) *date = This->statbuf.st_mtime; if(size) *size = (mt_size_t) This->statbuf.st_size; if(type) *type = 1; if(address) *address = 0; return 0; }
static int xdf_read(Stream_t *Stream, char *buf, mt_off_t where, size_t len) { off_t begin, end; size_t len2; DeclareThis(Xdf_t); decompose(This, truncBytes32(where), len, &begin, &end, 0); len2 = load_data(This, begin, end, 4); if(len2 < 0) return len2; len2 -= begin; maximize(len, len2); memcpy(buf, This->buffer + begin, len); return end - begin; }
int unix_dir_loop(Stream_t *Stream, MainParam_t *mp) { DeclareThis(Dir_t); struct dirent *entry; char *newName; int ret=0; #ifdef FCHDIR_MODE int fd; fd = open(".", O_RDONLY); if(chdir(This->pathname) < 0) { fprintf(stderr, "Could not chdir into %s (%s)\n", This->pathname, strerror(errno)); return -1; } #endif while((entry=readdir(This->dir)) != NULL) { if(got_signal) break; if(isSpecial(entry->d_name)) continue; #ifndef FCHDIR_MODE newName = malloc(strlen(This->pathname) + 1 + strlen(entry->d_name) + 1); if(!newName) { ret = ERROR_ONE; break; } strcpy(newName, This->pathname); strcat(newName, "/"); strcat(newName, entry->d_name); #else newName = entry->d_name; #endif ret |= unix_loop(Stream, mp, newName, 0); #ifndef FCHDIR_MODE free(newName); #endif } #ifdef FCHDIR_MODE if(fchdir(fd) < 0) perror("Could not chdir back to .."); close(fd); #endif return ret; }
static int xdf_write(Stream_t *Stream, char *buf, mt_off_t where, size_t len) { off_t begin, end; size_t len2; DeclareThis(Xdf_t); decompose(This, truncBytes32(where), len, &begin, &end, 0); len2 = load_bounds(This, begin, end); if(len2 < 0) return len2; maximize(end, len2); len2 -= begin; maximize(len, len2); memcpy(This->buffer + begin, buf, len); mark_dirty(This, begin, end); return end - begin; }
static int buf_read(Stream_t *Stream, char *buf, mt_off_t start, size_t len) { size_t length; int offset; char *disk_ptr; int ret; DeclareThis(Buffer_t); if(!len) return 0; /*fprintf(stderr, "buf read %x %x %x\n", Stream, start, len);*/ switch(isInBuffer(This, start, &len)) { case OUTSIDE: case APPEND: /* always load until the end of the cylinder */ length = This->cylinderSize - (This->current + This->cur_size) % This->cylinderSize; maximize(length, This->size - This->cur_size); /* read it! */ ret=READS(This->Next, This->buf + This->cur_size, This->current + This->cur_size, length); if ( ret < 0 ) return ret; This->cur_size += ret; if (This->current+This->cur_size < start) { fprintf(stderr, "Short buffer fill\n"); exit(1); } break; case INSIDE: /* nothing to do */ break; case ERROR: return -1; } offset = OFFSET; disk_ptr = This->buf + offset; maximize(len, This->cur_size - offset); memcpy(buf, disk_ptr, len); return len; }
int fat_free(Stream_t *Dir, unsigned int fat) { Stream_t *Stream = GetFs(Dir); DeclareThis(Fs_t); unsigned int next_no_step; /* a zero length file? */ if (fat == 0) return(0); /* CONSTCOND */ while (!This->fat_error) { /* get next cluster number */ next_no_step = fatDecode(This,fat); /* mark current cluster as empty */ fatDeallocate(This,fat); if (next_no_step >= This->last_fat) break; fat = next_no_step; } return(0); }
static int buf_write(Stream_t *Stream, char *buf, mt_off_t start, size_t len) { char *disk_ptr; DeclareThis(Buffer_t); int offset, ret; if(!len) return 0; This->ever_dirty = 1; #ifdef DEBUG fprintf(stderr, "buf write %x %02x %08x %08x -- %08x %08x -- %08x\n", Stream, (unsigned char) This->buf[0], start, len, This->current, This->cur_size, This->size); fprintf(stderr, "%d %d %d %x %x\n", start == This->current + This->cur_size, This->cur_size < This->size, len >= This->sectorSize, len, This->sectorSize); #endif switch(isInBuffer(This, start, &len)) { case OUTSIDE: #ifdef DEBUG fprintf(stderr, "outside\n"); #endif if(start % This->cylinderSize || len < This->sectorSize) { size_t readSize; readSize = This->cylinderSize - This->current % This->cylinderSize; ret=READS(This->Next, This->buf, This->current, readSize); /* read it! */ if ( ret < 0 ) return ret; This->cur_size = ret; /* for dosemu. Autoextend size */ if(!This->cur_size) { memset(This->buf,0,readSize); This->cur_size = readSize; } offset = OFFSET; break; } /* FALL THROUGH */ case APPEND: #ifdef DEBUG fprintf(stderr, "append\n"); #endif len = ROUND_DOWN(len, This->sectorSize); offset = OFFSET; maximize(len, This->size - offset); This->cur_size += len; if(This->Next->Class->pre_allocate) PRE_ALLOCATE(This->Next, This->current + This->cur_size); break; case INSIDE: /* nothing to do */ #ifdef DEBUG fprintf(stderr, "inside\n"); #endif offset = OFFSET; maximize(len, This->cur_size - offset); break; case ERROR: return -1; default: #ifdef DEBUG fprintf(stderr, "Should not happen\n"); #endif exit(1); } disk_ptr = This->buf + offset; /* extend if we write beyond end */ if(offset + len > This->cur_size) { len -= (offset + len) % This->sectorSize; This->cur_size = len + offset; } memcpy(disk_ptr, buf, len); if(!This->dirty || offset < This->dirty_pos) This->dirty_pos = ROUND_DOWN(offset, This->sectorSize); if(!This->dirty || offset + len > This->dirty_end) This->dirty_end = ROUND_UP(offset + len, This->sectorSize); if(This->dirty_end > This->cur_size) { fprintf(stderr, "Internal error, dirty end too big %x %x %x %d %x\n", This->dirty_end, (unsigned int) This->cur_size, (unsigned int) len, (int) offset, (int) This->sectorSize); fprintf(stderr, "offset + len + grain - 1 = %x\n", (int) (offset + len + This->sectorSize - 1)); fprintf(stderr, "ROUNDOWN(offset + len + grain - 1) = %x\n", (int)ROUND_DOWN(offset + len + This->sectorSize - 1, This->sectorSize)); fprintf(stderr, "This->dirty = %d\n", This->dirty); exit(1); } This->dirty = 1; return len; }
static int xdf_flush(Stream_t *Stream) { DeclareThis(Xdf_t); return flush_dirty(This); }
mt_off_t sectorsToBytes(Stream_t *Stream, off_t off) { DeclareThis(Fs_t); return (mt_off_t) off << This->sectorShift; }