├── .gitignore ├── CMakeLists.txt ├── COPYRIGHT.txt ├── README.md ├── doc ├── dirfunctions.md ├── dirpaths.md ├── filenames.md ├── index.md └── misc.md ├── init.lua ├── mkdocs.yml ├── paths.c ├── paths.h.in └── rocks └── paths-scm-1.rockspec /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | 3 | INCLUDE_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}") 4 | INCLUDE_DIRECTORIES("${LUA_INCDIR}") 5 | LINK_DIRECTORIES("${LUA_LIBDIR}") 6 | 7 | INCLUDE(CheckIncludeFiles) 8 | INCLUDE(CheckFunctionExists) 9 | INCLUDE(CheckLibraryExists) 10 | 11 | IF (UNIX OR NOT WIN32) 12 | CHECK_INCLUDE_FILES(fcntl.h HAVE_FCNTL_H) 13 | CHECK_INCLUDE_FILES(unistd.h HAVE_UNISTD_H) 14 | CHECK_INCLUDE_FILES(dirent.h HAVE_DIRENT_H) 15 | CHECK_INCLUDE_FILES(time.h HAVE_TIME_H) 16 | CHECK_INCLUDE_FILES(sys/time.h HAVE_SYS_TIME_H) 17 | CHECK_INCLUDE_FILES(sys/ndir.h HAVE_SYS_NDIR_H) 18 | CHECK_INCLUDE_FILES(sys/utsname.h HAVE_SYS_UTSNAME_H) 19 | CHECK_INCLUDE_FILES(sys/dir.h HAVE_SYS_DIR_H) 20 | CHECK_INCLUDE_FILES(ndir.h HAVE_NDIR_H) 21 | CHECK_FUNCTION_EXISTS(getcwd HAVE_GETCWD) 22 | CHECK_LIBRARY_EXISTS(dl dlopen "" HAVE_DLOPEN) 23 | ENDIF (UNIX OR NOT WIN32) 24 | 25 | CONFIGURE_FILE("paths.h.in" "${CMAKE_CURRENT_BINARY_DIR}/paths.h") 26 | 27 | SET(src 28 | "${CMAKE_CURRENT_SOURCE_DIR}/paths.c" 29 | "${CMAKE_CURRENT_BINARY_DIR}/paths.h" ) 30 | 31 | SET(luasrc 32 | "${CMAKE_CURRENT_SOURCE_DIR}/init.lua") 33 | 34 | # When using MSVC 35 | IF(MSVC) 36 | # we want to respect the standard, and we are bored of those **** . 37 | ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE=1) 38 | ENDIF(MSVC) 39 | 40 | ADD_LIBRARY("paths" MODULE ${src}) 41 | SET_TARGET_PROPERTIES("paths" PROPERTIES 42 | PREFIX "lib" 43 | IMPORT_PREFIX "lib") 44 | 45 | IF(APPLE) 46 | SET_TARGET_PROPERTIES("paths" PROPERTIES 47 | LINK_FLAGS "-undefined dynamic_lookup") 48 | ENDIF() 49 | 50 | INSTALL(FILES ${luasrc} DESTINATION ${LUADIR}/paths) 51 | INSTALL(TARGETS paths 52 | LIBRARY DESTINATION ${LIBDIR} 53 | RUNTIME DESTINATION ${LIBDIR}) 54 | 55 | IF(LUALIB) 56 | TARGET_LINK_LIBRARIES(paths ${LUALIB}) 57 | ENDIF() 58 | -------------------------------------------------------------------------------- /COPYRIGHT.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2014 Idiap Research Institute (Ronan Collobert) 2 | Copyright (c) 2012-2014 Deepmind Technologies (Koray Kavukcuoglu) 3 | Copyright (c) 2011-2012 NEC Laboratories America (Koray Kavukcuoglu) 4 | Copyright (c) 2011-2013 NYU (Clement Farabet) 5 | Copyright (c) 2006-2010 NEC Laboratories America (Ronan Collobert, Leon Bottou, Iain Melvin, Jason Weston) 6 | Copyright (c) 2006 Idiap Research Institute (Samy Bengio) 7 | Copyright (c) 2001-2004 Idiap Research Institute (Ronan Collobert, Samy Bengio, Johnny Mariethoz) 8 | 9 | All rights reserved. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | 14 | 1. Redistributions of source code must retain the above copyright 15 | notice, this list of conditions and the following disclaimer. 16 | 17 | 2. Redistributions in binary form must reproduce the above copyright 18 | notice, this list of conditions and the following disclaimer in the 19 | documentation and/or other materials provided with the distribution. 20 | 21 | 3. Neither the names of Deepmind Technologies, NYU, NEC Laboratories America 22 | and IDIAP Research Institute nor the names of its contributors may be 23 | used to endorse or promote products derived from this software without 24 | specific prior written permission. 25 | 26 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 27 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 30 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 | POSSIBILITY OF SUCH DAMAGE. 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Filename Manipulation Package # 3 | 4 | This package provides portable functions and variables to manipulate the file system : 5 | 6 | * [Manipulating filenames](doc/filenames.md) : functions for manipulating filenames ; 7 | * [Directory functions](doc/dirfunctions.md) : functions for listing and manipulating directories ; 8 | * [Directory paths](doc/dirpaths.md) : paths to well known directories ; 9 | * [Miscellaneous](doc/misc.md) : uncategorized functions ; 10 | 11 | When this package is loaded, it also computes a number of useful 12 | variables indicating where the various Torch components are installed. 13 | Do not change their values. 14 | -------------------------------------------------------------------------------- /doc/dirfunctions.md: -------------------------------------------------------------------------------- 1 | 2 | ## Directory Functions ## 3 | 4 | The following functions can be used 5 | to examine directory contents or manipulate directories. 6 | 7 | 8 | ### paths.dir(dname) ### 9 | 10 | Return a table containing the files and directories in directory `dname`. 11 | This function return `nil` if the specified directory does not exists. 12 | For linux, this includes the `.` and `..` directories. 13 | 14 | 15 | ### paths.files(dname [, include]) ### 16 | 17 | Returns an iterator over the files and directories located in directory `dname`. 18 | For linux, this includes the `.` and `..` directories. 19 | This can be used in *__for__* expression as shown below: 20 | 21 | ```lua 22 | for f in paths.files(".") do 23 | print(f) 24 | end 25 | ``` 26 | 27 | Optional argument `include` is either a function or a string used to 28 | determine which files are to be included. The function takes the filename 29 | as argument and should return true if the file is to be included. 30 | When a string is provided, the following function is used : 31 | 32 | ```lua 33 | function(file) 34 | return file:find(f) 35 | end 36 | ``` 37 | 38 | Files and directories of sub-folders aren't included. 39 | 40 | 41 | ### paths.iterdirs(dname) ### 42 | 43 | Returns an iterator over the directories located in directory `dname`. 44 | This can be used in *__for__* expression as shown below: 45 | 46 | ```lua 47 | for dir in paths.iterdirs(".") do 48 | print(dir) 49 | end 50 | ``` 51 | 52 | Directories of sub-folders, and the `.` and `..` folders aren't included. 53 | 54 | 55 | ### paths.iterfiles(dname) ### 56 | 57 | Returns an iterator over the files (non-directories) located in directory `dname`. 58 | This can be used in *__for__* expression as shown below: 59 | 60 | ```lua 61 | for file in paths.iterfiles(".") do 62 | print(file) 63 | end 64 | ``` 65 | 66 | Files of sub-folders, and the `.` and `..` folders aren't included. 67 | 68 | 69 | ### paths.mkdir(s) ### 70 | 71 | Create a directory. 72 | Returns `true` on success. 73 | 74 | 75 | ### paths.rmdir(s) ### 76 | 77 | Delete an empty directory. 78 | Returns `true` on success. 79 | 80 | 81 | ### paths.rmall(s, y) ### 82 | 83 | Recursively delete file or directory `s` and its contents. 84 | Argument `y` must be string `"yes"` 85 | Returns `true` on success. 86 | 87 | -------------------------------------------------------------------------------- /doc/dirpaths.md: -------------------------------------------------------------------------------- 1 | 2 | ## Directory Paths ## 3 | 4 | These variables indicate the paths where the various Torch components are installed, 5 | as well as other common environment variables like `$HOME`. 6 | It is not advisable to change their values! 7 | 8 | 9 | ### paths.install_prefix ### 10 | 11 | The base directory of the Torch installation. 12 | 13 | 14 | ### paths.install_bin ### 15 | 16 | The name of the directory containing the executable programs. 17 | Under Windows, this directory also contains 18 | the dynamically loadable libraries (`.dll`). 19 | 20 | 21 | ### paths.install_man ### 22 | 23 | The name of the directory containing the unix style manual pages. 24 | 25 | 26 | ### paths.install_lib ### 27 | 28 | The name of the directory containing the object code libraries. 29 | Under Unix, this directory also contains the dynamically 30 | loadable libraries (`.so` or `.dylib`). 31 | 32 | 33 | ### paths.install_share ### 34 | 35 | The name of the directory containing processor independent data files, 36 | such as lua code and other text files. 37 | 38 | 39 | ### paths.install_include ### 40 | 41 | The name of the directory containing the include files 42 | for the various Torch libraries. 43 | 44 | 45 | ### paths.install_hlp ### 46 | 47 | The name of the directory containing the Torch help files. 48 | 49 | 50 | ### paths.install_html ### 51 | 52 | The name of the directory containing the HTML version 53 | of the Torch help files. These files are generated 54 | when you enable the CMake option `HTML_DOC`. 55 | 56 | 57 | ### paths.install_cmake ### 58 | 59 | The name of the directory containing the CMake files 60 | used by external Torch modules. 61 | 62 | 63 | ### paths.install_lua_path ### 64 | 65 | The name of the directory containing the Lua packages. 66 | This directory is used to build variable `package.path`. 67 | 68 | 69 | ### paths.install_lua_cpath ### 70 | 71 | The name of the directory containing the Lua loadable binary modules. 72 | This directory is used to build variable `package.cpath`. 73 | 74 | 75 | ### paths.home ### 76 | 77 | The home directory of the current user. 78 | 79 | -------------------------------------------------------------------------------- /doc/filenames.md: -------------------------------------------------------------------------------- 1 | 2 | ## Manipulating Filenames ## 3 | 4 | The following functions can be used 5 | to manipulate filenames in a portable way 6 | over multiple platforms. 7 | 8 | 9 | ### paths.filep(path) ### 10 | 11 | Return a boolean indicating whether `path` 12 | refers to an existing file. 13 | 14 | 15 | ### paths.dirp(path) ### 16 | 17 | Return a boolean indicating whether `path` 18 | refers to an existing directory. 19 | 20 | 21 | ### paths.basename(path,[suffix]) ### 22 | 23 | Return the last path component of `path` 24 | and optionally strip the suffix `suffix`. 25 | This is similar to the well know shell command `"basename"`. 26 | 27 | 28 | ### paths.dirname(path) ### 29 | 30 | Return the name of directory containing file `path`. 31 | This is similar to the well known shell command `"dirname"`. 32 | 33 | 34 | ### paths.extname(path) ### 35 | 36 | Return the extension of the `path` or nil if none is found. 37 | 38 | 39 | ### paths.concat([path1,....,pathn]) ### 40 | 41 | Concatenates relative filenames. 42 | 43 | First this function computes the full filename 44 | of `path1` relative to the current directory. 45 | Then it successively computes the full filenames 46 | of arguments `path2` to `pathn` relative to 47 | the filename returned for the previous argument. 48 | Finally the last result is returned. 49 | 50 | Calling this function without argument returns the 51 | full name of the current directory. 52 | 53 | 54 | 55 | ### paths.cwd() ### 56 | 57 | Return the full path of the current working directory. 58 | 59 | 60 | ### paths.execdir() ### 61 | 62 | Return the name of the directory containing the 63 | current Lua executable. 64 | When the module `paths` is first loaded, 65 | this information is used to relocate 66 | the variables indicating 67 | the location of the various Torch components. 68 | 69 | 70 | 71 | ### paths.tmpname() ### 72 | 73 | Return the name of a temporary file. 74 | All the temporaty files whose name was obtained in this way 75 | are removed when Lua exits. 76 | 77 | This function should be preferred over `os.tmpname()` 78 | because it makes sure that the files are removed on exit. 79 | In addition, `os.tmpname()` under windows often returns filenames 80 | for which the user has no permission to write. 81 | 82 | -------------------------------------------------------------------------------- /doc/index.md: -------------------------------------------------------------------------------- 1 | 2 | # Filename Manipulation Package # 3 | 4 | This package provides portable functions and variables to manipulate the file system : 5 | 6 | * [Manipulating filenames](filenames.md) : functions for manipulating filenames ; 7 | * [Directory functions](dirfunctions.md) : functions for listing and manipulating directories ; 8 | * [Directory paths](dirpaths.md) : paths to well known directories ; 9 | * [Miscellaneous](misc.md) : uncategorized functions ; 10 | 11 | When this package is loaded, it also computes a number of useful 12 | variables indicating where the various Torch components are installed. 13 | Do not change their values. 14 | 15 | -------------------------------------------------------------------------------- /doc/misc.md: -------------------------------------------------------------------------------- 1 | 2 | ## Miscellaneous ## 3 | 4 | 5 | ### paths.uname() ### 6 | 7 | Returns up to three strings describing the operating system. 8 | The first string is a system name, e.g., "Windows", "Linux", "Darwin", "FreeBSD", etc. 9 | The second string is the network name of this computer. 10 | The third string indicates the processor type. 11 | 12 | 13 | ### paths.is_win() ### 14 | 15 | Returns true if the operating system is Microsoft Windows. 16 | 17 | 18 | ### paths.is_mac() ### 19 | 20 | Returns true if the operating system is Mac OS X. 21 | 22 | ### paths.getregistryvalue(key,subkey,value) ### 23 | 24 | Query a value in the Windows registry value. 25 | Causes an error on other systems. 26 | 27 | ### paths.findprogram(progname,...) ### 28 | 29 | Finds an executable program named "progname" and returns its full path. 30 | If none is found, continue searching programs named after the following arguments 31 | and return the full path of the first match. 32 | All the directories specified by the PATH variable are searched. 33 | Under windows, this also searches the "App Path" registry entries. 34 | 35 | 36 | 37 | ### paths.thisfile([arg]) ### 38 | 39 | Calling `paths.thisfile()` without argument 40 | inside a lua file returns returns the full 41 | pathname of the file from which it is called. 42 | This function always returns `nil` when called 43 | interactively. 44 | 45 | Calling `paths.thisfile(arg)` with a string argument `arg` 46 | returns the full pathname of the file `arg` relative 47 | to the directory containing the file from which 48 | function `paths.thisfile` is invoked. This is useful, 49 | for instance, to locate files located in the same 50 | directory as a lua script. 51 | 52 | 53 | ### paths.dofile(filename) ### 54 | 55 | This function is similar to the standard Lua function `dofile` 56 | but interprets `filename` relative to the directory containing 57 | the file that contains the call to `paths.dofile`, 58 | or to the current directory when `paths.dofile` is 59 | called interactively. 60 | -------------------------------------------------------------------------------- /init.lua: -------------------------------------------------------------------------------- 1 | require 'libpaths' 2 | 3 | local assert = assert 4 | local debug = debug 5 | local pcall = pcall 6 | local type = type 7 | local ipairs = ipairs 8 | local os = os 9 | 10 | function paths.is_win() 11 | return paths.uname():match('Windows') 12 | end 13 | 14 | function paths.is_mac() 15 | return paths.uname():match('Darwin') 16 | end 17 | 18 | if paths.is_win() then 19 | paths.home = os.getenv('HOMEDRIVE') or 'C:' 20 | paths.home = paths.home .. ( os.getenv('HOMEPATH') or '\\' ) 21 | else 22 | paths.home = os.getenv('HOME') or '.' 23 | end 24 | 25 | function paths.files(s, f) 26 | local d = paths.dir(s) 27 | local n = 0 28 | if type(f) == 'string' then 29 | local pattern = f 30 | f = function(file) return file:find(pattern) end 31 | elseif f and type(f) ~= 'function' then 32 | error("Expecting optional arg 2 to be function or string. Got : "..torch.type(f)) 33 | end 34 | f = f or function(file) return true end 35 | local n = 0 36 | return function() 37 | while true do 38 | n = n + 1 39 | if d == nil or n > #d then 40 | return nil 41 | elseif f(d[n]) then 42 | return d[n] 43 | end 44 | end 45 | end 46 | end 47 | 48 | function paths.iterdirs(s) 49 | return paths.files(s, 50 | function(dir) 51 | return paths.dirp(paths.concat(s, dir)) and dir ~= '.' and dir ~= '..' 52 | end) 53 | end 54 | 55 | function paths.iterfiles(s) 56 | return paths.files(s, 57 | function(file) 58 | return paths.filep(paths.concat(s, file)) and file ~= '.' and file ~= '..' 59 | end) 60 | end 61 | 62 | function paths.thisfile(arg, depth) 63 | local s = debug.getinfo(depth or 2).source 64 | if type(s) ~= "string" then 65 | s = nil 66 | elseif s:match("^@") then -- when called from a file 67 | s = paths.concat(s:sub(2)) 68 | elseif s:match("^qt[.]") then -- when called from a qtide editor 69 | local function z(s) return qt[s].fileName:tostring() end 70 | local b, f = pcall(z, s:sub(4)); 71 | if b and f and f ~= "" then s = f else s = nil end 72 | end 73 | if type(arg) == "string" then 74 | if s then s = paths.concat(paths.dirname(s), arg) else s = arg end 75 | end 76 | return s 77 | end 78 | 79 | function paths.dofile(f, depth) 80 | local s = paths.thisfile(nil, 1 + (depth or 2)) 81 | if s and s ~= "" then 82 | f = paths.concat(paths.dirname(s),f) 83 | end 84 | return dofile(f) 85 | end 86 | 87 | function paths.rmall(d, more) 88 | if more ~= 'yes' then 89 | return nil, "missing second argument ('yes')" 90 | elseif paths.filep(d) then 91 | return os.remove(d) 92 | elseif paths.dirp(d) then 93 | for f in paths.files(d) do 94 | if f ~= '.' and f ~= '..' then 95 | local ff = paths.concat(d, f) 96 | local r0,r1,r2 = paths.rmall(ff, more) 97 | if not r0 then 98 | return r0,r1,ff 99 | end 100 | end 101 | end 102 | return paths.rmdir(d) 103 | else 104 | return nil, "not a file or directory", d 105 | end 106 | end 107 | 108 | function paths.findprogram(...) 109 | for _,exe in ipairs{...} do 110 | if paths.is_win() then 111 | if not exe:match('[.]exe$') then 112 | exe = exe .. '.exe' 113 | end 114 | local path, k, x = os.getenv("PATH") or "." 115 | for dir in path:gmatch('[^;]+') do 116 | x = paths.concat(dir, exe) 117 | if paths.filep(x) then return x end 118 | end 119 | local function clean(s) 120 | if s:match('^"') then return s:match('[^"]+') else return s end 121 | end 122 | k = 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\' .. exe 123 | x = paths.getregistryvalue('HKEY_CURRENT_USER', k, '') 124 | if type(x) == 'string' then return clean(x) end 125 | x = paths.getregistryvalue('HKEY_LOCAL_MACHINE', k, '') 126 | if type(x) == 'string' then return clean(x) end 127 | k = 'Applications\\' .. exe .. '\\shell\\open\\command' 128 | x = paths.getregistryvalue('HKEY_CLASSES_ROOT', k, '') 129 | if type(x) == 'string' then return clean(x) end 130 | else 131 | local path = os.getenv("PATH") or "." 132 | for dir in path:gmatch('[^:]+') do 133 | local x = paths.concat(dir, exe) 134 | if paths.filep(x) then return x end 135 | end 136 | end 137 | end 138 | return nil 139 | end 140 | 141 | return paths 142 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: paths 2 | theme : simplex 3 | repo_url : https://github.com/torch/paths 4 | use_directory_urls : false 5 | markdown_extensions: [extra] 6 | docs_dir : doc 7 | pages: 8 | - [index.md, Paths] 9 | - [filenames.md, Manipulating Filenames] 10 | - [dirfunctions.md, Directory Functions] 11 | - [dirpaths.md, Directory Paths] 12 | - [misc.md, Miscellaneous] 13 | -------------------------------------------------------------------------------- /paths.c: -------------------------------------------------------------------------------- 1 | /* -*- C -*- */ 2 | 3 | 4 | #include "paths.h" 5 | 6 | 7 | /* ------------------------------------------------------ */ 8 | /* Utils to manipulate strings */ 9 | 10 | 11 | #define SBINCREMENT 256 12 | 13 | typedef struct { 14 | char *buffer; 15 | int maxlen; 16 | int len; 17 | } SB; 18 | 19 | static void 20 | sbinit(SB *sb) 21 | { 22 | sb->buffer = (char*)malloc(SBINCREMENT); 23 | sb->maxlen = SBINCREMENT; 24 | sb->len = 0; 25 | } 26 | 27 | static char * 28 | sbfree(SB *sb) 29 | { 30 | if (sb->buffer) 31 | free(sb->buffer); 32 | sb->buffer = 0; 33 | return 0; 34 | } 35 | 36 | static void 37 | sbgrow(SB *sb, int n) 38 | { 39 | if (sb->buffer && sb->len + n > sb->maxlen) 40 | { 41 | int nlen = sb->maxlen; 42 | while (sb->len + n > nlen) 43 | nlen += SBINCREMENT; 44 | sb->buffer = (char*)realloc(sb->buffer, nlen); 45 | sb->maxlen = nlen; 46 | } 47 | } 48 | 49 | static void 50 | sbadd1(SB *sb, char c) 51 | { 52 | sbgrow(sb, 1); 53 | if (sb->buffer) 54 | sb->buffer[sb->len++] = c; 55 | } 56 | 57 | static void 58 | sbaddn(SB *sb, const char *s, int n) 59 | { 60 | sbgrow(sb, n); 61 | if (sb->buffer && s && n) 62 | memcpy(sb->buffer + sb->len, s, n); 63 | else if (sb->buffer && n) 64 | sbfree(sb); 65 | sb->len += n; 66 | } 67 | 68 | static void 69 | sbaddsf(SB *sb, char *s) 70 | { 71 | if (s) 72 | sbaddn(sb, s, strlen(s)); 73 | else 74 | sbfree(sb); 75 | if (s) 76 | free((void*)s); 77 | } 78 | 79 | static void 80 | sbslash(SB *sb) 81 | { 82 | int i; 83 | if (sb->buffer && sb->len) 84 | for(i=0; ilen; i++) 85 | if (sb->buffer[i]=='\\') 86 | sb->buffer[i]='/'; 87 | } 88 | 89 | static int 90 | sbpush(lua_State *L, SB *sb) 91 | { 92 | sbslash(sb); 93 | lua_pushlstring(L, sb->buffer, sb->len); 94 | sbfree(sb); 95 | return 1; 96 | } 97 | 98 | static int 99 | sbsetpush(lua_State *L, SB *sb, const char *s) 100 | { 101 | sbfree(sb); 102 | lua_pushstring(L, s); 103 | return 1; 104 | } 105 | 106 | 107 | /* ------------------------------------------------------ */ 108 | /* filep, dirp, basename, dirname */ 109 | 110 | 111 | static int 112 | filep(lua_State *L, int i) 113 | { 114 | const char *s = luaL_checkstring(L, i); 115 | #ifdef _WIN32 116 | struct _stat buf; 117 | if (_stat(s,&buf) < 0) 118 | return 0; 119 | if (buf.st_mode & S_IFDIR) 120 | return 0; 121 | #else 122 | struct stat buf; 123 | if (stat(s,&buf) < 0) 124 | return 0; 125 | if (buf.st_mode & S_IFDIR) 126 | return 0; 127 | #endif 128 | return 1; 129 | } 130 | 131 | 132 | static int 133 | dirp(lua_State *L, int i) 134 | { 135 | const char *s = luaL_checkstring(L, i); 136 | #ifdef _WIN32 137 | char buffer[8]; 138 | struct _stat buf; 139 | const char *last; 140 | if ((s[0]=='/' || s[0]=='\\') && 141 | (s[1]=='/' || s[1]=='\\') && !s[2]) 142 | return 1; 143 | if (s[0] && isalpha((unsigned char)(s[0])) && s[1] == ':' && s[2] == 0) 144 | { buffer[0]=s[0]; buffer[1]=':'; buffer[2]='.'; buffer[3]=0; s = buffer; } 145 | if (_stat(s, &buf) >= 0) 146 | if (buf.st_mode & S_IFDIR) 147 | return 1; 148 | #else 149 | struct stat buf; 150 | if (stat(s,&buf)==0) 151 | if (buf.st_mode & S_IFDIR) 152 | return 1; 153 | #endif 154 | return 0; 155 | } 156 | 157 | 158 | static int 159 | lua_filep(lua_State *L) 160 | { 161 | lua_pushboolean(L, filep(L, 1)); 162 | return 1; 163 | } 164 | 165 | 166 | static int 167 | lua_dirp(lua_State *L) 168 | { 169 | lua_pushboolean(L, dirp(L, 1)); 170 | return 1; 171 | } 172 | 173 | 174 | static int 175 | lua_basename(lua_State *L) 176 | { 177 | const char *fname = luaL_checkstring(L, 1); 178 | const char *suffix = luaL_optstring(L, 2, 0); 179 | 180 | #ifdef _WIN32 181 | 182 | int sl; 183 | const char *p, *s; 184 | SB sb; 185 | sbinit(&sb); 186 | /* Special cases */ 187 | if (fname[0] && fname[1]==':') { 188 | sbaddn(&sb, fname, 2); 189 | fname += 2; 190 | if (fname[0]=='/' || fname[0]=='\\') 191 | sbadd1(&sb, '/'); 192 | while (fname[0]=='/' || fname[0]=='\\') 193 | fname += 1; 194 | if (fname[0]==0) 195 | return sbpush(L, &sb); 196 | sb.len = 0; 197 | } 198 | /* Position p after last nontrivial slash */ 199 | s = p = fname; 200 | while (*s) { 201 | if ((s[0]=='\\' || s[0]=='/') && 202 | (s[1] && s[1]!='/' && s[1]!='\\' ) ) 203 | p = s + 1; 204 | s++; 205 | } 206 | /* Copy into buffer */ 207 | while (*p && *p!='/' && *p!='\\') 208 | sbadd1(&sb, *p++); 209 | /* Process suffix */ 210 | if (suffix==0 || suffix[0]==0) 211 | return sbpush(L, &sb); 212 | if (suffix[0]=='.') 213 | suffix += 1; 214 | if (suffix[0]==0) 215 | return sbpush(L, &sb); 216 | sl = strlen(suffix); 217 | if (sb.len > sl) { 218 | s = sb.buffer + sb.len - (sl + 1); 219 | if (s[0]=='.' && _strnicmp(s+1,suffix, sl)==0) 220 | sb.len = s - sb.buffer; 221 | } 222 | return sbpush(L, &sb); 223 | 224 | #else 225 | 226 | int sl; 227 | const char *s, *p; 228 | SB sb; 229 | sbinit(&sb); 230 | /* Position p after last nontrivial slash */ 231 | s = p = fname; 232 | while (*s) { 233 | if (s[0]=='/' && s[1] && s[1]!='/') 234 | p = s + 1; 235 | s++; 236 | } 237 | /* Copy into buffer */ 238 | while (*p && *p!='/') 239 | sbadd1(&sb, *p++); 240 | /* Process suffix */ 241 | if (suffix==0 || suffix[0]==0) 242 | return sbpush(L, &sb); 243 | if (suffix[0]=='.') 244 | suffix += 1; 245 | if (suffix[0]==0) 246 | return sbpush(L, &sb); 247 | sl = strlen(suffix); 248 | if (sb.len > sl) { 249 | s = sb.buffer + sb.len - (sl + 1); 250 | if (s[0]=='.' && strncmp(s+1,suffix, sl)==0) 251 | sb.len = s - sb.buffer; 252 | } 253 | return sbpush(L, &sb); 254 | 255 | #endif 256 | } 257 | 258 | 259 | static int 260 | lua_dirname(lua_State *L) 261 | { 262 | const char *fname = luaL_checkstring(L, 1); 263 | 264 | #ifdef _WIN32 265 | 266 | const char *s; 267 | const char *p; 268 | SB sb; 269 | sbinit(&sb); 270 | /* Handle leading drive specifier */ 271 | if (isalpha((unsigned char)fname[0]) && fname[1]==':') { 272 | sbadd1(&sb, *fname++); 273 | sbadd1(&sb, *fname++); 274 | } 275 | /* Search last non terminal / or \ */ 276 | p = 0; 277 | s = fname; 278 | while (*s) { 279 | if ((s[0]=='\\' || s[0]=='/') && 280 | (s[1] && s[1]!='/' && s[1]!='\\') ) 281 | p = s; 282 | s++; 283 | } 284 | /* Cannot find non terminal / or \ */ 285 | if (p == 0) { 286 | if (sb.len > 0) { 287 | if (fname[0]==0 || fname[0]=='/' || fname[0]=='\\') 288 | sbadd1(&sb, '/'); 289 | return sbpush(L, &sb); 290 | } else { 291 | if (fname[0]=='/' || fname[0]=='\\') 292 | return sbsetpush(L, &sb, "//"); 293 | else 294 | return sbsetpush(L, &sb, "."); 295 | } 296 | } 297 | /* Single leading slash */ 298 | if (p == fname) { 299 | sbadd1(&sb, '/'); 300 | return sbpush(L, &sb); 301 | } 302 | /* Backtrack all slashes */ 303 | while (p>fname && (p[-1]=='/' || p[-1]=='\\')) 304 | p--; 305 | /* Multiple leading slashes */ 306 | if (p == fname) 307 | return sbsetpush(L, &sb, "//"); 308 | /* Regular case */ 309 | s = fname; 310 | do { 311 | sbadd1(&sb, *s++); 312 | } while (s= fname) { 350 | if (*p == '.') { 351 | lua_pushstring(L, p + 1); 352 | return 1; 353 | } 354 | p--; 355 | } 356 | return 0; 357 | } 358 | 359 | 360 | /* ------------------------------------------------------ */ 361 | /* cwd and concat */ 362 | 363 | 364 | static int 365 | lua_cwd(lua_State *L) 366 | { 367 | #ifdef _WIN32 368 | 369 | char drv[2]; 370 | int l; 371 | SB sb; 372 | sbinit(&sb); 373 | drv[0] = '.'; drv[1] = 0; 374 | l = GetFullPathNameA(drv, sb.maxlen, sb.buffer, 0); 375 | if (l > sb.maxlen) { 376 | sbgrow(&sb, l+1); 377 | l = GetFullPathNameA(drv, sb.maxlen, sb.buffer, 0); 378 | } 379 | if (l <= 0) 380 | return sbsetpush(L, &sb, "."); 381 | sb.len += l; 382 | return sbpush(L, &sb); 383 | 384 | #elif HAVE_GETCWD 385 | 386 | const char *s; 387 | SB sb; 388 | sbinit(&sb); 389 | s = getcwd(sb.buffer, sb.maxlen); 390 | while (!s && errno==ERANGE) 391 | { 392 | sbgrow(&sb, sb.maxlen + SBINCREMENT); 393 | s = getcwd(sb.buffer, sb.maxlen); 394 | } 395 | if (! s) 396 | return sbsetpush(L, &sb, "."); 397 | sb.len += strlen(s); 398 | return sbpush(L, &sb); 399 | 400 | #else 401 | 402 | const char *s; 403 | SB sb; 404 | sbinit(&sb); 405 | sbgrow(&sb, PATH_MAX); 406 | s = getwd(sb.buffer); 407 | if (! s) 408 | return sbsetpush(L, &sb, "."); 409 | sb.len += strlen(s); 410 | return sbpush(L, &sb); 411 | 412 | #endif 413 | } 414 | 415 | 416 | 417 | static int 418 | concat_fname(lua_State *L, const char *fname) 419 | { 420 | const char *from = lua_tostring(L, -1); 421 | 422 | #ifdef _WIN32 423 | 424 | const char *s; 425 | SB sb; 426 | sbinit(&sb); 427 | sbaddn(&sb, from, strlen(from)); 428 | if (fname==0) 429 | return sbpush(L, &sb); 430 | /* Handle absolute part of fname */ 431 | if (fname[0]=='/' || fname[0]=='\\') { 432 | if (fname[1]=='/' || fname[1]=='\\') { 433 | sb.len = 0; /* Case //abcd */ 434 | sbaddn(&sb, "//", 2); 435 | } else { 436 | char drive; 437 | if (sb.len >= 2 && sb.buffer[1]==':' /* Case "/abcd" */ 438 | && isalpha((unsigned char)(sb.buffer[0])) ) 439 | drive = sb.buffer[0]; 440 | else 441 | drive = _getdrive() + 'A' - 1; 442 | sb.len = 0; 443 | sbadd1(&sb, drive); 444 | sbaddn(&sb, ":/", 2); 445 | } 446 | } else if (fname[0] && /* Case "x:abcd" */ 447 | isalpha((unsigned char)(fname[0])) && fname[1]==':') { 448 | if (fname[2]!='/' && fname[2]!='\\') { 449 | if (sb.len < 2 || sb.buffer[1]!=':' 450 | || !isalpha((unsigned char)(sb.buffer[0])) 451 | || (toupper((unsigned char)sb.buffer[0]) != 452 | toupper((unsigned char)fname[0]) ) ) 453 | { 454 | int l; 455 | char drv[4]; 456 | sb.len = 0; 457 | drv[0]=fname[0]; drv[1]=':'; drv[2]='.'; drv[3]=0; 458 | l = GetFullPathNameA(drv, sb.maxlen, sb.buffer, 0); 459 | if (l > sb.maxlen) { 460 | sbgrow(&sb, l+1); 461 | l = GetFullPathNameA(drv, sb.maxlen, sb.buffer, 0); 462 | } 463 | if (l <= 0) 464 | sbaddn(&sb, drv, 3); 465 | else 466 | sb.len += l; 467 | } 468 | fname += 2; 469 | } else { 470 | sb.len = 0; /* Case "x:/abcd" */ 471 | sbadd1(&sb, toupper((unsigned char)fname[0])); 472 | sbaddn(&sb, ":/", 2); 473 | fname += 2; 474 | while (*fname == '/' || *fname == '\\') 475 | fname += 1; 476 | } 477 | } 478 | /* Process path components */ 479 | for (;;) 480 | { 481 | while (*fname=='/' || *fname=='\\') 482 | fname ++; 483 | if (*fname == 0) 484 | return sbpush(L, &sb); 485 | if (fname[0]=='.') { 486 | if (fname[1]=='/' || fname[1]=='\\' || fname[1]==0) { 487 | fname += 1; 488 | continue; 489 | } 490 | if (fname[1]=='.') 491 | if (fname[2]=='/' || fname[2]=='\\' || fname[2]==0) { 492 | size_t l; 493 | fname += 2; 494 | lua_pushcfunction(L, lua_dirname); 495 | sbpush(L, &sb); 496 | lua_call(L, 1, 1); 497 | s = lua_tolstring(L, -1, &l); 498 | sbinit(&sb); 499 | sbaddn(&sb, s, l); 500 | lua_pop(L, 1); 501 | continue; 502 | } 503 | } 504 | if (sb.len==0 || 505 | (sb.buffer[sb.len-1]!='/' && sb.buffer[sb.len-1]!='\\') ) 506 | sbadd1(&sb, '/'); 507 | while (*fname && *fname!='/' && *fname!='\\') 508 | sbadd1(&sb, *fname++); 509 | } 510 | 511 | #else 512 | SB sb; 513 | sbinit(&sb); 514 | 515 | if (fname && fname[0]=='/') 516 | sbadd1(&sb, '/'); 517 | else 518 | sbaddn(&sb, from, strlen(from)); 519 | for (;;) { 520 | while (fname && fname[0]=='/') 521 | fname++; 522 | if (!fname || !fname[0]) { 523 | sbadd1(&sb, '/'); 524 | while (sb.len > 1 && sb.buffer[sb.len-1]=='/') 525 | sb.len --; 526 | return sbpush(L, &sb); 527 | } 528 | if (fname[0]=='.') { 529 | if (fname[1]=='/' || fname[1]==0) { 530 | fname +=1; 531 | continue; 532 | } 533 | if (fname[1]=='.') 534 | if (fname[2]=='/' || fname[2]==0) { 535 | fname +=2; 536 | while (sb.len > 0 && sb.buffer[sb.len-1]=='/') 537 | sb.len --; 538 | while (sb.len > 0 && sb.buffer[sb.len-1]!='/') 539 | sb.len --; 540 | continue; 541 | } 542 | } 543 | if (sb.len == 0 || sb.buffer[sb.len-1] != '/') 544 | sbadd1(&sb, '/'); 545 | while (*fname!=0 && *fname!='/') 546 | sbadd1(&sb, *fname++); 547 | } 548 | 549 | 550 | #endif 551 | 552 | } 553 | 554 | 555 | static int 556 | lua_concatfname(lua_State *L) 557 | { 558 | int i; 559 | int narg = lua_gettop(L); 560 | lua_cwd(L); 561 | for (i=1; i<=narg; i++) 562 | { 563 | concat_fname(L, luaL_checkstring(L, i)); 564 | lua_remove(L, -2); 565 | } 566 | return 1; 567 | } 568 | 569 | 570 | 571 | /* ------------------------------------------------------ */ 572 | /* execdir */ 573 | 574 | 575 | static int 576 | lua_execdir(lua_State *L) 577 | { 578 | const char *s = 0; 579 | #if HAVE_LUA_EXECUTABLE_DIR 580 | s = lua_executable_dir(0); 581 | #endif 582 | if (s && s[0]) 583 | lua_pushstring(L, s); 584 | else 585 | lua_pushnil(L); 586 | return 1; 587 | } 588 | 589 | 590 | 591 | /* ------------------------------------------------------ */ 592 | /* file lists */ 593 | 594 | 595 | static int 596 | lua_dir(lua_State *L) 597 | { 598 | int k = 0; 599 | const char *s = luaL_checkstring(L, 1); 600 | 601 | #ifdef _WIN32 602 | 603 | SB sb; 604 | struct _finddata_t info; 605 | intptr_t hfind; 606 | /* special cases */ 607 | lua_createtable(L, 0, 0); 608 | if ((s[0]=='/' || s[0]=='\\') && 609 | (s[1]=='/' || s[1]=='\\') && !s[2]) 610 | { 611 | int drive; 612 | hfind = GetLogicalDrives(); 613 | for (drive='A'; drive<='Z'; drive++) 614 | if (hfind & ((intptr_t)1<<(drive-'A'))) { 615 | lua_pushfstring(L, "%c:/", drive); 616 | lua_rawseti(L, -2, ++k); 617 | } 618 | } 619 | else if (dirp(L, 1)) { 620 | lua_pushliteral(L, ".."); 621 | lua_rawseti(L, -2, ++k); 622 | } else { 623 | lua_pushnil(L); 624 | return 1; 625 | } 626 | /* files */ 627 | sbinit(&sb); 628 | sbaddn(&sb, s, strlen(s)); 629 | if (sb.len>0 && sb.buffer[sb.len-1]!='/' && sb.buffer[sb.len-1]!='\\') 630 | sbadd1(&sb, '/'); 631 | sbaddn(&sb, "*.*", 3); 632 | sbadd1(&sb, 0); 633 | hfind = _findfirst(sb.buffer, &info); 634 | if (hfind != -1) { 635 | do { 636 | if (strcmp(".",info.name) && strcmp("..",info.name)) { 637 | lua_pushstring(L, info.name); 638 | lua_rawseti(L, -2, ++k); 639 | } 640 | } while ( _findnext(hfind, &info) != -1 ); 641 | _findclose(hfind); 642 | } 643 | sbfree(&sb); 644 | 645 | #else 646 | 647 | DIR *dirp; 648 | struct dirent *d; 649 | dirp = opendir(s); 650 | if (dirp) { 651 | lua_createtable(L, 0, 0); 652 | while ((d = readdir(dirp))) { 653 | int n = NAMLEN(d); 654 | lua_pushlstring(L, d->d_name, n); 655 | lua_rawseti(L, -2, ++k); 656 | } 657 | closedir(dirp); 658 | } else 659 | lua_pushnil(L); 660 | 661 | #endif 662 | 663 | return 1; 664 | } 665 | 666 | 667 | /* ------------------------------------------------------ */ 668 | /* tmpname */ 669 | 670 | 671 | static const char *tmpnames_key = "tmpname_sentinel"; 672 | 673 | struct tmpname_s { 674 | struct tmpname_s *next; 675 | char tmp[4]; 676 | }; 677 | 678 | static int 679 | gc_tmpname(lua_State *L) 680 | { 681 | if (lua_isuserdata(L, -1)) 682 | { 683 | struct tmpname_s **pp = (struct tmpname_s **)lua_touserdata(L, -1); 684 | while (pp && *pp) 685 | { 686 | struct tmpname_s *p = *pp; 687 | *pp = p->next; 688 | remove(p->tmp); 689 | free(p); 690 | } 691 | } 692 | return 0; 693 | 694 | } 695 | 696 | static void 697 | add_tmpname(lua_State *L, const char *tmp) 698 | { 699 | struct tmpname_s **pp = 0; 700 | lua_pushlightuserdata(L, (void*)tmpnames_key); 701 | lua_rawget(L, LUA_REGISTRYINDEX); 702 | if (lua_isuserdata(L, -1)) 703 | { 704 | pp = (struct tmpname_s **)lua_touserdata(L, -1); 705 | lua_pop(L, 1); 706 | } 707 | else 708 | { 709 | lua_pop(L, 1); 710 | /* create sentinel */ 711 | lua_pushlightuserdata(L, (void*)tmpnames_key); 712 | pp = (struct tmpname_s **)lua_newuserdata(L, sizeof(void*)); 713 | pp[0] = 0; 714 | lua_createtable(L, 0, 1); 715 | lua_pushcfunction(L, gc_tmpname); 716 | lua_setfield(L,-2,"__gc"); 717 | lua_setmetatable(L, -2); 718 | lua_rawset(L, LUA_REGISTRYINDEX); 719 | } 720 | while (pp && *pp) 721 | { 722 | struct tmpname_s *p = *pp; 723 | if (!strcmp(p->tmp, tmp)) return; 724 | pp = &(p->next); 725 | } 726 | if (pp) 727 | { 728 | int len = strlen(tmp); 729 | struct tmpname_s *t = (struct tmpname_s*)malloc(len + sizeof(struct tmpname_s)); 730 | if (t) 731 | { 732 | t->next = 0; 733 | memcpy(t->tmp, tmp, len); 734 | t->tmp[len] = 0; 735 | *pp = t; 736 | } 737 | } 738 | } 739 | 740 | 741 | static int 742 | lua_tmpname(lua_State *L) 743 | { 744 | #ifdef _WIN32 745 | char *tmp = _tempnam("c:/temp", "luatmp"); 746 | #else 747 | char *tmp = tempnam(NULL, "luatmp"); 748 | #endif 749 | if (tmp) 750 | { 751 | lua_pushstring(L, tmp); 752 | add_tmpname(L, tmp); 753 | free(tmp); 754 | return 1; 755 | } 756 | else 757 | { 758 | lua_pushnil(L); 759 | return 1; 760 | } 761 | } 762 | 763 | 764 | 765 | /* ------------------------------------------------------ */ 766 | /* mkdir, rmdir */ 767 | 768 | static int 769 | pushresult (lua_State *L, int i, const char *filename) { 770 | int en = errno; 771 | if (i) { 772 | lua_pushboolean(L, 1); 773 | return 1; 774 | } 775 | else { 776 | lua_pushnil(L); 777 | lua_pushfstring(L, "%s: %s", filename, strerror(en)); 778 | lua_pushinteger(L, en); 779 | return 3; 780 | } 781 | } 782 | 783 | static int 784 | lua_mkdir(lua_State *L) 785 | { 786 | int status = 0; 787 | const char *s = luaL_checkstring(L, 1); 788 | lua_pushcfunction(L, lua_mkdir); 789 | lua_pushcfunction(L, lua_dirname); 790 | lua_pushvalue(L, 1); 791 | lua_call(L, 1, 1); 792 | if (! dirp(L, -1)) 793 | lua_call(L, 1, 3); 794 | #ifdef _WIN32 795 | status = _mkdir(s); 796 | #else 797 | status = mkdir(s, 0777); 798 | #endif 799 | return pushresult(L, status == 0, s); 800 | } 801 | 802 | static int 803 | lua_rmdir(lua_State *L) 804 | { 805 | const char *s = luaL_checkstring(L, 1); 806 | #ifdef _WIN32 807 | int status = _rmdir(s); 808 | #else 809 | int status = rmdir(s); 810 | #endif 811 | return pushresult(L, status == 0, s); 812 | } 813 | 814 | 815 | /* ------------------------------------------------------ */ 816 | /* uname */ 817 | 818 | 819 | static int 820 | lua_uname(lua_State *L) 821 | { 822 | #if defined(_WIN32) 823 | const char *name; 824 | SYSTEM_INFO info; 825 | lua_pushliteral(L, "Windows"); 826 | name = getenv("COMPUTERNAME"); 827 | lua_pushstring(L, name ? name : ""); 828 | memset(&info, 0, sizeof(info)); 829 | GetSystemInfo(&info); 830 | if (info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) 831 | lua_pushliteral(L, "AMD64"); 832 | else if (info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) 833 | lua_pushliteral(L, "X86"); 834 | else if (info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM) 835 | lua_pushliteral(L, "ARM"); 836 | else if (info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) 837 | lua_pushliteral(L, "IA64"); 838 | else if (info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) 839 | lua_pushstring(L, ""); 840 | return 3; 841 | #else 842 | # if defined(HAVE_SYS_UTSNAME_H) 843 | struct utsname info; 844 | if (uname(&info) >= 0) 845 | { 846 | lua_pushstring(L, info.sysname); 847 | lua_pushstring(L, info.nodename); 848 | lua_pushstring(L, info.machine); 849 | return 3; 850 | } 851 | # endif 852 | lua_pushstring(L, "Unknown"); 853 | return 1; 854 | #endif 855 | } 856 | 857 | static int 858 | lua_getregistryvalue(lua_State *L) 859 | { 860 | #ifdef _WIN32 861 | static char *keynames[] = { 862 | "HKEY_CLASSES_ROOT", 863 | "HKEY_CURRENT_CONFIG", 864 | "HKEY_CURRENT_USER", 865 | "HKEY_LOCAL_MACHINE", 866 | "HKEY_USERS", 867 | NULL }; 868 | static HKEY keys[] = { 869 | HKEY_CLASSES_ROOT, 870 | HKEY_CURRENT_CONFIG, 871 | HKEY_CURRENT_USER, 872 | HKEY_LOCAL_MACHINE, 873 | HKEY_USERS 874 | }; 875 | 876 | HKEY rkey = keys[ luaL_checkoption(L, 1, NULL, keynames) ]; 877 | const char *subkey = luaL_checkstring(L, 2); 878 | const char *value = luaL_checkstring(L, 3); 879 | HKEY skey; 880 | DWORD type; 881 | DWORD len = 0; 882 | char *data = NULL; 883 | LONG res; 884 | res = RegOpenKeyExA(rkey, subkey, 0, KEY_READ, &skey); 885 | if (res != ERROR_SUCCESS) 886 | { 887 | lua_pushnil(L); 888 | lua_pushinteger(L, res); 889 | if (res == ERROR_FILE_NOT_FOUND) 890 | lua_pushstring(L, "subkey not found"); 891 | if (res == ERROR_ACCESS_DENIED) 892 | lua_pushstring(L, "subkey access denied"); 893 | else 894 | return 2; 895 | return 3; 896 | } 897 | res = RegQueryValueExA(skey, value, NULL, &type, (LPBYTE)data, &len); 898 | if (len > 0) 899 | { 900 | len += 8; 901 | data = (char*)malloc(len); 902 | if (! data) 903 | luaL_error(L, "out of memory"); 904 | res = RegQueryValueExA(skey, value, NULL, &type, (LPBYTE)data, &len); 905 | } 906 | RegCloseKey(skey); 907 | if (res != ERROR_SUCCESS) 908 | { 909 | if (data) 910 | free(data); 911 | lua_pushnil(L); 912 | lua_pushinteger(L, res); 913 | if (res == ERROR_FILE_NOT_FOUND) 914 | lua_pushstring(L, "value not found"); 915 | if (res == ERROR_ACCESS_DENIED) 916 | lua_pushstring(L, "value access denied"); 917 | else 918 | return 2; 919 | return 3; 920 | } 921 | switch(type) 922 | { 923 | case REG_DWORD: 924 | lua_pushinteger(L, (lua_Integer)*(const DWORD*)data); 925 | if (data) 926 | free(data); 927 | return 1; 928 | case REG_EXPAND_SZ: 929 | if (data && len > 0) 930 | { 931 | if ((len = ExpandEnvironmentStrings(data, NULL, 0)) > 0) 932 | { 933 | char *buf = (char*)malloc(len + 8); 934 | if (!buf) 935 | luaL_error(L, "out of memory"); 936 | len = ExpandEnvironmentStrings(data, buf, len+8); 937 | free(data); 938 | data = buf; 939 | } 940 | } 941 | /* fall thru */ 942 | case REG_SZ: 943 | if (data && len > 0) 944 | if (((const char*)data)[len-1] == 0) 945 | len -= 1; 946 | /* fall thru */ 947 | case REG_BINARY: 948 | if (data && len > 0) 949 | lua_pushlstring(L, (const char*)data, (int)len); 950 | else 951 | lua_pushliteral(L, ""); 952 | if (data) 953 | free(data); 954 | return 1; 955 | /* unimplemented */ 956 | case REG_QWORD: 957 | case REG_MULTI_SZ: 958 | default: 959 | lua_pushnil(L); 960 | lua_pushinteger(L, res); 961 | lua_pushfstring(L, "getting registry type %d not implemented", type); 962 | return 3; 963 | } 964 | #else 965 | luaL_error(L, "This function exists only on windows"); 966 | return 0; 967 | #endif 968 | } 969 | 970 | /* ------------------------------------------------------ */ 971 | /* require (with global flag) */ 972 | 973 | #ifdef HAVE_DLOPEN 974 | # define NEED_PATH_REQUIRE 1 975 | # include 976 | # ifndef RTLD_LAZY 977 | # define RTLD_LAZY 1 978 | # endif 979 | # ifndef RTLD_GLOBAL 980 | # define RTLD_GLOBAL 0 981 | # endif 982 | # define LL_LOAD(h,fname) h=dlopen(fname,RTLD_LAZY|RTLD_GLOBAL) 983 | # define LL_SYM(h,sym) dlsym(h, sym) 984 | #endif 985 | 986 | #ifdef _WIN32 987 | # define NEED_PATH_REQUIRE 1 988 | # include 989 | # define LL_LOAD(h,fname) h=(void*)LoadLibraryA(fname) 990 | # define LL_SYM(h,sym) GetProcAddress((HINSTANCE)h,sym) 991 | #endif 992 | 993 | #if NEED_PATH_REQUIRE 994 | 995 | /* {{{ functions copied or derived from loadlib.c */ 996 | 997 | static int readable (const char *filename) 998 | { 999 | FILE *f = fopen(filename, "r"); /* try to open file */ 1000 | if (f == NULL) return 0; /* open failed */ 1001 | fclose(f); 1002 | return 1; 1003 | } 1004 | 1005 | #if LUA_VERSION_NUM >= 502 /* LUA52 compatibility defs */ 1006 | #define LUA_PATHSEP ";" 1007 | #define PATHS_LUA_CLEANUP_DEFS 1 1008 | #endif 1009 | static const char *pushnexttemplate (lua_State *L, const char *path) 1010 | { 1011 | const char *l; 1012 | while (*path == *LUA_PATHSEP) path++; /* skip separators */ 1013 | if (*path == '\0') return NULL; /* no more templates */ 1014 | l = strchr(path, *LUA_PATHSEP); /* find next separator */ 1015 | if (l == NULL) l = path + strlen(path); 1016 | lua_pushlstring(L, path, l - path); /* template */ 1017 | return l; 1018 | } 1019 | #ifdef PATHS_LUA_CLEANUP_DEFS /* cleanup after yourself */ 1020 | #undef LUA_PATHSEP 1021 | #endif 1022 | 1023 | static const char *pushfilename (lua_State *L, const char *name) 1024 | { 1025 | const char *path; 1026 | const char *filename; 1027 | lua_getglobal(L, "package"); 1028 | lua_getfield(L, -1, "cpath"); 1029 | lua_remove(L, -2); 1030 | if (! (path = lua_tostring(L, -1))) 1031 | luaL_error(L, LUA_QL("package.cpath") " must be a string"); 1032 | lua_pushliteral(L, ""); 1033 | while ((path = pushnexttemplate(L, path))) { 1034 | filename = luaL_gsub(L, lua_tostring(L, -1), "?", name); 1035 | lua_remove(L, -2); 1036 | if (readable(filename)) 1037 | { /* stack: cpath errmsg filename */ 1038 | lua_remove(L, -3); 1039 | lua_remove(L, -2); 1040 | return lua_tostring(L, -1); 1041 | } 1042 | lua_pushfstring(L, "\n\tno file " LUA_QS, filename); 1043 | lua_remove(L, -2); /* remove file name */ 1044 | lua_concat(L, 2); /* add entry to possible error message */ 1045 | } 1046 | lua_pushfstring(L, "module " LUA_QS " not found", name); 1047 | lua_replace(L, -3); 1048 | lua_concat(L, 2); 1049 | lua_error(L); 1050 | return 0; 1051 | } 1052 | 1053 | /* functions copied or derived from loadlib.c }}} */ 1054 | 1055 | static int 1056 | path_require(lua_State *L) 1057 | { 1058 | const char *filename; 1059 | lua_CFunction func; 1060 | void *handle; 1061 | const char *name = luaL_checkstring(L, 1); 1062 | lua_settop(L, 1); 1063 | lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); /* index 2 */ 1064 | lua_getfield(L, 2, name); 1065 | if (lua_toboolean(L, -1)) 1066 | return 1; 1067 | filename = pushfilename(L, name); /* index 3 */ 1068 | LL_LOAD(handle, filename); 1069 | if (! handle) 1070 | luaL_error(L, "cannot load " LUA_QS, filename); 1071 | lua_pushfstring(L, "luaopen_%s", name); /* index 4 */ 1072 | func = (lua_CFunction)LL_SYM(handle, lua_tostring(L, -1)); 1073 | if (! func) 1074 | luaL_error(L, "no symbol " LUA_QS " in module " LUA_QS, 1075 | lua_tostring(L, -1), filename); 1076 | lua_pushboolean(L, 1); 1077 | lua_setfield(L, 2, name); 1078 | lua_pushcfunction(L, func); 1079 | lua_pushstring(L, name); 1080 | lua_call(L, 1, 1); 1081 | if (! lua_isnil(L, -1)) 1082 | lua_setfield(L, 2, name); 1083 | lua_getfield(L, 2, name); 1084 | return 1; 1085 | } 1086 | 1087 | #else 1088 | 1089 | /* fallback to calling require */ 1090 | 1091 | static int 1092 | path_require(lua_State *L) 1093 | { 1094 | int narg = lua_gettop(L); 1095 | lua_getglobal(L, "require"); 1096 | lua_insert(L, 1); 1097 | lua_call(L, narg, 1); 1098 | return 1; 1099 | } 1100 | 1101 | #endif 1102 | 1103 | 1104 | 1105 | 1106 | /* ------------------------------------------------------ */ 1107 | /* register */ 1108 | 1109 | 1110 | static const struct luaL_Reg paths__ [] = { 1111 | {"filep", lua_filep}, 1112 | {"dirp", lua_dirp}, 1113 | {"basename", lua_basename}, 1114 | {"dirname", lua_dirname}, 1115 | {"extname", lua_extname}, 1116 | {"cwd", lua_cwd}, 1117 | {"concat", lua_concatfname}, 1118 | {"execdir", lua_execdir}, 1119 | {"dir", lua_dir}, 1120 | {"tmpname", lua_tmpname}, 1121 | {"mkdir", lua_mkdir}, 1122 | {"rmdir", lua_rmdir}, 1123 | {"uname", lua_uname}, 1124 | {"getregistryvalue", lua_getregistryvalue}, 1125 | {"require", path_require}, 1126 | {NULL, NULL} 1127 | }; 1128 | 1129 | 1130 | PATHS_API int 1131 | luaopen_libpaths(lua_State *L) 1132 | { 1133 | lua_newtable(L); 1134 | lua_pushvalue(L, -1); 1135 | lua_setglobal(L, "paths"); 1136 | #if LUA_VERSION_NUM >= 502 1137 | luaL_setfuncs(L, paths__, 0); 1138 | #else 1139 | luaL_register(L, NULL, paths__); 1140 | #endif 1141 | return 1; 1142 | } 1143 | -------------------------------------------------------------------------------- /paths.h.in: -------------------------------------------------------------------------------- 1 | /* -*- C -*- */ 2 | 3 | #include "lua.h" 4 | #include "lauxlib.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #if defined(_WIN32) || defined(LUA_WIN) 12 | # ifdef paths_EXPORTS 13 | # define PATHS_API __declspec(dllexport) 14 | # else 15 | # define PATHS_API __declspec(dllimport) 16 | # endif 17 | #else 18 | # define PATHS_API /**/ 19 | #endif 20 | 21 | 22 | #if defined(_WIN32) || defined(LUA_WIN) 23 | 24 | # include 25 | # include 26 | # include 27 | # include 28 | # include 29 | # include 30 | # include 31 | # include 32 | # include 33 | 34 | #else 35 | 36 | #cmakedefine HAVE_DIRENT_H 1 37 | #cmakedefine HAVE_FCNTL_H 1 38 | #cmakedefine HAVE_UNISTD_H 1 39 | #cmakedefine HAVE_TIME_H 1 40 | #cmakedefine HAVE_SYS_TIME_H 1 41 | #cmakedefine HAVE_SYS_NDIR_H 1 42 | #cmakedefine HAVE_SYS_DIR_H 1 43 | #cmakedefine HAVE_SYS_UTSNAME_H 1 44 | #cmakedefine HAVE_NDIR_H 1 45 | #cmakedefine HAVE_GETCWD 1 46 | #cmakedefine HAVE_DLOPEN 1 47 | 48 | # include 49 | # include 50 | # include 51 | # if HAVE_FCNTL_H 52 | # include 53 | # endif 54 | # if HAVE_UNISTD_H 55 | # include 56 | # endif 57 | # if HAVE_SYS_TIME_H 58 | # include 59 | # endif 60 | # if HAVE_SYS_UTSNAME_H 61 | # include 62 | # endif 63 | # if HAVE_TIME_H 64 | # include 65 | # endif 66 | # ifdef HAVE_UNISTD_H 67 | # include 68 | # endif 69 | # ifdef HAVE_DIRENT_H 70 | # include 71 | # define NAMLEN(dirent) strlen((dirent)->d_name) 72 | # else 73 | # define dirent direct 74 | # define NAMLEN(dirent) (dirent)->d_namlen 75 | # if HAVE_SYS_NDIR_H 76 | # include 77 | # endif 78 | # if HAVE_SYS_DIR_H 79 | # include 80 | # endif 81 | # if HAVE_NDIR_H 82 | # include 83 | # endif 84 | # endif 85 | 86 | #endif 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /rocks/paths-scm-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "paths" 2 | version = "scm-1" 3 | 4 | source = { 5 | url = "git://github.com/torch/paths.git", 6 | } 7 | 8 | description = { 9 | summary = "Paths manipulations", 10 | detailed = [[ 11 | ]], 12 | homepage = "https://github.com/torch/paths", 13 | license = "BSD" 14 | } 15 | 16 | dependencies = { 17 | "lua >= 5.1", 18 | } 19 | 20 | build = { 21 | type = "command", 22 | build_command = [[ 23 | cmake -E make_directory build && cd build && cmake .. -DCMAKE_BUILD_TYPE=Release -DLUALIB=$(LUALIB) -DLUA_INCDIR="$(LUA_INCDIR)" -DLUA_LIBDIR="$(LUA_LIBDIR)" -DLUADIR="$(LUADIR)" -DLIBDIR="$(LIBDIR)" -DCMAKE_INSTALL_PREFIX="$(PREFIX)" && $(MAKE) 24 | ]], 25 | install_command = "cd build && $(MAKE) install" 26 | } 27 | --------------------------------------------------------------------------------