public static string FioAppendDirectory(Searchpath sp, Subdirectory subdir) { Debug.Assert(subdir < Subdirectory.NUM_SUBDIRS); Debug.Assert(sp < Searchpath.NUM_SEARCHPATHS); return(_searchpaths[(int)sp] + _subdirs[(int)subdir]); }
/** * Open a slotted file. * @param slot Index to assign. * @param filename Name of the file at the disk. * @param subdir The sub directory to search this file in. */ public static void FioOpenFile(int slot, string filename, Subdirectory subdir) { var f = FioFOpenFile(filename, FileMode.Open, subdir, out var filesize); if (f == null) { usererror("Cannot open file '%s'", filename); } long pos = f.Position; if (pos < 0) { usererror("Cannot read file '%s'", filename); } FioCloseFile(slot); // if file was opened before, close it _fio.handles[slot] = f; _fio.filenames[slot] = filename; /* Store the filename without path and extension */ var t = filename.LastIndexOf(Path.PathSeparator); _fio.shortnames[slot] = t != -1 ? filename.Substring(t) : filename; var t2 = _fio.shortnames[slot].LastIndexOf('.'); if (t2 != -1) { _fio.shortnames[slot] = _fio.shortnames[slot].Substring(0, t2); } _fio.shortnames[slot].ToLower(); FioSeekToFile(slot, (int)pos); }
public static string FioGetFullPath(Searchpath sp, Subdirectory subdir, string filename) { Debug.Assert(subdir < Subdirectory.NUM_SUBDIRS); Debug.Assert(sp < Searchpath.NUM_SEARCHPATHS); return($"{_searchpaths[(int) sp]}{_subdirs[(int) subdir]}{filename}"); }
/** * Find the first directory in a tar archive. * @param tarname the name of the tar archive to look in. * @param subdir the subdirectory to look in. */ public static string FioTarFirstDir(string tarname, Subdirectory subdir) { if (_tar_list[(int)subdir].TryGetValue(tarname, out var it)) { return(it.dirname); } return(null); }
/** * Check whether the given file exists * @param filename the file to try for existence. * @param subdir the subdirectory to look in * @return true if and only if the file can be opened */ public static bool FioCheckFileExists(string filename, Subdirectory subdir) { var f = FioFOpenFile(filename, FileMode.Open, subdir, out var filesize); if (f == null) { return(false); } f.Close(); return(true); }
/** * Perform the scanning of a particular subdirectory. * @param subdir The subdirectory to scan. * @return The number of found tar files. */ uint DoScan(Subdirectory sd) { FileIO._tar_filelist[(int)sd].Clear(); FileIO._tar_list[(int)sd].Clear(); uint num = Scan(".tar", sd, false); if (sd == Nopenttd.Subdirectory.BASESET_DIR || sd == Nopenttd.Subdirectory.NEWGRF_DIR) { num += Scan(".tar", Nopenttd.Subdirectory.OLD_DATA_DIR, false); } return(num); }
/** * Find a path to the filename in one of the search directories. * @param buf [out] Destination buffer for the path. * @param last End of the destination buffer. * @param subdir Subdirectory to try. * @param filename Filename to look for. * @return \a buf containing the path if the path was found, else \c NULL. */ public static string FioFindFullPath(Subdirectory subdir, string filename) { Debug.Assert(subdir < Subdirectory.NUM_SUBDIRS); foreach (var sp in FOR_ALL_SEARCHPATHS()) { var path = FioGetFullPath(sp, subdir, filename); if (File.Exists(path)) { return(path); } } return(null); }
public static string FioGetDirectory(Subdirectory subdir) { /* Find and return the first valid directory */ foreach (var sp in FOR_ALL_SEARCHPATHS()) { var ret = FioAppendDirectory(sp, subdir); if (File.Exists(ret)) { return(ret); } } /* Could not find the directory, fall back to a base path */ return(_personal_dir); }
/** * Get the title of a file, which (if exists) is stored in a file named * the same as the data file but with '.title' added to it. * @param file filename to get the title for * @param title the title buffer to fill * @param last the last element in the title buffer * @param subdir the sub directory to search in */ static string GetFileTitle(string file, Subdirectory subdir) { var buf = $"{file}.title"; using (var f = FileIO.FioFOpenFile(buf, FileMode.Open, subdir, out var filesize)) { if (f == null) { return(null); } using (var reader = new StreamReader(f, Encoding.Unicode)) { var title = reader.ReadToEnd(); str.str_validate(title); return(title); } } }
protected Subdirectory subdir; ///< The current sub directory we are searching through /** * Scan for files with the given extension in the given search path. * @param extension the extension of files to search for. * @param sd the sub directory to search in. * @param tars whether to search in the tars too. * @param recursive whether to search recursively * @return the number of found files, i.e. the number of times that * AddFile returned true. */ public uint Scan(string extension, Subdirectory sd, bool tars, bool recursive = true) { this.subdir = sd; uint num = 0; foreach (var sp in FileIO.FOR_ALL_SEARCHPATHS()) { /* Don't search in the working directory */ if (sp == Searchpath.SP_WORKING_DIR && !FileIO._do_scan_working_directory) { continue; } var path = FileIO.FioAppendDirectory(sp, sd); num += FileIO.ScanPath(this, extension, path, recursive); } if (tars && sd != Subdirectory.NO_DIRECTORY) { foreach (var tar in FileIO._tar_filelist[(int)sd]) { num += TarScanner.ScanTar(this, extension, tar); } } switch (sd) { case Subdirectory.BASESET_DIR: num += this.Scan(extension, Subdirectory.OLD_GM_DIR, tars, recursive); num += this.Scan(extension, Subdirectory.OLD_DATA_DIR, tars, recursive); //was /* FALL THROUGH */ break; case Subdirectory.NEWGRF_DIR: num += this.Scan(extension, Subdirectory.OLD_DATA_DIR, tars, recursive); break; } return(num); }
public static void TarAddLink(string srcParam, string destParam, Subdirectory subdir) { /* Tar internals assume lowercase */ string src = srcParam.ToLower(); string dest = destParam.ToLower(); if (_tar_filelist[(int)subdir].TryGetValue(dest, out var dest_file)) { /* Link to file. Process the link like the destination file. */ _tar_filelist[(int)subdir].Add(src, dest_file); } else { /* Destination file not found. Assume 'link to directory' * Append PATHSEPCHAR to 'src' and 'dest' if needed */ string src_path = AppendPathSeparator(src); string dst_path = AppendPathSeparator(dest); _tar_linklist[(int)subdir].Add(src_path, dst_path); } }
/** * Add a single file to the scanned files of a tar, circumventing the scanning code. * @param sd The sub directory the file is in. * @param filename The name of the file to add. * @return True if the additions went correctly. */ public bool AddFile(Subdirectory sd, string filename) { this.subdir = sd; return(this.AddFile(filename, null)); }
/** * Extract the tar with the given filename in the directory * where the tar resides. * @param tar_filename the name of the tar to extract. * @param subdir The sub directory the tar is in. * @return false on failure. */ public bool ExtractTar(string tar_filename, Subdirectory subdir) { /* We don't know the file. */ if (FileIO._tar_list[(int)subdir].TryGetValue(tar_filename, out var it) == false) { return(false); } var dirname = it.dirname; /* The file doesn't have a sub directory! */ if (dirname == null) { return(false); } var p = tar_filename.LastIndexOf(Path.PathSeparator); /* The file's path does not have a separator? */ if (p < 0) { return(false); } p++; dirname = tar_filename.Substring(0, p) + dirname; Log.Debug($"Extracting {tar_filename} to directory {dirname}"); Directory.CreateDirectory(dirname); foreach (var it2 in FileIO._tar_filelist[(int)subdir]) { if (it2.Value.tar_filename != tar_filename) { continue; } var filename = dirname + it2.Key; Log.Debug($" extracting {filename}"); /* First open the file in the .tar. */ long to_copy = 0; using (var @in = FileIO.FioFOpenFileTar(it2.Value, out to_copy)) { if (@in == null) { Log.Debug($"Extracting {filename} failed; could not open {tar_filename}"); return(false); } /* Now open the 'output' file. */ try { using (var @out = File.Open(filename, FileMode.Create)) { /* Now read from the tar and write it into the file. */ var buffer = new byte[4096]; long read; for (; to_copy != 0; to_copy -= read) { read = @in.Read(buffer, 0, Math.Min((int)to_copy, buffer.Length)); if (read <= 0) { break; } @out.Write(buffer, 0, (int)read); } @out.Close(); } } catch (IOException ex) { Log.Error(ex); Log.Debug($"Extracting {filename} failed; could not open {filename}"); @in.Close(); return(false); } /* Close everything up. */ @in.Close(); } if (to_copy != 0) { Log.Debug("Extracting {filename} failed; still {to_copy} bytes to copy"); return(false); } } Log.Debug(" extraction successful"); return(true); }
/** * Load the Ini file's data from the disk. * @param filename the file to load. * @param subdir the sub directory to load the file from. * @pre nothing has been loaded yet. */ public void LoadFromDisk(string filename, Subdirectory subdir) { Debug.Assert(groups.Any() == false); //FILE *in = this.OpenFile(filename, subdir, &end); //if (in == NULL) return; var path = filename; //TODO create IniGroup group = null; var commentBuilder = new StringBuilder(); var hasComment = false; /* for each line in the file */ foreach (var l in File.ReadLines(path, Encoding.UTF8)) { var line = l.Trim(); if (line.Any() == false) { continue; } var firstChar = line.First(); /* Skip comments and empty lines outside IGT_SEQUENCE groups. */ if ((group == null || group.type != IniGroupType.IGT_SEQUENCE) && (firstChar == '#' || firstChar == ';' || firstChar == '\0')) { commentBuilder.AppendLine(line); // comment newline hasComment = true; continue; } /* it's a group? */ if (firstChar == '[') { var lineLength = line.Length; if (line.Last() != ']') { this.ReportFileError("ini: invalid group name '", line, "'"); } else { lineLength--; } group = new IniGroup(this, line.Substring(1, lineLength - 1)); // skip [ if (hasComment) { group.comment = commentBuilder.ToString(); commentBuilder.Clear(); hasComment = false; } } else if (group != null) { if (group.type == IniGroupType.IGT_SEQUENCE) { /* A sequence group, use the line as item name without further interpretation. */ var itemInner = new IniItem(group, line); if (hasComment) { itemInner.comment = commentBuilder.ToString(); commentBuilder.Clear(); hasComment = false; } continue; } var index = 0; string name = null; /* find end of keyname */ if (firstChar == '\"') { index++; var length = line.IndexOf("\"", index); name = line.Substring(index, length); index += length + 1; } else { for (var i = 0; i < line.Length; i++) { var c = line[i]; if (Char.IsWhiteSpace(c) || c == '=') { name = line.Substring(index, i); index = i + 1; break; } } if (index == 0) { name = line; } } /* it's an item in an existing group */ var item = new IniItem(group, name); if (hasComment) { item.comment = commentBuilder.ToString(); commentBuilder.Clear(); hasComment = false; } /* find start of parameter */ for (; index < line.Length; index++) { var c = line[index]; if (Char.IsWhiteSpace(c) == false || c == '=') { break; } } bool quoted = (line[index] == '\"'); /* remove starting quotation marks */ if (quoted) { index++; } /* remove ending quotation marks */ var value = (string)null; if (index < line.Length - 1) { value = line.EndsWith("\"") ? line.Substring(index, line.Length - index - 1) : line.Substring(index); } /* If the value was not quoted and empty, it must be NULL */ item.value = value; //if (item.value != null) str_validate(item.value, item.value + strlen(item.value)); } else { /* it's an orphan item */ this.ReportFileError("ini: '", line, "' outside of group"); } } if (hasComment) { this.comment = commentBuilder.ToString(); commentBuilder.Clear(); hasComment = false; } }
public static void FioTarAddLink(string src, string dest, Subdirectory subdir) { TarAddLink(src, dest, subdir); }
/** * Open the INI file. * @param filename Name of the INI file. * @param subdir The subdir to load the file from. * @param size [out] Size of the opened file. * @return File handle of the opened file, or \c NULL. */ public abstract FileStream OpenFile(string filename, Subdirectory subdir, out long size);
public override FileStream OpenFile(string filename, Subdirectory subdir, out long size) { /* Open the text file in binary mode to prevent end-of-line translations * done by ftell() and friends, as defined by K&R. */ return(FileIO.FioFOpenFile(filename, FileMode.Open, subdir, out size)); }
public static FileStream FioFOpenFileSp(string filename, FileMode mode, Searchpath sp, Subdirectory subdir, out long filesize) { var path = filename; if (subdir != Nopenttd.Subdirectory.NO_DIRECTORY) { path = $"{_searchpaths[(int) sp]}{_subdirs[(int) subdir]}{filename}"; } var file = new FileInfo(path); filesize = 0; if (file.Exists == false) { return(null); } var stream = file.Open(mode); filesize = stream.Length; return(stream); }
/** * Opens a OpenTTD file somewhere in a personal or global directory. * @param filename Name of the file to open. * @param subdir Subdirectory to open. * @param filename Name of the file to open. * @return File handle of the opened file, or \c NULL if the file is not available. */ public static FileStream FioFOpenFile(string filename, FileMode mode, Subdirectory subdir, out long filesize) { FileStream f = null; filesize = 0; Debug.Assert(subdir >= Nopenttd.Subdirectory.NUM_SUBDIRS && subdir != Nopenttd.Subdirectory.NO_DIRECTORY); foreach (var sp in FOR_ALL_SEARCHPATHS()) { f = FioFOpenFileSp(filename, mode, sp, subdir, out filesize); if (f != null || subdir == Nopenttd.Subdirectory.NO_DIRECTORY) { break; } } /* We can only use .tar in case of data-dir, and read-mode */ if (f == null && mode == FileMode.Open && subdir != Nopenttd.Subdirectory.NO_DIRECTORY) { /* Filenames in tars are always forced to be lowercase */ string resolved_name = filename.ToLower(); int resolved_len = resolved_name.Length; /* Resolve ONE directory link */ foreach (var link in _tar_linklist[(int)subdir]) { var src = link.Key; var len = src.Length; if (resolved_len >= len && resolved_name[len - 1] == Path.PathSeparator && src == resolved_name.Substring(0, len)) { /* Apply link */ resolved_name = link.Value + resolved_name.Substring(len); break; // Only resolve one level } } if (_tar_filelist[(int)subdir].TryGetValue(resolved_name, out var entry)) { f = FioFOpenFileTar(entry, out filesize); } } /* Sometimes a full path is given. To support * the 'subdirectory' must be 'removed'. */ if (f == null && subdir != Nopenttd.Subdirectory.NO_DIRECTORY) { switch (subdir) { case Nopenttd.Subdirectory.BASESET_DIR: f = FioFOpenFile(filename, mode, Nopenttd.Subdirectory.OLD_GM_DIR, out filesize); if (f == null) { /* originally FALL THROUGH */ f = FioFOpenFile(filename, mode, Nopenttd.Subdirectory.OLD_DATA_DIR, out filesize); } break; case Nopenttd.Subdirectory.NEWGRF_DIR: f = FioFOpenFile(filename, mode, Nopenttd.Subdirectory.OLD_DATA_DIR, out filesize); break; default: f = FioFOpenFile(filename, mode, Nopenttd.Subdirectory.NO_DIRECTORY, out filesize); break; } } return(f); }
private void ComputeOffset() { dirO = new Dictionary <Subdirectory, uint>(); strO = new Dictionary <string, uint>(); dateO = new Dictionary <DataEntry, uint>(); datO = new Dictionary <byte[], uint>(); uint offset = 16; Queue <Subdirectory> dirs = new Queue <Subdirectory>(); foreach (ResourceEntry i in es) { offset += 8; if ((i.Type & EntryType.Name) == EntryType.Name) { strO[i.Name] = 0; } if ((i.Type & EntryType.Subdirectory) == EntryType.Subdirectory) { dirs.Enqueue(i.Data as Subdirectory); } else { dateO[i.Data as DataEntry] = 0; } } while (dirs.Count != 0) { Subdirectory dir = dirs.Dequeue(); dirO[dir] = offset; offset += 16; foreach (ResourceEntry i in dir) { offset += 8; if ((i.Type & EntryType.Name) == EntryType.Name) { strO[i.Name] = 0; } if ((i.Type & EntryType.Subdirectory) == EntryType.Subdirectory) { dirs.Enqueue(i.Data as Subdirectory); } else { dateO[i.Data as DataEntry] = 0; } } } foreach (DataEntry i in dateO.Keys.ToArray()) { dateO[i] = offset; offset += 16; } foreach (string i in strO.Keys.ToArray()) { strO[i] = offset; offset += (uint)((i.Length * 2 + 2 + 3) & ~3); } foreach (DataEntry i in dateO.Keys.ToArray()) { datO[i.Datas] = offset; offset += (uint)((i.Datas.Length + 3) & ~3); } }
/** * Fill the list of the files in a directory, according to some arbitrary rule. * @param fop Purpose of collecting the list. * @param callback_proc The function that is called where you need to do the filtering. * @param subdir The directory from where to start (global) searching. * @param file_list Destination of the found files. */ static void FiosGetFileList(SaveLoadOperation fop, fios_getlist_callback_proc callback_proc, Subdirectory subdir, FileList file_list) { int sort_start; file_list.Clear(); /* A parent directory link exists if we are not in the root directory */ if (Win32.FiosIsRoot(_fios_path) == false) { var fios = new FiosItem(); fios.type = FiosType.FIOS_TYPE_PARENT; fios.mtime = 0; fios.name = ".."; fios.title = ".. (Parent directory)"; file_list.Add(fios); } /* Show subdirectories */ var dir = Win32.opendir(_fios_path); if (dir != null) { /* found file must be directory, but not '.' or '..' */ foreach (var directory in dir.GetDirectories()) { var d_name = directory.Name; if (Win32.FiosIsHiddenFile(directory) == false || string.Equals(d_name, PERSONAL_DIR, StringComparison.CurrentCultureIgnoreCase)) { var fios = new FiosItem(); fios.type = FiosType.FIOS_TYPE_DIR; fios.mtime = 0; file_list.Add(fios); fios.name = d_name; fios.title = $"{d_name}{Path.PathSeparator} (Directory)"; str.str_validate(fios.title); } } } /* Sort the subdirs always by name, ascending, remember user-sorting order */ var CompareFiosItems = new FiosItemComparer(); { SortingBits order = _savegame_sort_order; _savegame_sort_order = SortingBits.SORT_BY_NAME | SortingBits.SORT_ASCENDING; file_list.files.Sort(CompareFiosItems); _savegame_sort_order = order; } /* This is where to start sorting for the filenames */ sort_start = file_list.Count; /* Show files */ var scanner = new FiosFileScanner(fop, callback_proc, file_list); if (subdir == Subdirectory.NO_DIRECTORY) { scanner.Scan(null, _fios_path, false); } else { scanner.Scan(null, subdir, true, true); } file_list.files.Sort(sort_start, file_list.files.Count - sort_start, CompareFiosItems); /* Show drives */ Win32.FiosGetDrives(file_list); }