(********************************************************************) (* *) (* archive_base.s7i Common functions for file archives. *) (* Copyright (C) 2023 Thomas Mertes *) (* *) (* This file is part of the Seed7 Runtime Library. *) (* *) (* The Seed7 Runtime Library is free software; you can *) (* redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) (* Foundation; either version 2.1 of the License, or (at your *) (* option) any later version. *) (* *) (* The Seed7 Runtime Library 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 Lesser General Public License for more *) (* details. *) (* *) (* You should have received a copy of the GNU Lesser General *) (* Public License along with this program; if not, write to the *) (* Free Software Foundation, Inc., 51 Franklin Street, *) (* Fifth Floor, Boston, MA 02110-1301, USA. *) (* *) (********************************************************************) (** * Hash map that contains all paths in an archive as keys of the hash map. * The [[ar]], [[cpio]], [[rpm]], [[tar]] and [[zip]] libraries use this type * to maintain the paths of the files in the archive. Some archive libraries * store additional information in the value of the hash map. This additional * information is not used by [[#readDir(in_archiveRegisterType,in_string)|readDir]]. *) const type: archiveRegisterType is hash [string] integer; (** * Determine the file names in a directory inside an archive. * The [[ar]], [[cpio]], [[rpm]], [[tar]] and [[zip]] libraries use this function. * The archive libraries maintain the files in the archive with the hash map ''register''. * Note that the function returns only the file names. * Additional information must be obtained with other calls. * @param register Hash map that contains all paths in the archive as keys of the hash map. * @param dirPath Path of a directory in the archive. * @return an array with the file names. * @exception RANGE_ERROR ''dirPath'' does not use the standard path * representation. * @exception FILE_ERROR ''dirPath'' is not present in the ''register''. *) const func array string: readDir (in archiveRegisterType: register, in string: dirPath) is func result var array string: fileNames is 0 times ""; local var string: filePath is ""; var boolean: dirExists is FALSE; var set of string: fileNameSet is (set of string).value; var string: fileName is ""; var integer: slashPos is 0; begin if dirPath <> "/" and endsWith(dirPath, "/") then raise RANGE_ERROR; elsif dirPath = "" or dirPath = "." then for key fileName range register do slashPos := pos(fileName, '/'); if slashPos = 1 then fileName := "/"; elsif slashPos <> 0 then fileName := fileName[.. pred(slashPos)]; end if; if fileName not in fileNameSet then incl(fileNameSet, fileName); end if; end for; else for key filePath range register do if startsWith(filePath, dirPath) then fileName := filePath[succ(length(dirPath)) ..]; if fileName = "" then dirExists := TRUE; elsif startsWith(fileName, "/") then fileName := fileName[2 ..]; elsif dirPath <> "/" then fileName := ""; # A file name <> dirPath starts with dirPath. end if; slashPos := pos(fileName, '/'); if slashPos <> 0 then fileName := fileName[.. pred(slashPos)]; end if; if fileName <> "" and fileName not in fileNameSet then incl(fileNameSet, fileName); dirExists := TRUE; end if; end if; end for; if not dirExists then raise FILE_ERROR; end if; end if; fileNames := sort(toArray(fileNameSet)); end func; const func boolean: implicitDir (in archiveRegisterType: register, in string: dirPath) is func result var boolean: implicitDir is FALSE; local var string: filePath is ""; begin if dirPath <> "" then for key filePath range register do if startsWith(filePath, dirPath) and length(filePath) > length(dirPath) and (filePath[succ(length(dirPath))] = '/' or dirPath = "/") then implicitDir := TRUE; end if; end for; end if; end func; const func boolean: isEmptyDir (in archiveRegisterType: register, in string: dirPath) is func result var boolean: isEmptyDir is TRUE; local var string: filePath is ""; begin for key filePath range register do if startsWith(filePath, dirPath) and filePath <> dirPath then isEmptyDir := FALSE; end if; end for; end func;