(********************************************************************) (* *) (* osfiles.s7i Functions to handle operating system files *) (* Copyright (C) 1989 - 2017, 2019 - 2021, 2023 Thomas Mertes *) (* 2024 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. *) (* *) (********************************************************************) include "enable_io.s7i"; include "time.s7i"; include "bigint.s7i"; include "filesys.s7i"; const proc: GET_ATIME (in string: filePath, inout integer: year, inout integer: month, inout integer: day, inout integer: hour, inout integer: minute, inout integer: second, inout integer: micro_second, inout integer: timeZone, inout boolean: daylightSavingTime) is action "CMD_GET_ATIME"; const proc: GET_CTIME (in string: filePath, inout integer: year, inout integer: month, inout integer: day, inout integer: hour, inout integer: minute, inout integer: second, inout integer: micro_second, inout integer: timeZone, inout boolean: daylightSavingTime) is action "CMD_GET_CTIME"; const proc: GET_MTIME (in string: filePath, inout integer: year, inout integer: month, inout integer: day, inout integer: hour, inout integer: minute, inout integer: second, inout integer: micro_second, inout integer: timeZone, inout boolean: daylightSavingTime) is action "CMD_GET_MTIME"; const proc: SET_ATIME (in string: filePath, in integer: year, in integer: month, in integer: day, in integer: hour, in integer: minute, in integer: second, in integer: micro_second, in integer: timeZone) is action "CMD_SET_ATIME"; const proc: SET_MTIME (in string: filePath, in integer: year, in integer: month, in integer: day, in integer: hour, in integer: minute, in integer: second, in integer: micro_second, in integer: timeZone) is action "CMD_SET_MTIME"; const proc: GET_ATIME_OF_SYMLINK (in string: filePath, inout integer: year, inout integer: month, inout integer: day, inout integer: hour, inout integer: minute, inout integer: second, inout integer: micro_second, inout integer: timeZone, inout boolean: daylightSavingTime) is action "CMD_GET_ATIME_OF_SYMLINK"; const proc: GET_MTIME_OF_SYMLINK (in string: filePath, inout integer: year, inout integer: month, inout integer: day, inout integer: hour, inout integer: minute, inout integer: second, inout integer: micro_second, inout integer: timeZone, inout boolean: daylightSavingTime) is action "CMD_GET_MTIME_OF_SYMLINK"; const proc: SET_MTIME_OF_SYMLINK (in string: filePath, in integer: year, in integer: month, in integer: day, in integer: hour, in integer: minute, in integer: second, in integer: micro_second, in integer: timeZone) is action "CMD_SET_MTIME_OF_SYMLINK"; (** * Determine the filenames in a directory. * The function does follow symbolic links. * The files "." and ".." are excluded from the result. * Note that the function returns only the filenames. * Additional information must be obtained using other calls. * @return a string-array containing the filenames in the directory. * @exception MEMORY_ERROR Not enough memory to convert ''dirPath'' * to the system path type or not enough memory to * represent the result ''string array''. * @exception RANGE_ERROR ''dirPath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception FILE_ERROR The file described with ''dirPath'' does not * exist, or it is not a directory, or a system function * returns an error. *) const func array string: readDir (in string: dirPath) is action "CMD_READ_DIR"; (** * Determine the type of a file. * The function does follow symbolic links. If the chain of * symbolic links is too long the function returns ''FILE_SYMLINK''. * If a symbolic link refers to a place where the permission * is denied the function returns ''FILE_SYMLINK''. * A return value of ''FILE_ABSENT'' does not imply that a file * with this name can be created, since missing directories and * invalid file names cause also ''FILE_ABSENT''. * @return the type of the file. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' * to the system path type. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation. * @exception FILE_ERROR The system function returns an error other * than ENOENT, ENOTDIR, ENAMETOOLONG or EACCES. *) const func fileType: fileType (in string: filePath) is action "CMD_FILETYPE"; (** * Determine the type of a file. * The function does not follow symbolic links. Therefore it may * return ''FILE_SYMLINK''. A return value of ''FILE_ABSENT'' does * not imply that a file with this name can be created, since missing * directories and invalid file names cause also ''FILE_ABSENT''. * @return the type of the file. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' * to the system path type. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation. * @exception FILE_ERROR The system function returns an error other * than ENOENT, ENOTDIR, ENAMETOOLONG or EACCES. *) const func fileType: fileTypeSL (in string: filePath) is action "CMD_FILETYPE_SL"; (** * Determine the size of a file. * The function follows symbolic links. The file size is measured in bytes. * For directories, fifos and sockets a size of 0 is returned. * @return the size of the file. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' * to the system path type. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception RANGE_ERROR The file size is not representable as integer. * @exception FILE_ERROR It was not possible to determine the file size. *) const func integer: fileSize (in string: filePath) is action "CMD_FILESIZE"; (** * Determine the size of a file. * The function follows symbolic links. The file size is measured in bytes. * For directories, fifos and sockets a size of 0 is returned. * @return the size of the file. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' * to the system path type. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception FILE_ERROR It was not possible to determine the file size. *) const func bigInteger: bigFileSize (in string: filePath) is action "CMD_BIG_FILESIZE"; (** * Determine the file mode (permissions) of a file. * The function follows symbolic links. * @return the file mode. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' * to the system path type. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception FILE_ERROR The file described with ''filePath'' does not * exist, or a system function returns an error. *) const func fileMode: getFileMode (in string: filePath) is action "CMD_GET_FILE_MODE"; # The function fileMode() is deprecated. Use getFileMode() instead. const func fileMode: fileMode (in string: filePath) is return getFileMode(filePath); (** * Change the file mode (permissions) of a file. * The function follows symbolic links. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' * to the system path type. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception FILE_ERROR The file described with ''filePath'' does not * exist, or a system function returns an error. *) const proc: setFileMode (in string: filePath, in fileMode: mode) is action "CMD_SET_FILE_MODE"; (** * Determine the access time of a file. * The function follows symbolic links. * @return the access time of the file. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' * to the system path type. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception FILE_ERROR The file described with ''filePath'' does not * exist, or a system function returns an error. *) const func time: getATime (in string: filePath) is func result var time: accessTime is time.value; begin GET_ATIME(filePath, accessTime.year, accessTime.month, accessTime.day, accessTime.hour, accessTime.minute, accessTime.second, accessTime.micro_second, accessTime.timeZone, accessTime.daylightSavingTime); end func; (** * Set the access time of a file. * The function follows symbolic links. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' * to the system path type. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception RANGE_ERROR ''aTime'' is invalid or it cannot be * converted to the system file time. * @exception FILE_ERROR The file described with ''filePath'' does not * exist, or a system function returns an error. *) const proc: setATime (in string: filePath, in time: aTime) is func begin SET_ATIME(filePath, aTime.year, aTime.month, aTime.day, aTime.hour, aTime.minute, aTime.second, aTime.micro_second, aTime.timeZone); end func; (** * Determine the change time of a file. * The function follows symbolic links. * @return the change time of the file. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' * to the system path type. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception FILE_ERROR The file described with ''filePath'' does not * exist, or a system function returns an error. *) const func time: getCTime (in string: filePath) is func result var time: changeTime is time.value; begin GET_CTIME(filePath, changeTime.year, changeTime.month, changeTime.day, changeTime.hour, changeTime.minute, changeTime.second, changeTime.micro_second, changeTime.timeZone, changeTime.daylightSavingTime); end func; (** * Determine the modification time of a file. * The function follows symbolic links. * @return the modification time of the file. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' * to the system path type. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception FILE_ERROR The file described with ''filePath'' does not * exist, or a system function returns an error. *) const func time: getMTime (in string: filePath) is func result var time: modificationTime is time.value; begin GET_MTIME(filePath, modificationTime.year, modificationTime.month, modificationTime.day, modificationTime.hour, modificationTime.minute, modificationTime.second, modificationTime.micro_second, modificationTime.timeZone, modificationTime.daylightSavingTime); end func; (** * Set the modification time of a file. * The function follows symbolic links. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' * to the system path type. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception RANGE_ERROR ''mTime'' is invalid or it cannot be * converted to the system file time. * @exception FILE_ERROR The file described with ''filePath'' does not * exist, or a system function returns an error. *) const proc: setMTime (in string: filePath, in time: mTime) is func begin SET_MTIME(filePath, mTime.year, mTime.month, mTime.day, mTime.hour, mTime.minute, mTime.second, mTime.micro_second, mTime.timeZone); end func; (** * Determine the name of the owner (UID) of a file. * The function follows symbolic links. * @return the name of the file owner. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' * to the system path type. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception FILE_ERROR The file described with ''filePath'' does not * exist, or a system function returns an error. *) const func string: getOwner (in string: filePath) is action "CMD_GET_OWNER"; (** * Set the owner of a file. * The function follows symbolic links. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' * to the system path type. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception FILE_ERROR The file described with ''filePath'' does not * exist, or a system function returns an error. *) const proc: setOwner (in string: filePath, in string: owner) is action "CMD_SET_OWNER"; (** * Determine the name of the group (GID) to which a file belongs. * The function follows symbolic links. * @return the name of the file group. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' * to the system path type. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception FILE_ERROR The file described with ''filePath'' does not * exist, or a system function returns an error. *) const func string: getGroup (in string: filePath) is action "CMD_GET_GROUP"; (** * Set the group of a file. * The function follows symbolic links. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' * to the system path type. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception FILE_ERROR The file described with ''filePath'' does not * exist, or a system function returns an error. *) const proc: setGroup (in string: filePath, in string: group) is action "CMD_SET_GROUP"; (** * Determine the file mode (permissions) of a symbolic link. * The function only works for symbolic links and does not follow the * symbolic link. * @return the file mode. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' * to the system path type. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception FILE_ERROR The file described with ''filePath'' does not * exist, or it is not a symbolic link, or a system function * returns an error. *) const func fileMode: getFileMode (in string: filePath, SYMLINK) is action "CMD_GET_FILE_MODE_OF_SYMLINK"; (** * Determine the access time of a symbolic link. * The function only works for symbolic links and does not follow the * symbolic link. * @return the access time of the symbolic link. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' * to the system path type. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception FILE_ERROR The file described with ''filePath'' does not * exist, or it is not a symbolic link, or a system function * returns an error. *) const func time: getATime (in string: filePath, SYMLINK) is func result var time: accessTime is time.value; begin GET_ATIME_OF_SYMLINK(filePath, accessTime.year, accessTime.month, accessTime.day, accessTime.hour, accessTime.minute, accessTime.second, accessTime.micro_second, accessTime.timeZone, accessTime.daylightSavingTime); end func; (** * Determine the modification time of a symbolic link. * The function only works for symbolic links and does not follow the * symbolic link. * @return the modification time of the symbolic link. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' * to the system path type. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception FILE_ERROR The file described with ''filePath'' does not * exist, or it is not a symbolic link, or a system function * returns an error. *) const func time: getMTime (in string: filePath, SYMLINK) is func result var time: modificationTime is time.value; begin GET_MTIME_OF_SYMLINK(filePath, modificationTime.year, modificationTime.month, modificationTime.day, modificationTime.hour, modificationTime.minute, modificationTime.second, modificationTime.micro_second, modificationTime.timeZone, modificationTime.daylightSavingTime); end func; (** * Set the modification time of a symbolic link. * The function only works for symbolic links and does not follow the * symbolic link. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' * to the system path type. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception RANGE_ERROR ''mTime'' is invalid or it cannot be * converted to the system file time. * @exception FILE_ERROR The file described with ''filePath'' does not * exist, or it is not a symbolic link, or a system function * returns an error. *) const proc: setMTime (in string: filePath, in time: mTime, SYMLINK) is func begin SET_MTIME_OF_SYMLINK(filePath, mTime.year, mTime.month, mTime.day, mTime.hour, mTime.minute, mTime.second, mTime.micro_second, mTime.timeZone); end func; (** * Determine the name of the owner (UID) of a symbolic link. * The function only works for symbolic links and does not follow the * symbolic link. * @return the name of the file owner. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception FILE_ERROR The file described with ''filePath'' does not * exist, or it is not a symbolic link, or a system function * returns an error. *) const func string: getOwner (in string: filePath, SYMLINK) is action "CMD_GET_OWNER_OF_SYMLINK"; (** * Set the owner of a symbolic link. * The function only works for symbolic links and does not follow the * symbolic link. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' * to the system path type. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception FILE_ERROR The file described with ''filePath'' does not * exist, or it is not a symbolic link, or a system function * returns an error. *) const proc: setOwner (in string: filePath, in string: owner, SYMLINK) is action "CMD_SET_OWNER_OF_SYMLINK"; (** * Determine the name of the group (GID) to which a symbolic link belongs. * The function only works for symbolic links and does not follow the * symbolic link. * @return the name of the file group. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception FILE_ERROR The file described with ''filePath'' does not * exist, or it is not a symbolic link, or a system function * returns an error. *) const func string: getGroup (in string: filePath, SYMLINK) is action "CMD_GET_GROUP_OF_SYMLINK"; (** * Set the group of a symbolic link. * The function only works for symbolic links and does not follow the * symbolic link. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' * to the system path type. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception FILE_ERROR The file described with ''filePath'' does not * exist, or it is not a symbolic link, or a system function * returns an error. *) const proc: setGroup (in string: filePath, in string: group, SYMLINK) is action "CMD_SET_GROUP_OF_SYMLINK"; (** * Reads the destination of a symbolic link. * This function reads the link destination stored in the file system. * Symbolic links can be relative or absolute. Relative symbolic links * are relative to their location in the file system and not relative to * the current working directory. * readLink("/aDir/symbolicLink") returns e.g. "../linkDest" * readLink("/aDir/symbolicLink", ABSOLUTE) returns e.g. "/aDir/linkDest" * @param filePath Relative or absolute path of a symbolic link. * @return The destination referred by the symbolic link. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' * to the system path type or not enough memory to * represent the result [[string]]. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation, or it cannot be converted to the system * path type. * @exception FILE_ERROR The file described with ''filePath'' does not * exist, or it is not a symbolic link, or a system function * returns an error. *) const func string: readLink (in string: filePath) is action "CMD_READ_LINK"; # The function readlink() is deprecated. Use readLink() instead. const func string: readlink (in string: filePath) is return readLink(filePath); (** * Reads the absolute destination path of a symbolic link. * The symbolic links stored in the file system can be relative or * absolute. Relative symbolic links are relative to their location in * the file system and not relative to the current working directory. * For a relative symbolic link ''filePath'' is converted to an * absolute path, and the symbolic link is concatenated to this path. * readLink("/aDir/symbolicLink") returns e.g. "../linkDest" * readLink("/aDir/symbolicLink", ABSOLUTE) returns e.g. "/aDir/linkDest" * @param filePath Relative or absolute path of a symbolic link. * @return The absolute destination path referred by the symbolic link. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' * to the system path type or not enough memory to * represent the result [[string]]. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception FILE_ERROR The file described with ''filePath'' does not * exist, or it is not a symbolic link, or a system function * returns an error. *) const func string: readLink (in string: filePath, ABSOLUTE) is action "CMD_READ_LINK_ABSOLUTE"; (** * Get the final path that functions like getMTime() and open() would use. * If ''filePath'' is not a symbolic link it is returned. For a symbolic link * the function follows the symbolic link chain until the path is not a * symbolic link again. The final path may refer to a non-existing file. * @param filePath Relative or absolute path. * @return The final path after possibly following a symbolic link chain. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' * to the system path type or not enough memory to * represent the result string. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception FILE_ERROR The file described with ''filePath'' does not * exist or a system function returns an error. *) const func string: finalPath (in string: filePath) is action "CMD_FINAL_PATH"; (** * Create a symbolic link. * The symbolic link ''symlinkPath'' will refer to ''targetPath'' afterwards. * The function does not follow symbolic links. * @param symlinkPath Name of the symbolic link to be created. * @param targetPath String to be contained in the symbolic link. * @exception MEMORY_ERROR Not enough memory to convert ''symlinkPath'' or * ''targetPath'' to the system path type. * @exception RANGE_ERROR ''symlinkPath'' or ''targetPath'' does not use the * standard path representation or one of them cannot be * converted to the system path type. * @exception FILE_ERROR The file ''symlinkPath'' already exists, or a * system function returns an error. *) const proc: makeLink (in string: symlinkPath, in string: targetPath) is action "CMD_MAKE_LINK"; # The function symlink() is deprecated. Use makeLink() instead. # Note that makeLink() has the symlinkPath as first parameter. const proc: symlink (in string: targetPath, in string: symlinkPath) is func begin makeLink(symlinkPath, targetPath); end func; (** * Remove a file of any type unless it is a directory that is not empty. * The function does not follow symbolic links. An attempt to remove a * directory that is not empty triggers FILE_ERROR. * @param filePath Name of the file to be removed. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' to * the system path type. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception FILE_ERROR The file does not exist or it is a directory * that is not empty or a system function returns an error. *) const proc: removeFile (in string: filePath) is action "CMD_REMOVE_FILE"; (** * Remove a file of any type inclusive a directory tree. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' to * the system path type. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception FILE_ERROR The file does not exist or a system function * returns an error. *) const proc: removeTree (in string: filePath) is action "CMD_REMOVE_TREE"; (** * Copy a file or directory tree. * Permissions/mode, ownership and timestamps of the destination file * are determined independent of the corresponding source properties. * The destination file gets the permissions/mode defined by umask. * The user executing the program is the owner of the destination file. * The timestamps of the destination file are set to the current time. * Symbolic links in ''sourcePath'' are always followed. * Therefore ''copyFile'' will never create a symbolic link. * Note that ''copyFile'' does not preserve hard links (they are * resolved to distinct files). * @exception MEMORY_ERROR Not enough memory to convert ''sourcePath'' * or ''destPath'' to the system path type. * @exception RANGE_ERROR ''sourcePath'' or ''destPath'' does not use * the standard path representation or one of them cannot be * converted to the system path type. * @exception FILE_ERROR Source file does not exist, destination file * already exists or a system function returns an error. *) const proc: copyFile (in string: sourcePath, in string: destPath) is action "CMD_COPY_FILE"; (** * Clone a file or directory tree. * Permissions/mode, ownership and timestamps of the original are * preserved. Symlinks are not followed. Instead the symlink is * copied. Note that ''cloneFile'' does not preserve hard links (they * are resolved to distinct files). * @exception MEMORY_ERROR Not enough memory to convert * ''sourcePath'' or ''destPath'' to the system path type. * @exception RANGE_ERROR ''sourcePath'' or ''destPath'' does not use * the standard path representation or one of them cannot be * converted to the system path type. * @exception FILE_ERROR Source file does not exist, destination file * already exists or a system function returns an error. *) const proc: cloneFile (in string: sourcePath, in string: destPath) is action "CMD_CLONE_FILE"; (** * Move and rename a file or directory tree. * The function uses the C ''rename()'' function. If ''rename()'' fails * the file (or directory tree) is cloned with ''cloneFile'' (which * preserves permissions/mode, ownership and timestamps) to the new * place and with the new name. If ''cloneFile'' succeeds the original * file is deleted. If ''cloneFile'' fails (no space on device or * other reason) all remains of the failed clone are removed. Note * that ''cloneFile'' works for symbolic links but does not preserve * hard links (they are resolved to distinct files). * @exception MEMORY_ERROR Not enough memory to convert ''sourcePath'' * or ''destPath'' to the system path type. * @exception RANGE_ERROR ''sourcePath'' or ''destPath'' does not use * the standard path representation or one of them cannot be * converted to the system path type. * @exception FILE_ERROR Source file does not exist, destination file * already exists or a system function returns an error. *) const proc: moveFile (in string: sourcePath, in string: destPath) is action "CMD_MOVE"; (** * Create a new directory. * The function does not follow symbolic links. * @param dirPath Name of the directory to be created. * @exception MEMORY_ERROR Not enough memory to convert ''dirPath'' to * the system path type. * @exception RANGE_ERROR ''dirPath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception FILE_ERROR The file ''dirPath'' already exists, or a * system function returns an error. *) const proc: makeDir (in string: dirPath) is action "CMD_MAKE_DIR"; # The function mkdir() is deprecated. Use makeDir() instead. const proc: mkdir (in string: dirPath) is func begin makeDir(dirPath); end func; (** * Determine the current working directory of the calling process. * @return The absolute path of the current working directory. * @exception MEMORY_ERROR Not enough memory to represent the * result [[string]]. * @exception FILE_ERROR The system function returns an error. *) const func string: getcwd is action "CMD_GETCWD"; (** * Changes the current working directory of the calling process. * @exception MEMORY_ERROR Not enough memory to convert ''dirPath'' to * the system path type. * @exception RANGE_ERROR ''dirPath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception FILE_ERROR A system function returns an error. *) const proc: chdir (in string: dirPath) is action "CMD_CHDIR"; (** * Determine the home directory of the user. * This function should be preferred over the use of an environment * variable such as $HOME. $HOME is not supported under all operating * systems and it is not guaranteed, that it uses the standard path * representation. * @return The absolute path of the home directory. * @exception MEMORY_ERROR Not enough memory to represent the * result [[string]]. * @exception FILE_ERROR Not able to determine the home directory. *) const func string: homeDir is action "CMD_HOME_DIR"; (** * Determine the absolute path for a given ''path''. * The examples assume that the current working directory is "/home/myuser". * toAbsPath(getcwd, "aFile") returns e.g. "/home/myuser/aFile" * toAbsPath(".", "aFile") returns e.g. "/home/myuser/aFile" * toAbsPath(".", "../aFile") returns e.g. "/home/aFile" * toAbsPath(".", "..") returns e.g. "/home" * toAbsPath("/usr", "include") returns "/usr/include" * @param basePath Path of the base location. The relative ''path'' is * relative to this location. * @param path Absolute or relative path for which the absolute path should * be determined: * @return ''path'' if ''path'' is already absolute, or * concatenate ''basePath'' with ''path''. *) const func string: toAbsPath (in string: basePath, in string: path) is func result var string: absolutePath is ""; local var integer: dotdotPos is 0; var integer: slashPos is 0; begin if startsWith(path, "/") then absolutePath := path; elsif basePath = "/" then absolutePath := "/" & path; elsif startsWith(basePath, "/") then absolutePath := basePath & "/" & path; else absolutePath := getcwd & "/" & basePath & "/" & path; end if; absolutePath := removeDotFiles(absolutePath); end func; const func string: parentDir (in string: path) is func result var string: parentDir is ""; local var integer: slashPos is 0; begin slashPos := rpos(path, '/'); if slashPos = 0 then parentDir := "."; elsif slashPos = 1 then parentDir := "/"; else parentDir := path[.. pred(slashPos)]; end if; end func; (** * Create the parent directories of the given ''filePath''. * @exception MEMORY_ERROR Not enough memory to convert ''filePath'' to * the system path type. * @exception RANGE_ERROR ''filePath'' does not use the standard path * representation or it cannot be converted to the system * path type. * @exception FILE_ERROR A system function returns an error, or * a component of ''filePath'' is not a directory. *) const proc: makeParentDirs (in string: filePath) is func local var integer: slashPos is 0; var string: dirPath is ""; begin slashPos := pos(filePath, '/', 2); while slashPos <> 0 do dirPath := filePath[.. pred(slashPos)]; if fileTypeSL(dirPath) = FILE_ABSENT then makeDir(dirPath); slashPos := pos(filePath, '/', succ(slashPos)); elsif fileTypeSL(dirPath) = FILE_DIR then slashPos := pos(filePath, '/', succ(slashPos)); else raise FILE_ERROR; end if; end while; end func; (** * Convert a DOS/Windows path to the standard path representation. * A path in the standard path representation is left unchanged. * convDosPath("C:/abc") returns "/c/abc" * convDosPath("C:/abc/") returns "/c/abc" * convDosPath("C:/abc//def") returns "/c/abc/def" * convDosPath("C:\\abc") returns "/c/abc" * convDosPath("C:\\abc\\") returns "/c/abc" * convDosPath("C:\\abc\\\\def") returns "/c/abc/def" * convDosPath("d:/abc") returns "/d/abc" * convDosPath("d://abc") returns "/d/abc" * convDosPath("d:\\abc") returns "/d/abc" * convDosPath("d:\\\\abc") returns "/d/abc" * convDosPath("d:abc") returns "/d/abc" * convDosPath("dir/file") returns "dir/file" * convDosPath("dir\\file") returns "dir/file" * convDosPath("/usr/include") returns "/usr/include" * @param path Absolute or relative DOS/Windows path. * @return The path in the standard path representation. *) const func string: convDosPath (in string: path) is func result var string: stdPath is ""; begin # Path delimiter is slash stdPath := replace(path, "\\", "/"); # Convert drive letters to standard path if length(stdPath) >= 2 and stdPath[2] = ':' and lower(stdPath[1]) >= 'a' and lower(stdPath[1]) <= 'z' then stdPath @:= [2] lower(stdPath[1]); stdPath @:= [1] '/'; if length(stdPath) >= 3 and stdPath[3] <> '/' then stdPath := stdPath[.. 2] & "/" & stdPath[3 ..]; end if; end if; # Remove double slashes stdPath := replaceN(stdPath, "//", "/"); # Remove slash at end of path if stdPath <> "/" and endsWith(stdPath, "/") then stdPath := stdPath[.. pred(length(stdPath))]; end if; end func; const func string: toStdPath (in string: path) is func result var string: stdPath is ""; begin stdPath := path; # Remove double slashes stdPath := replaceN(stdPath, "//", "/"); # Remove slash at end of path while stdPath <> "/" and endsWith(stdPath, "/") do stdPath := stdPath[.. pred(length(stdPath))]; end while; end func; (** * [[filesys#fileSys|FileSys]] implementation type to access operating system files. *) const type: osFileSys is sub emptyFileSys struct end struct; type_implements_interface(osFileSys, fileSys); const func fileSys: openOsFileSys is func result var fileSys: newFileSys is fileSys.value; local var osFileSys: osFiles is osFileSys.value; begin newFileSys := toInterface(osFiles); end func; (** * [[filesys#fileSys|File system]] of the operating system files. *) var fileSys: osFiles is openOsFileSys; const proc: close (inout osFileSys: fileSystem) is noop; const func array string: readDir (inout osFileSys: fileSystem, in string: dirPath) is return readDir(dirPath); const func fileType: fileType (inout osFileSys: fileSystem, in string: filePath) is return fileType(filePath); const func fileType: fileTypeSL (inout osFileSys: fileSystem, in string: filePath) is return fileTypeSL(filePath); const func integer: fileSize (inout osFileSys: fileSystem, in string: filePath) is return fileSize(filePath); const func bigInteger: bigFileSize (inout osFileSys: fileSystem, in string: filePath) is return bigFileSize(filePath); const func fileMode: getFileMode (inout osFileSys: fileSystem, in string: filePath) is return getFileMode(filePath); const proc: setFileMode (inout osFileSys: fileSystem, in string: filePath, in fileMode: mode) is func begin setFileMode(filePath, mode); end func; const func time: getMTime (inout osFileSys: fileSystem, in string: filePath) is return getMTime(filePath); const proc: setMTime (inout osFileSys: fileSystem, in string: filePath, in time: modificationTime) is func begin setMTime(filePath, modificationTime); end func; const func string: getOwner (inout osFileSys: fileSystem, in string: filePath) is return getOwner(filePath); const proc: setOwner (inout osFileSys: fileSystem, in string: filePath, in string: owner) is func begin setOwner(filePath, owner); end func; const func string: getGroup (inout osFileSys: fileSystem, in string: filePath) is return getGroup(filePath); const proc: setGroup (inout osFileSys: fileSystem, in string: filePath, in string: group) is func begin setGroup(filePath, group); end func; const func fileMode: getFileMode (inout osFileSys: fileSystem, in string: filePath, SYMLINK) is return getFileMode(filePath, SYMLINK); const func time: getMTime (inout osFileSys: fileSystem, in string: filePath, SYMLINK) is return getMTime(filePath, SYMLINK); const proc: setMTime (inout osFileSys: fileSystem, in string: filePath, in time: modificationTime, SYMLINK) is func begin setMTime(filePath, modificationTime, SYMLINK); end func; const func string: getOwner (inout osFileSys: fileSystem, in string: filePath, SYMLINK) is return getOwner(filePath, SYMLINK); const proc: setOwner (inout osFileSys: fileSystem, in string: filePath, in string: owner, SYMLINK) is func begin setOwner(filePath, owner, SYMLINK); end func; const func string: getGroup (inout osFileSys: fileSystem, in string: filePath, SYMLINK) is return getGroup(filePath, SYMLINK); const proc: setGroup (inout osFileSys: fileSystem, in string: filePath, in string: group, SYMLINK) is func begin setGroup(filePath, group, SYMLINK); end func; const func file: open (inout osFileSys: fileSystem, in string: filePath, in string: mode) is return open(filePath, mode); const func string: getFile (inout osFileSys: fileSystem, in string: filePath) is func result var string: data is ""; local var file: workFile is STD_NULL; begin workFile := open(filePath, "r"); if workFile <> STD_NULL then data := gets(workFile, length(workFile)); close(workFile); else raise FILE_ERROR; end if; end func; const proc: putFile (inout osFileSys: fileSystem, in string: filePath, in string: stri) is func local var file: workFile is STD_NULL; begin if stri <> "" then workFile := open(filePath, "w"); if workFile <> STD_NULL then write(workFile, stri); close(workFile); end if; end if; end func; const func string: readLink (inout osFileSys: fileSystem, in string: filePath) is return readLink(filePath); const proc: makeLink (inout osFileSys: fileSystem, in string: symlinkPath, in string: targetPath) is func begin makeLink(symlinkPath, targetPath); end func; const proc: makeDir (inout osFileSys: fileSystem, in string: dirPath) is func begin makeDir(dirPath); end func; const func string: getcwd (inout osFileSys: fileSystem) is return getcwd; const proc: chdir (inout osFileSys: fileSystem, in string: dirPath) is func begin chdir(dirPath); end func;