/* ********************************************************************* This source file is a part of the standard library of Scol For the latest info, see http://www.scolring.org Copyright (c) 2013 Stephane Bisaro aka Iri This program 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 of the License, or (at your option) any later version. This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA, or go to http://www.gnu.org/copyleft/lesser.txt ********************************************************************* */ /* * Standard functions for system files * See http://redmine.scolring.org/projects/tutorials/wiki/Scol_usage * for more informations */ /*! \file systemfiles.pkg * \author Scol team * \version 0.3 * \copyright GNU Lesser General Public License 2.0 or later * \brief Scol Standard Library - System files API * * \details This API provides an high level method to easily manage file and path names * * Dependancies : * - lib/std/list.pkg * - lib/std/string.pkg **/ fun std_sfgetfilesinfolder (rep, out)= if rep == nil then out else let _listofsubdir hd rep -> reps in let _listoffiles hd rep -> files in ( if reps != nil then set out = std_lCat std_sfgetfilesinfolder reps nil out else nil; set out = std_lCat files out; std_sfgetfilesinfolder tl rep out );; /*! \brief Return the list of file names in some folders and its subfolders. * \remark REQUIRED : lib/std/list.pkg is required. You must load it before use this function. * \remark NOTE : this function can take a long time if the depth of the tree is important. * \ingroup std_fs * * Prototype: fun [[S r1]] [S r1] * * \param [S r1] : a list of folder (e.g. "lib" :: "locked/lib" :: nil) * * \return [S r1] : a list of file names **/ fun std_sfGetTree (rep)= std_sfgetfilesinfolder rep nil;; // Pour retro-compatibilite fun std_sfGetFilesInFolder (rep)= std_sfgetfilesinfolder rep nil;; fun std_sfgettreecb (lrep, cb, n)= if lrep == nil then n else let _listofsubdir hd lrep -> reps in let _listoffiles hd lrep -> files in ( set n = n + sizelist files; exec cb with [hd lrep files]; if reps == nil then n else set n = n + std_sfgettreecb reps cb 0; std_sfgettreecb tl lrep cb n );; /*! \brief List all files and all subdirectories from a list of directories. For each * directory, a function is called with the list of its files. * * \remark NOTE : this function can take a long time if the depth of the tree is important. * \ingroup std_fs * * Prototype: fun [[S r1] fun [S [S r1]] u0] I * * \param [S r1] : a list of directories (e.g. "lib" :: "locked/lib" :: nil) * \param fun [S [S r1]] u0 : function to call for each directory read. These arguments are : * - the pathname of the current directory * - the list of files in this directory * * \return I : the number of found items **/ fun std_sfGetTreeCb (lrep, cb)= std_sfgettreecb lrep cb 0;; /*! \brief Return the position of the last slash (/) in a path name * * \ingroup std_fs * Prototype: fun [S] I * * \param S : a path name * * \return I : this position or nil if not found **/ fun std_sfGetLastPosSlash (s)= if s == nil then nil else let (strlen s) - 1 -> i in ( while (i >= 0) && ((nth_char s i) != '/) do // ' int set i = i-1; if i < 0 then nil else i );; /*! \brief Return the position of the first slash (/) in a path name * * \ingroup std_fs * Prototype: fun [S] I * * \param S : a path name * * \return I : this position or nil if not found **/ fun std_sfGetFirstPosSlash (s)= strfind "/" s 0;; /*! \brief Return the position of the last point (.) in a path name * * \ingroup std_fs * Prototype: fun [S] I * * \param S : a path name * * \return I : this position or nil if not found **/ fun std_sfGetLastPosPoint(s)= if s == nil then nil else let (strlen s) - 1 -> i in ( while (i >= 0) && ((nth_char s i) != '.) do // ' int set i = i - 1; if i < 0 then nil else i );; /*! \brief Return the father path directory in a path name. * * \ingroup std_fs * Prototype: fun [S I] S * * \param S : a pathname * \param I : a flag : 1 to add a slash at the end, else 0 * * \return S : the father directory **/ fun std_sfGetFatherDirectory (rep, withSep)= if rep == nil then nil else ( set rep = substr rep 0 (strlen rep)-1; let std_sfGetLastPosSlash rep -> pos in if pos == nil then rep else substr rep 0 pos+withSep; );; /*! \brief Return the root directory in a path name. * * \ingroup std_fs * Prototype: fun [S I] S * * \param S : a pathname * \param I : a flag : 1 to add a slash at the end, else 0 * * \return S : the root directory **/ fun std_sfGetRootDirectory (rep, withSep)= if rep == nil then nil else ( set rep = substr rep 0 (strlen rep)-1; let std_sfGetFirstPosSlash rep -> pos in if pos == nil then rep else substr rep 0 pos+withSep; );; /*! \brief Return the path without the extension, if any * * \ingroup std_fs * Prototype: fun [S] S * * \param S : a pathname * * \return S : the path without extension **/ fun std_sfGetPathWithoutExtension (path)= let std_sfGetLastPosPoint path -> i in if i == nil then path else substr path 0 i;; /*! \brief Return the extension of a path name. * * \ingroup std_fs * Prototype: fun [S I] S * * \param S : a pathname * \param I : a flag : 1 to add a . at the begin, else 0 * * \return S : the extension or nil if no extension found **/ fun std_sfGetExtension (path, with)= let std_sfGetLastPosPoint path -> i in if i == nil then nil else let strlen path -> n in let if with == 0 then 1 else 0 -> a in substr path i+a n-i;; /*! \brief Compare if a path has a given extension. * * \ingroup std_fs * Prototype: fun [S S] I * * \param S : a pathname * \param S : an extension, such as "pkg" or "png" * * \return S : 1 if equal, nil if no extension found, 0 if not equal **/ fun std_sfCmpExtension (filename, ext)= set ext = if 0 == strfind "." ext 0 then substr ext 1 strlen ext else ext; let std_sfGetLastPosPoint filename -> i in if i == nil then nil else !strcmp ext substr filename i+1 strlen ext;; /*! \brief Get a file path and file name from a path * * \ingroup std_fs * Prototype: fun [S S] [S S] * * \param S : the path * \param S : should set to nil * * \return [S S] : the path and the filename **/ fun std_sfGetPathFile(longfile, file)= if (longfile==nil) || (strlen longfile)==0 || (nth_char longfile ((strlen longfile)-1)) == '/ then // ' ( if (strfind "." file 0) != nil then [longfile file] else if file != nil then [strcatn longfile::file::"/"::nil nil] else [longfile nil]; ) else std_sfGetPathFile substr longfile 0 (strlen longfile)-1 strcat substr longfile ((strlen longfile)-1) 1 file;; /*! \brief Return the absolute path from a relative path *
* let "./std/systemfiles.pkg" -> relative in * let "lib" -> rootdir in * _fooS std_sfPathFromRelativePath relative rootdir; // lib/std/systemfiles.pkg ** * \remark REQUIRED : lib/std/string.pkg is required to use this function * * \ingroup std_fs * Prototype: fun [S S] [S S] * * \param S : the relative path * \param S : the root directory * * \return S : the absolute path **/ fun std_sfPathFromRelativePath (relativePath, rootdir)= if 0 != strfind "./" relativePath 0 then relativePath else ( set rootdir = if 1 == std_szCheckLastChar rootdir "/" then rootdir else strcat rootdir "/"; strcat rootdir substr relativePath 2 strlen relativePath; );; /*! \brief Return the relative path from an absolute path *
* let "lib/std/systemfiles.pkg" -> absolute in * let "lib" -> rootdir in * _fooS std_sfRelativePathFromPath absolute rootdir; // ./std/systemfiles.pkg ** * \remark REQUIRED : lib/std/string.pkg is required to use this function * * \ingroup std_fs * Prototype: fun [S S] [S S] * * \param S : the absolute path * \param S : the root directory * * \return S : the relative path **/ fun std_sfRelativePathFromPath (absolutePath, rootdir)= if (rootdir == nil) || (!strcmp rootdir "") then absolutePath else ( set rootdir = if 1 == std_szCheckLastChar rootdir "/" then rootdir else strcat rootdir "/"; strcat "./" substr absolutePath strlen rootdir strlen absolutePath );; /*! \brief Convert a list of read file references to a list of file references * * \ingroup std_fs * Prototype: fun [[P r1]] [S r1] * * \param [P r1] : a list of read file references * * \return [S r1] : the list of path file **/ fun std_sfConvertListPtoS (pFiles)= if pFiles == nil then nil else (_PtoScol hd pFiles) :: std_sfConvertListPtoS tl pFiles;; /*! \brief Convert a list of write file references to a list of file references * * \ingroup std_fs * Prototype: fun [[W r1]] [S r1] * * \param [W r1] : a list of write file references * * \return [S r1] : the list of path file **/ fun std_sfConvertListWtoS (wFiles)= if wFiles == nil then nil else (_PtoScol _WtoP hd wFiles) :: std_sfConvertListWtoS tl wFiles;; /*! \brief Convert a list of write file references to a list of read file references * * \ingroup std_fs * Prototype: fun [[W r1]] [P r1] * * \param [W r1] : a list of write file references * * \return [P r1] : the list of read file references **/ fun std_sfConvertListWtoP (wFiles)= if wFiles == nil then nil else (_WtoP hd wFiles) :: std_sfConvertListWtoP tl wFiles;; /*! \brief Convert a list of read file references to a list of write file references * * \ingroup std_fs * Prototype: fun [[P r1]] [W r1] * * \param [P r1] : a list of read file references * * \return [W r1] : the list of write file references **/ fun std_sfConvertListPtoW (pFiles)= if pFiles == nil then nil else (_getmodifypack _PtoScol hd pFiles) :: std_sfConvertListPtoW tl pFiles;; /*! \brief To cipher/uncipher a file to another file by the XOR algorithm. * * The same function ciphers and unciphers the initial file if the same * key is given. * * This algorithm is simple but not secure for critical data. * * \ingroup std_fs * Prototype: fun [P W S] I * * \param P : a read file references. This is the file to cipher/uncipher. * This file isn't loaded in Scol memory. * \param W : a write file references. This is the ciphering output. * \param S : the key to cipher/uncipher. Its length mist be >= at 1. * * \return I : 0 or nil if an argument is bas. * * \remark The output file is NOT overwritten. If it already exists, the * output will be appended. * \remark Input and output files should be DIFFERENT. * \see std_szXor (in lib/std/string.pkg) for a string **/ fun std_sfXor (pFile, wFile, szKey)= let strlen szKey -> n2 in if (pFile == nil) || (wFile == nil) || (n2 < 1) then nil else let _FILEOpen _channel pFile -> pF in if pF == nil then nil else let [0 0] -> [i k] in let _FILESize pF -> n in ( _FILESeek pF 0 0; while (i < n) && (k != nil) do let (nth_char _FILERead pF 1 0)^(nth_char szKey (mod i n2)) -> c in if (c == nil) || (0 != _appendpack if c == 0 then "\0" else ctoa c wFile) then set k = nil else ( set i = i+1; _FILESeek pF i 0; ); _FILEClose pF; k );;