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

fileio.c

/*
      FATSort, utility for sorting FAT directory structures
      Copyright (C) 2004 Boris Leidner <fatsort(at)formenos.de>

      This program is free software; you can redistribute it and/or
      modify it under the terms of the GNU General Public License
      as published by the Free Software Foundation; either version 2
      of the License, or (at your option) any later version.

      This program is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      GNU General Public License for more details.

      You should have received a copy of the GNU General Public License
      along with this program; if not, write to the Free Software
      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

/*
      This file contains file io functions for UNIX/Linux AND Win32
*/

#include "fileio.h"

#ifdef __WIN32__  /* Win32 implementation of file io */

// extra header files needed under Windows
#include <windows.h>
#include <winioctl.h>
#include <ctype.h>

#include <stdio.h>
#include <sys/types.h>

// fseek, fread and fwrite need to be wrapped as in drive devices you can only seek to the beginning of sectors and can only write whole sectors

#define DEFAULT_SECSIZE 512
#define MAX_SECSIZE 1024
#define UNKNOWN_OFFSET -1

#define hi_dword(qword) ((long)((qword) >> 32))
#define lo_dword(qword) ((long)(qword))

int sector_size = DEFAULT_SECSIZE;
off64_t seek_target = 0;
off64_t current_off = 0;
off64_t prev_sec_off = UNKNOWN_OFFSET;
u_char sector_buffer[MAX_SECSIZE];
char prev_access = ' ';

int fs_seek(FILE *stream, off64_t offset, int whence) {
      switch(whence) {
            case SEEK_SET:
                  seek_target = offset;
      // DEBUG
      // printf("SEEK: %08lx%08lx\n", hi_dword(seek_target), lo_dword(seek_target));
                  return 0;
            default:
                  return -1;
      }
}

void split_off(off64_t off, off64_t *_true_off, int *_off_sec) {
      int off_sec = off % sector_size;

      if (_true_off) *_true_off = off - off_sec;
      if (_off_sec) *_off_sec = off_sec;
}

int true_fseek_win32(FILE *stream, off64_t target, char access) {
      int off_sec;
      off64_t true_off;
      int seek_result;
      u_char dummy_buffer[MAX_SECSIZE];

      // force seeking between interleaved reads/writes
      if (target != current_off || access != prev_access) {
            prev_access = access;
            split_off(target, &true_off, &off_sec);
      // DEBUG
      // printf("TRUESEEK: %08lx%08lx!=%08lx%08lx/%04x->%08lx%08lx+%04x\n", hi_dword(current_off), lo_dword(current_off), hi_dword(seek_target), lo_dword(seek_target), sector_size, hi_dword(true_off), lo_dword(true_off), off_sec);
            if ((seek_result = fseeko64(stream, true_off, SEEK_SET)) != 0) return seek_result;
            if (off_sec > 0 && access == 'R' && fread(dummy_buffer, 1, off_sec, stream) < off_sec) return -1;
      }

      return 0;
}

off_t fs_read(void *ptr, u_int32_t size, u_int32_t n, FILE *stream) {
      
      if (true_fseek_win32(stream, seek_target, 'R') != 0) return -1;
      off_t n_read = fread(ptr, size, n, stream);
      // DEBUG
      // printf("READ: %08lx%08lx->%02lx*%02lx@%02lx (%02x,%02x,%02x...)\n", hi_dword(seek_target), lo_dword(seek_target), lo_dword(size), lo_dword(n), lo_dword(n_read), ((u_char*)(ptr))[0], ((u_char*)(ptr))[1], ((u_char*)(ptr))[2]);
      seek_target += (size * n_read);
      if (n_read < n) current_off = UNKNOWN_OFFSET; else current_off = seek_target;

      return n_read;
}

int true_write_win32(FILE *stream) {

      if (prev_sec_off != UNKNOWN_OFFSET) {
            if (true_fseek_win32(stream, prev_sec_off, 'W') != 0) {
                  current_off = UNKNOWN_OFFSET;
                  return -1;
            }
            current_off = UNKNOWN_OFFSET;
            if (fwrite(sector_buffer, sector_size, 1, stream) < 1) return -1;
            // DEBUG
            //    printf("TRUEWRITE: %08lx%08lx\n", hi_dword(prev_sec_off), lo_dword(prev_sec_off));
            //    {FILE *f; char fn[100]; sprintf(fn, "%08lx%08lx-w.dat", hi_dword(prev_sec_off), lo_dword(prev_sec_off)); f = fopen(fn, "wb"); fwrite(sector_buffer, sector_size, 1, f); fclose(f);}
            current_off = prev_sec_off + sector_size;
      }

      return 0;
}

off_t fs_write(const void *ptr, u_int32_t size, u_int32_t n, FILE *stream) {

      int off_sec;
      off64_t sec_true_off;
      split_off(seek_target, &sec_true_off, NULL);

      // if writing a new sector, flush the previous sector and read in the new one
      if (sec_true_off != prev_sec_off) {
            if (true_write_win32(stream) != 0) return -1;
            if (true_fseek_win32(stream, sec_true_off, 'R') != 0) return -1;
            if (fread(sector_buffer, sector_size, 1, stream) < 1) return -1;
            // DEBUG
            //    {FILE *f; char fn[100]; sprintf(fn, "%08lx%08lx-r.dat", hi_dword(sec_true_off), lo_dword(sec_true_off)); f = fopen(fn, "rb"); if (f == NULL) {f = fopen(fn, "wb"); fwrite(sector_buffer, sector_size, 1, f);} fclose(f);}
            prev_sec_off = sec_true_off;
            current_off = sec_true_off + sector_size;
      }
      split_off(seek_target, NULL, &off_sec);
      memcpy(&sector_buffer[off_sec], ptr, size * n);
      // DEBUG
      //  printf("WRITE: %08lx%08lx->%02lx*%02lx@%02lx (%02x,%02x,%02x...)\n", hi_dword(seek_target), lo_dword(seek_target), lo_dword(size), lo_dword(n), lo_dword(n), ((u_char*)(ptr))[0], ((u_char*)(ptr))[1], ((u_char*)(ptr))[2]);
      seek_target += (size * n);

      return n;
}

int fs_close(FILE* file) {
      true_write_win32(file);
      return fclose(file);
}

#else  /* Linux or UNIX */

#include <stdio.h>
#include <sys/types.h>

int fs_seek(FILE *stream, off_t offset, int whence) {
      return fseeko(stream, offset, whence);
}

off_t fs_read(void *ptr, u_int32_t size, u_int32_t n, FILE *stream) {
      return fread(ptr, size, n, stream);
}

off_t fs_write(const void *ptr, u_int32_t size, u_int32_t n, FILE *stream) {
      return fwrite(ptr, size, n, stream);
}

int fs_close(FILE* file) {
      return fclose(file);
}


#define fs_seek(stream,offset,whence) fseeko(stream,offset,whence)
// #define fs_read(ptr,size,n,stream) fread(ptr,size,n,stream)
#define fs_write(ptr,size,n,stream) fwrite(ptr,size,n,stream)
#define fs_close(file) fclose(file)
#endif

Generated by  Doxygen 1.6.0   Back to index