Esempio n. 1
0
        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]);
        }
Esempio n. 2
0
        /**
         * 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);
        }
Esempio n. 3
0
        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}");
        }
Esempio n. 4
0
/**
 * 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);
        }
Esempio n. 5
0
        /**
         * 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);
        }
Esempio n. 6
0
        /**
         * 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);
        }
Esempio n. 7
0
        /**
         * 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);
        }
Esempio n. 8
0
        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);
        }
Esempio n. 9
0
        /**
         * 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);
                }
            }
        }
Esempio n. 10
0
        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);
        }
Esempio n. 11
0
        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);
            }
        }
Esempio n. 12
0
/**
 * 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));
        }
Esempio n. 13
0
/**
 * 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);
        }
Esempio n. 14
0
/**
 * 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;
            }
        }
Esempio n. 15
0
 public static void FioTarAddLink(string src, string dest, Subdirectory subdir)
 {
     TarAddLink(src, dest, subdir);
 }
Esempio n. 16
0
/**
 * 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);
Esempio n. 17
0
 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));
 }
Esempio n. 18
0
        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);
        }
Esempio n. 19
0
        /**
         * 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);
        }
Esempio n. 20
0
        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);
            }
        }
Esempio n. 21
0
        /**
         * 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);
        }