2004-03-03 00:56:51 +01:00
|
|
|
// file layer on top of POSIX.
|
|
|
|
// provides streaming support and caching.
|
|
|
|
//
|
|
|
|
// Copyright (c) 2004 Jan Wassenberg
|
|
|
|
//
|
|
|
|
// This file 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 file 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.
|
|
|
|
//
|
|
|
|
// Contact info:
|
|
|
|
// Jan.Wassenberg@stud.uni-karlsruhe.de
|
|
|
|
// http://www.stud.uni-karlsruhe.de/~urkt/
|
|
|
|
|
|
|
|
#ifndef FILE_H
|
|
|
|
#define FILE_H
|
|
|
|
|
|
|
|
|
|
|
|
struct File
|
|
|
|
{
|
|
|
|
#ifdef PARANOIA
|
|
|
|
u32 magic;
|
|
|
|
#endif
|
|
|
|
|
2004-03-05 17:23:31 +01:00
|
|
|
// keep offset of flags and size members in sync with struct ZFile!
|
|
|
|
// it is accessed by VFS and must be the same for both (union).
|
|
|
|
// dirty, but necessary because VFile is pushing the HDATA size limit.
|
2004-06-03 02:17:24 +02:00
|
|
|
uint flags;
|
2004-06-02 22:41:05 +02:00
|
|
|
off_t size;
|
2004-03-05 17:23:31 +01:00
|
|
|
|
2004-03-03 00:56:51 +01:00
|
|
|
u32 fn_hash;
|
|
|
|
|
|
|
|
void* mapping;
|
2004-06-03 02:17:24 +02:00
|
|
|
uint map_refs;
|
|
|
|
|
2004-03-03 00:56:51 +01:00
|
|
|
int fd;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
2004-07-05 04:31:32 +02:00
|
|
|
// write-only access; otherwise, read only
|
|
|
|
FILE_WRITE = 0x01,
|
2004-03-03 00:56:51 +01:00
|
|
|
|
2004-08-05 14:48:13 +02:00
|
|
|
|
|
|
|
// the file's contents aren't cached at a higher level; do so here.
|
|
|
|
// we keep the file open (until the cache is "full enough"). if it
|
|
|
|
// is loaded, we keep the buffer there to satisfy later loads.
|
|
|
|
FILE_CACHE = 0x04,
|
2004-07-05 04:31:32 +02:00
|
|
|
|
|
|
|
// random access hint
|
2004-08-05 14:48:13 +02:00
|
|
|
// FILE_RANDOM = 0x08,
|
2004-07-09 21:57:59 +02:00
|
|
|
|
2004-08-15 23:50:29 +02:00
|
|
|
FILE_NO_AIO = 0x10,
|
|
|
|
|
|
|
|
FILE_CACHE_BLOCK = 0x20
|
2004-05-06 19:14:30 +02:00
|
|
|
};
|
2004-03-03 00:56:51 +01:00
|
|
|
|
|
|
|
|
2004-08-02 15:44:48 +02:00
|
|
|
// convert to/from our portable path representation,
|
|
|
|
// e.g. for external libraries that require the real filename.
|
|
|
|
// note: also removes/adds current directory.
|
2004-06-08 17:16:50 +02:00
|
|
|
extern int file_make_native_path(const char* path, char* n_path);
|
|
|
|
extern int file_make_portable_path(const char* n_path, char* path);
|
|
|
|
|
|
|
|
|
2004-05-17 15:23:39 +02:00
|
|
|
// set current directory to rel_path, relative to the path to the executable,
|
|
|
|
// which is taken from argv0.
|
|
|
|
//
|
|
|
|
// example: executable in "$install_dir/system"; desired root dir is
|
|
|
|
// "$install_dir/data" => rel_path = "../data".
|
|
|
|
//
|
|
|
|
// this is necessary because the current directory is unknown at startup
|
|
|
|
// (e.g. it isn't set when invoked via batch file), and this is the
|
|
|
|
// easiest portable way to find our install directory.
|
|
|
|
//
|
|
|
|
// can only be called once, by design (see source). rel_path is trusted.
|
|
|
|
extern int file_rel_chdir(const char* argv0, const char* rel_path);
|
2004-05-06 19:14:30 +02:00
|
|
|
|
|
|
|
|
2004-08-11 22:23:22 +02:00
|
|
|
// called for each entry in a directory.
|
|
|
|
// name is the complete path (see below); it's a directory iff size < 0.
|
|
|
|
typedef int(*FileCB)(const char* const name, const ssize_t size, const uintptr_t user);
|
2004-05-06 19:14:30 +02:00
|
|
|
|
2004-08-11 22:23:22 +02:00
|
|
|
// for all files and dirs in <dir> (but not its subdirs!):
|
|
|
|
// call <cb>, passing <user> and the entries's name (not path!)
|
2004-05-08 03:11:51 +02:00
|
|
|
extern int file_enum(const char* dir, FileCB cb, uintptr_t user);
|
2004-05-06 19:14:30 +02:00
|
|
|
|
2004-08-27 02:33:20 +02:00
|
|
|
// get file status. output param is zeroed on error.
|
2004-05-06 19:14:30 +02:00
|
|
|
extern int file_stat(const char* path, struct stat*);
|
2004-03-03 00:56:51 +01:00
|
|
|
|
2004-05-08 03:11:51 +02:00
|
|
|
extern int file_open(const char* fn, uint flags, File* f);
|
2004-03-03 00:56:51 +01:00
|
|
|
extern int file_close(File* f);
|
|
|
|
|
2004-06-03 02:17:24 +02:00
|
|
|
|
|
|
|
//
|
2004-08-27 02:33:20 +02:00
|
|
|
// asynchronous IO
|
2004-06-03 02:17:24 +02:00
|
|
|
//
|
|
|
|
|
2004-08-18 04:12:52 +02:00
|
|
|
typedef void* FileIO;
|
2004-08-15 23:50:29 +02:00
|
|
|
|
|
|
|
extern int file_start_io(File* f, off_t ofs, size_t size, void* buf, FileIO* io);
|
|
|
|
|
|
|
|
// indicates if the given IO has completed.
|
2004-08-10 17:57:35 +02:00
|
|
|
// return value: 0 if pending, 1 if complete, < 0 on error.
|
2004-08-18 04:12:52 +02:00
|
|
|
extern int file_io_complete(FileIO io);
|
2004-08-15 23:50:29 +02:00
|
|
|
|
2004-08-18 04:12:52 +02:00
|
|
|
extern int file_wait_io(FileIO io, void*& p, size_t& size);
|
2004-08-10 17:57:35 +02:00
|
|
|
|
2004-08-18 04:12:52 +02:00
|
|
|
extern int file_discard_io(FileIO io);
|
2004-03-03 00:56:51 +01:00
|
|
|
|
|
|
|
|
2004-08-27 02:33:20 +02:00
|
|
|
//
|
|
|
|
// synchronous IO
|
|
|
|
//
|
2004-03-03 00:56:51 +01:00
|
|
|
|
|
|
|
// return value:
|
2004-08-12 17:51:31 +02:00
|
|
|
// < 0: failed; abort transfer.
|
|
|
|
// >= 0: bytes output; continue.
|
|
|
|
typedef ssize_t(*FileIOCB)(uintptr_t ctx, void* p, size_t size);
|
2004-03-03 00:56:51 +01:00
|
|
|
|
2004-08-27 02:33:20 +02:00
|
|
|
// transfer <size> bytes, starting at <ofs>, to/from the given file.
|
|
|
|
// (read or write access was chosen at file-open time).
|
|
|
|
//
|
|
|
|
// if non-NULL, <cb> is called for each block transferred, passing <ctx>.
|
|
|
|
// it returns how much data was actually transferred, or a negative error
|
|
|
|
// code (in which case we abort the transfer and return that value).
|
|
|
|
// the callback mechanism is useful for user progress notification or
|
|
|
|
// processing data while waiting for the next I/O to complete
|
|
|
|
// (quasi-parallel, without the complexity of threads).
|
|
|
|
//
|
|
|
|
// return number of bytes transferred (see above), or a negative error code.
|
2004-08-24 19:34:00 +02:00
|
|
|
extern ssize_t file_io(File* f, off_t ofs, size_t size, void* buf, FileIOCB cb = 0, uintptr_t ctx = 0);
|
2004-03-03 00:56:51 +01:00
|
|
|
|
|
|
|
|
2004-08-27 02:33:20 +02:00
|
|
|
//
|
|
|
|
// memory mapping
|
|
|
|
//
|
|
|
|
|
|
|
|
// useful for files that are too large to be loaded into memory,
|
|
|
|
// or if only (non-sequential) portions of a file are needed at a time.
|
|
|
|
|
|
|
|
|
|
|
|
// map the entire file <f> into memory. if already currently mapped,
|
|
|
|
// return the previous mapping (reference-counted).
|
|
|
|
// output parameters are zeroed on failure.
|
|
|
|
//
|
|
|
|
// the mapping will be removed (if still open) when its file is closed.
|
|
|
|
// however, map/unmap calls should still be paired so that the mapping
|
|
|
|
// may be removed when no longer needed.
|
|
|
|
//
|
|
|
|
// rationale: reference counting is required for zip_map: several
|
|
|
|
// Zip "mappings" each reference one ZArchive's actual file mapping.
|
|
|
|
// implement it here so that we also get refcounting for normal files.
|
|
|
|
extern int file_map(File* f, void*& p, size_t& size);
|
|
|
|
|
|
|
|
// decrement the reference count for the mapping belonging to file <f>.
|
|
|
|
// fail if there are no references; remove the mapping if the count reaches 0.
|
|
|
|
//
|
|
|
|
// the mapping will be removed (if still open) when its file is closed.
|
|
|
|
// however, map/unmap calls should still be paired so that the mapping
|
|
|
|
// may be removed when no longer needed.
|
|
|
|
extern int file_unmap(File* f);
|
|
|
|
|
2004-06-02 17:31:55 +02:00
|
|
|
#endif // #ifndef FILE_H
|