- Timestamp:
- 06/03/04 15:57:00 (21 years ago)
- Location:
- ps/trunk/source/lib/res
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
ps/trunk/source/lib/res/vfs.cpp
r373 r385 689 689 690 690 691 // mount either a single archive or a directory into the VFS at 692 // <vfs_mount_point>, which is created if it does not yet exist. 693 // new files override the previous VFS contents if pri(ority) is higher. 694 // if <name> is a directory, all archives in that directory (but not 695 // its subdirs - see add_dirent_cb) are also mounted in alphabetical order. 696 // name = "." or "./" isn't allowed - see implementation for rationale. 691 697 int vfs_mount(const char* const vfs_mount_point, const char* const name, const uint pri) 692 698 { … … 701 707 } 702 708 709 CHECK_PATH(name); 710 711 // TODO: disallow mounting parent directory of a previous mounting 712 703 713 // disallow . because "./" isn't supported on Windows. 704 714 // the more important reason is that mount points must not overlap … … 719 729 720 730 731 // rebuild the VFS, i.e. re-mount everything. open files are not affected. 732 // necessary after loose files or directories change, so that the VFS 733 // "notices" the changes and updates file locations. res calls this after 734 // FAM reports changes; can also be called from the console after a 735 // rebuild command. there is no provision for updating single VFS dirs - 736 // it's not worth the trouble. 721 737 int vfs_rebuild() 722 738 { … … 729 745 730 746 747 // unmount a previously mounted item, and rebuild the VFS afterwards. 731 748 int vfs_unmount(const char* name) 732 749 { … … 753 770 754 771 755 int vfs_realpath(const char* fn, char* full_path)756 {757 const FileLoc* loc;758 CHECK_ERR(tree_lookup(fn, &loc));759 760 if(loc->archive > 0)761 {762 const char* archive_fn = h_filename(loc->archive);763 if(!archive_fn)764 return -1;765 strncpy(full_path, archive_fn, PATH_MAX);766 }767 else768 {769 strncpy(full_path, loc->dir.c_str(), PATH_MAX);770 }771 772 return 0;773 }774 775 776 int vfs_stat(const char* fn, struct stat* s)777 {778 const FileLoc* loc;779 CHECK_ERR(tree_lookup(fn, &loc));780 781 if(loc->archive > 0)782 return zip_stat(loc->archive, fn, s);783 else784 {785 const char* dir = loc->dir.c_str();786 return file_stat(dir, s);787 }788 }789 790 791 772 struct VDir 792 773 { 793 774 // we need to cache the complete contents of the directory: 794 // 775 // if we reference the real directory and it changes, 776 // the c_str pointers may become invalid, and some files 777 // may be returned out of order / not at all. 778 // we copy the directory's subdirectory and file containers. 795 779 SubDirs* subdirs; 796 780 SubDirIt subdir_it; … … 818 802 CHECK_ERR(tree_lookup(path, 0, &dir)); 819 803 804 // rationale for copy: see VDir definition 820 805 vd->subdirs = new SubDirs(dir->subdirs); 821 806 vd->subdir_it = vd->subdirs->begin(); … … 826 811 827 812 828 Handle vfs_open_dir(const char* const path) 829 { 830 return h_alloc(H_VDir, path, 0); 831 } 832 833 813 // open a directory for reading its entries via vfs_next_dirent. 814 // directory contents are cached here; subsequent changes to the dir 815 // are not returned by this handle. rationale: see VDir definition. 816 Handle vfs_open_dir(const char* const dir) 817 { 818 return h_alloc(H_VDir, dir, 0); 819 } 820 821 822 // close the handle to a directory. 823 // all vfsDirEnt.name strings are now invalid. 834 824 int vfs_close_dir(Handle& hd) 835 825 { … … 838 828 839 829 840 // filter: 841 // 0: any file 842 // ".": file without extension (filename doesn't contain '.') 843 // ".ext": file with extension <ext> (which must not contain '.') 844 // "/": subdirectory 830 // get the next directory entry (in alphabetical order) that matches filter. 831 // return 0 on success. filter values: 832 // - 0: any file; 833 // - ".": any file without extension (filename doesn't contain '.'); 834 // - ".ext": any file with extension ".ext" (which must not contain '.'); 835 // - "/": any subdirectory 845 836 int vfs_next_dirent(const Handle hd, vfsDirEnt* ent, const char* const filter) 846 837 { 847 838 H_DEREF(hd, VDir, vd); 848 839 849 // interpret filter 840 // interpret filter (paranoid) 850 841 bool filter_dir = false; 851 842 bool filter_no_ext = false; … … 872 863 } 873 864 865 // rationale: the filename is currently stored internally as 866 // std::string (=> less manual memory allocation). we don't want to 867 // return a reference, because that would break C compatibility. 868 // we're trying to avoid fixed-size buffers, so that is out as well. 869 // finally, allocating a copy is not so good because it has to be 870 // freed by the user (won't happen). returning a volatile pointer 871 // to the string itself via c_str is the only remaining option. 874 872 const char* fn; 875 873 … … 915 913 916 914 915 // return actual path to the specified file: 916 // "<real_directory>/fn" or "<archive_name>/fn". 917 int vfs_realpath(const char* fn, char* full_path) 918 { 919 const FileLoc* loc; 920 CHECK_ERR(tree_lookup(fn, &loc)); 921 922 const char* dir; 923 924 // file is in normal directory 925 if(loc->archive <= 0) 926 dir = loc->dir.c_str(); 927 // file is in archive 928 { 929 // "dir" is the archive filename 930 dir = h_filename(loc->archive); 931 if(!dir) 932 return -1; 933 } 934 935 CHECK_ERR(path_append(full_path, dir, fn)); 936 return 0; 937 } 938 939 940 // return information about the specified file as in stat(2), 941 // most notably size. stat buffer is undefined on error. 942 int vfs_stat(const char* fn, struct stat* s) 943 { 944 const FileLoc* loc; 945 CHECK_ERR(tree_lookup(fn, &loc)); 946 947 if(loc->archive > 0) 948 return zip_stat(loc->archive, fn, s); 949 else 950 { 951 // similar to realpath, but don't bother splitting it out. 952 char path[VFS_MAX_PATH]; 953 path_append(path, loc->dir.c_str(), fn); 954 return file_stat(path, s); 955 } 956 } 957 958 917 959 /////////////////////////////////////////////////////////////////////////////// 918 960 // … … 1039 1081 1040 1082 1083 // open the file for synchronous or asynchronous IO. write access is 1084 // requested via VFS_WRITE flag, and is not possible for files in archives. 1041 1085 Handle vfs_open(const char* fn, uint flags /* = 0 */) 1042 1086 { … … 1052 1096 1053 1097 1098 // close the handle to a file. 1054 1099 inline int vfs_close(Handle& h) 1055 1100 { … … 1062 1107 1063 1108 1064 ssize_t vfs_io(Handle hf, off_t ofs, size_t size, void*& p) 1109 // try to transfer <size> bytes, starting at <ofs>, to/from the given file. 1110 // (read or write access was chosen at file-open time). 1111 // return bytes of actual data transferred, or a negative error code. 1112 // TODO: buffer types 1113 ssize_t vfs_io(const Handle hf, const off_t ofs, const size_t size, void*& p) 1065 1114 { 1066 1115 #ifdef PARANOIA … … 1081 1130 1082 1131 1083 Handle vfs_load(const char* fn, void*& p, size_t& size) 1132 // load the entire file <fn> into memory; return a handle to the memory 1133 // and the buffer address/size. output parameters are zeroed on failure. 1134 Handle vfs_load(const char* const fn, void*& p, size_t& size) 1084 1135 { 1085 1136 #ifdef PARANOIA … … 1145 1196 1146 1197 1198 /////////////////////////////////////////////////////////////////////////////// 1147 1199 // 1148 1200 // memory mapping 1149 1201 // 1202 /////////////////////////////////////////////////////////////////////////////// 1203 1150 1204 1151 1205 // map the entire file <hf> into memory. if already currently mapped, … … 1186 1240 return file_unmap(&vf->f); 1187 1241 } 1242 1243 1244 /////////////////////////////////////////////////////////////////////////////// 1245 // 1246 // asynchronous I/O 1247 // 1248 /////////////////////////////////////////////////////////////////////////////// 1249 1250 1251 // begin transferring <size> bytes, starting at <ofs>. get result 1252 // with vfs_wait_read; when no longer needed, free via vfs_discard_io. 1253 Handle vfs_start_io(Handle hf, off_t ofs, size_t size, void* buf) 1254 { 1255 H_DEREF(hf, VFile, vf); 1256 if(vf_flags(vf) & VF_ZIP) 1257 ; 1258 1259 return 0; 1260 } 1261 1262 1263 // wait until the transfer <hio> completes, and return its buffer. 1264 // output parameters are zeroed on error. 1265 int vfs_wait_io(Handle hio, void*& p, size_t& size) 1266 { 1267 p = 0; 1268 size = 0; 1269 1270 return 0; 1271 } 1272 1273 1274 // finished with transfer <hio> - free its buffer (returned by vfs_wait_read) 1275 int vfs_discard_io(Handle& hio) 1276 { 1277 return 0; 1278 } -
ps/trunk/source/lib/res/vfs.h
r373 r385 21 21 #define __VFS_H__ 22 22 23 #include "h_mgr.h" 23 #include "h_mgr.h" // Handle 24 24 #include "posix.h" // struct stat 25 25 26 27 // 28 // VFS tree 29 // 30 26 31 // the VFS doesn't require this length restriction - VFS internal storage 27 // is not fixed-length. the purpose here is to allow fixed-sized path buffers 28 // allocated on the stack. 29 // 30 // length includes trailing '\0'. 32 // is not fixed-length. the purpose here is to give an indication of how 33 // large fixed-size user buffers should be. length includes trailing '\0'. 31 34 #define VFS_MAX_PATH 256 32 35 36 // VFS paths are of the form: 37 // "[dir/{subdir/}]file" or "[dir/{subdir/}]dir[/]". 38 // in English: '/' as path separator; trailing '/' allowed for dir names; 39 // no leading '/', since "" is the root dir. 40 41 // mount either a single archive or a directory into the VFS at 42 // <vfs_mount_point>, which is created if it does not yet exist. 43 // new files override the previous VFS contents if pri(ority) is higher. 44 // if <name> is a directory, all archives in that directory (but not 45 // its subdirs - see add_dirent_cb) are also mounted in alphabetical order. 46 // name = "." or "./" isn't allowed - see implementation for rationale. 33 47 extern int vfs_mount(const char* vfs_mount_point, const char* name, uint pri); 34 extern int vfs_umount(const char* name);35 48 36 extern int vfs_stat(const char* fn, struct stat*); 49 // rebuild the VFS, i.e. re-mount everything. open files are not affected. 50 // necessary after loose files or directories change, so that the VFS 51 // "notices" the changes and updates file locations. res calls this after 52 // FAM reports changes; can also be called from the console after a 53 // rebuild command. there is no provision for updating single VFS dirs - 54 // it's not worth the trouble. 55 extern int vfs_rebuild(); 56 57 // unmount a previously mounted item, and rebuild the VFS afterwards. 58 extern int vfs_unmount(const char* name); 59 60 61 // 62 // directory entry 63 // 64 65 // information about a directory entry, returned by vfs_next_dirent. 66 struct vfsDirEnt 67 { 68 // name of directory entry - does not include path. 69 // valid until the directory handle is closed. must not be modified! 70 // rationale for pointer and invalidation: see vfs_next_dirent. 71 const char* name; 72 }; 73 74 // open the directory for reading its entries via vfs_next_dirent. 75 // directory contents are cached here; subsequent changes to the dir 76 // are not returned by this handle. rationale: see VDir definition. 77 extern Handle vfs_open_dir(const char* dir); 78 79 // close the handle to a directory. 80 // all vfsDirEnt.name strings are now invalid. 81 extern int vfs_close_dir(Handle& hd); 82 83 // get the next directory entry (in alphabetical order) that matches filter. 84 // return 0 on success. filter values: 85 // - 0: any file; 86 // - ".": any file without extension (filename doesn't contain '.'); 87 // - ".ext": any file with extension ".ext" (which must not contain '.'); 88 // - "/": any subdirectory 89 extern int vfs_next_dirent(Handle hd, vfsDirEnt* ent, const char* filter); 90 91 92 // 93 // file 94 // 95 96 // return actual path to the specified file: 97 // "<real_directory>/fn" or "<archive_name>/fn". 37 98 extern int vfs_realpath(const char* fn, char* realpath); 38 99 39 extern Handle vfs_load(const char* fn, void*& p, size_t& size); 100 // return information about the specified file as in stat(2), 101 // most notably size. stat buffer is undefined on error. 102 extern int vfs_stat(const char* fn, struct stat*); 40 103 104 // vfs_open flags - keep in sync with file.cpp flag definitions! 105 enum vfsOpenFlags 106 { 107 // write-only access; otherwise, read only 108 VFS_WRITE = 0x01, 109 110 // buffers returned may be read-only (allows some caching optimizations) 111 VFS_MEM_READONLY = 0x02, 112 113 // don't cache the whole file, e.g. if kept in memory elsewhere anyway. 114 VFS_NOCACHE = 0x04, 115 116 // random access hint 117 VFS_RANDOM = 0x08 118 119 }; 120 121 // open the file for synchronous or asynchronous IO. write access is 122 // requested via VFS_WRITE flag, and is not possible for files in archives. 41 123 extern Handle vfs_open(const char* fn, uint flags = 0); 124 125 // close the handle to a file. 42 126 extern int vfs_close(Handle& h); 43 127 … … 66 150 67 151 // 68 // directory entry enumeration152 // asynchronous I/O 69 153 // 70 154 71 struct vfsDirEnt 72 { 73 // the filename is currently stored internally as std::string. returning as char* for C compat 74 // stored internally as std::string. returning as char* for C compat 75 // would mean we have to return a copy. we try to avoid fixed-size 76 // buffers, so that leaves a reference. 77 const char* name; 78 }; 155 // begin transferring <size> bytes, starting at <ofs>. get result 156 // with vfs_wait_read; when no longer needed, free via vfs_discard_io. 157 extern Handle vfs_start_io(Handle hf, off_t ofs, size_t size, void* buf); 79 158 80 extern Handle vfs_open_dir(const char* path); 81 extern int vfs_close_dir(Handle& hd); 82 extern int vfs_next_dirent(Handle hd, vfsDirEnt* ent, const char* filter); 159 // wait until the transfer <hio> completes, and return its buffer. 160 // output parameters are zeroed on error. 161 extern int vfs_wait_io(Handle hio, void*& p, size_t& size); 162 163 // finished with transfer <hio> - free its buffer (returned by vfs_wait_read). 164 extern int vfs_discard_io(Handle& hio); 83 165 84 166 85 167 // 86 // async read interface168 // synchronous I/O 87 169 // 88 170 89 extern Handle vfs_start_read(const Handle hf, off_t ofs, size_t& advance, void* buf); 90 extern int vfs_wait_read(Handle hr, void*& p, size_t& size); 91 extern int vfs_discard_read(Handle& hr); 92 171 // try to transfer <size> bytes, starting at <ofs>. 172 // (read or write access was chosen at file-open time). 173 // return bytes of actual data transferred, or a negative error code. 174 // TODO: buffer types 93 175 extern ssize_t vfs_io(Handle hf, off_t ofs, size_t size, void*& p); 94 176 95 96 // keep in sync with File flags! 97 98 enum 99 { 100 VFS_WRITE = 1, // write-only access; otherwise, read only 101 VFS_MEM_READONLY = 2, // !want to be able to change in memory data 102 VFS_NOCACHE = 4, // don't cache whole file, e.g. if cached on a higher level 103 VFS_RANDOM = 8 // random access hint, allow offset 104 }; 105 106 107 108 extern int vfs_rebuild(); 177 // load the entire file <fn> into memory; return a memory handle to the 178 // buffer and its address/size. output parameters are zeroed on failure. 179 extern Handle vfs_load(const char* fn, void*& p, size_t& size); 109 180 110 181
Note:
See TracChangeset
for help on using the changeset viewer.
