diff --git a/Makefile b/Makefile index 72d9b21..5d62eaf 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,7 @@ OBJS = csto.o \ lextra.o \ lfs.o \ ljson.o \ + lpath.o \ lprocess.o \ lsocket.o \ util.o @@ -28,12 +29,13 @@ libcallisto.so: ${LIBS} ${OBJS} csto.o: csto.c callisto.h callisto.o: callisto.c callisto.h -lcl.o: lcl.c callisto.h -lextra.o: lextra.c callisto.h +lcl.o: lcl.c callisto.h util.h +lextra.o: lextra.c callisto.h util.h lenviron.o: lenviron.c callisto.h -lfs.o: lfs.c callisto.h +lfs.o: lfs.c callisto.h errors.h util.h ljson.o: ljson.c callisto.h -lprocess.o: lprocess.c callisto.h +lpath.o: lpath.c callisto.h errors.h util.h +lprocess.o: lprocess.c callisto.h util.h lsocket.o: lsocket.c callisto.h util.o: util.c diff --git a/callisto.c b/callisto.c index 7ac39a2..7696b6e 100644 --- a/callisto.c +++ b/callisto.c @@ -17,6 +17,7 @@ static const luaL_Reg loadedlibs[] = { {CALLISTO_JSONLIBNAME, luaopen_json}, {CALLISTO_MATHLIBNAME, luaopen_math}, {CALLISTO_OSLIBNAME, luaopen_os}, + {CALLISTO_PATHLIBNAME, luaopen_path}, {CALLISTO_PROCLIBNAME, luaopen_process}, {CALLISTO_SOCKLIBNAME, luaopen_socket}, {NULL, NULL} diff --git a/callisto.h b/callisto.h index dffc12f..d4cd4b5 100644 --- a/callisto.h +++ b/callisto.h @@ -24,6 +24,7 @@ #define CALLISTO_JSONLIBNAME "json" #define CALLISTO_MATHLIBNAME "math" #define CALLISTO_OSLIBNAME "os" +#define CALLISTO_PATHLIBNAME "path" #define CALLISTO_PROCLIBNAME "process" #define CALLISTO_SOCKLIBNAME "socket" @@ -34,6 +35,9 @@ int luaopen_environ(lua_State *); int luaopen_extra(lua_State *); int luaopen_fs(lua_State *); int luaopen_json(lua_State *); +/* luaopen_math and luaopen_os + * are provided by Lua */ +int luaopen_path(lua_State *); int luaopen_process(lua_State *); int luaopen_socket(lua_State *); diff --git a/errors.h b/errors.h new file mode 100644 index 0000000..a942eed --- /dev/null +++ b/errors.h @@ -0,0 +1,32 @@ +/* Error messages */ + +#ifndef _ERRORS_H_ + +#define _ERRORS_H_ + +#define E_PATHNAMETOOLONG "pathname too long" +#define E_WORKDIRNOTVALID "working directory is no longer valid" +#define E_COMPNOTEXIST "component of path does not exist" +#define E_DIRNOTEMPTY "directory not empty" +#define E_MOUNTPOINT "directory is busy" +#define E_NOSUCHDEST "no such file or directory" +#define E_FTRAVERSE "failed to traverse directory" +#define E_NOSUCHDIR "no such directory" +#define E_STICKYDIR "permission denied (sticky directory)" +#define E_INTFAULT "internal error (EFAULT)" +#define E_MVPARENT "cannot move a parent directory of pathname" +#define E_FEXISTS "file exists" +#define E_MAXLINK "maximum link count reached" +#define E_NOSPACE "insufficient space left on file system" +#define E_NOTADIR "pathname or a component of pathname is not a directory" +#define E_SYMLINK "could not translate pathname; too many symbolic links" +#define E_DIFFFS "pathnames are on different file systems" +#define E_DIRDOT "last component of path is '.'" +#define E_ISADIR "cannot move a file to the name of a directory" +#define E_IOERR "I/O error" +#define E_NOMEM "insufficent memory" +#define E_QUOTA "file system quota reached" +#define E_PERM "permission denied" +#define E_ROFS "read-only file system" + +#endif diff --git a/lfs.c b/lfs.c index ab010ae..448b378 100644 --- a/lfs.c +++ b/lfs.c @@ -21,97 +21,9 @@ #include #include "callisto.h" +#include "errors.h" #include "util.h" -/* Error messages */ -#define E_PATHNAMETOOLONG "pathname too long" -#define E_WORKDIRNOTVALID "working directory is no longer valid" -#define E_COMPNOTEXIST "component of path does not exist" -#define E_DIRNOTEMPTY "directory not empty" -#define E_MOUNTPOINT "directory is busy" -#define E_NOSUCHDEST "no such file or directory" -#define E_FTRAVERSE "failed to traverse directory" -#define E_NOSUCHDIR "no such directory" -#define E_STICKYDIR "permission denied (sticky directory)" -#define E_INTFAULT "internal error (EFAULT)" -#define E_MVPARENT "cannot move a parent directory of pathname" -#define E_FEXISTS "file exists" -#define E_MAXLINK "maximum link count reached" -#define E_NOSPACE "insufficient space left on file system" -#define E_NOTADIR "pathname or a component of pathname is not a directory" -#define E_SYMLINK "could not translate pathname; too many symbolic links" -#define E_DIFFFS "pathnames are on different file systems" -#define E_DIRDOT "last component of path is '.'" -#define E_ISADIR "cannot move a file to the name of a directory" -#define E_IOERR "I/O error" -#define E_NOMEM "insufficent memory" -#define E_QUOTA "file system quota reached" -#define E_PERM "permission denied" -#define E_ROFS "read-only file system" - -/*** - * Returns the last component of the given pathname, - * removing any trailing '/' characters. If the given - * path consists entirely of '/' characters, the string - * `"/"` is returned. If *path* is an empty string, - * the string `"."` is returned. - * - * This function may return nil if the given - * pathname exceeds the system's path length - * limit (On most Linux systems this will be 4096). - * - * @function basename - * @usage fs.basename(arg[0]) - * @tparam string path The path to process. - */ -static int -fs_basename(lua_State *L) -{ - const char *ret; - char *path; /* parameter 1 (string) */ - - path = strndup(luaL_checkstring(L, 1), lua_rawlen(L, 1)); - ret = basename(path); - - if (ret == NULL && errno == ENAMETOOLONG) /* check if path is too long */ - return lfail(L, E_PATHNAMETOOLONG); - - lua_pushstring(L, ret); - return 1; -} - -/*** - * Returns the parent directory of the pathname - * given. Any trailing '/' characters are not - * counted as part of the directory name. - * If the given path is an empty string or contains - * no '/' characters, the string `"."` is returned, - * signifying the current directory. - * - * This function may return nil if the given - * pathname exceeds the system's path length - * limit (On most Linux systems this will be 4096). - * - * @function dirname - * @usage fs.dirname(arg[0]) - * @tparam string path The path to process. - */ -static int -fs_dirname(lua_State *L) -{ - const char *ret; - char *path; /* parameter 1 (string) */ - - path = strndup(luaL_checkstring(L, 1), lua_rawlen(L, 1)); - ret = dirname(path); - - if (ret == NULL && errno == ENAMETOOLONG) /* check if path is too long */ - return lfail(L, E_PATHNAMETOOLONG); - - lua_pushstring(L, ret); - return 1; -} - /*** * Returns true if the given pathname exists * in the file system, or returns false if it @@ -606,8 +518,6 @@ fs_workdir(lua_State *L) } static const luaL_Reg fslib[] = { - {"basename", fs_basename}, - {"dirname", fs_dirname}, {"exists", fs_exists}, {"mkdir", fs_mkdir}, {"move", fs_move}, diff --git a/lpath.c b/lpath.c new file mode 100644 index 0000000..7d05a3d --- /dev/null +++ b/lpath.c @@ -0,0 +1,98 @@ +/*** + * File system path manipulation. + * @module path + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "callisto.h" +#include "errors.h" +#include "util.h" + + +/*** + * Returns the last component of the given pathname, + * removing any trailing '/' characters. If the given + * path consists entirely of '/' characters, the string + * `"/"` is returned. If *path* is an empty string, + * the string `"."` is returned. + * + * This function may return nil if the given + * pathname exceeds the system's path length + * limit (On most Linux systems this will be 4096). + * + * @function basename + * @usage path.basename(arg[0]) + * @tparam string path The path to process. + */ +static int +path_basename(lua_State *L) +{ + const char *ret; + char *path; /* parameter 1 (string) */ + + path = strndup(luaL_checkstring(L, 1), lua_rawlen(L, 1)); + ret = basename(path); + + if (ret == NULL && errno == ENAMETOOLONG) /* check if path is too long */ + return lfail(L, E_PATHNAMETOOLONG); + + lua_pushstring(L, ret); + return 1; +} + +/*** + * Returns the parent directory of the pathname + * given. Any trailing '/' characters are not + * counted as part of the directory name. + * If the given path is an empty string or contains + * no '/' characters, the string `"."` is returned, + * signifying the current directory. + * + * This function may return nil if the given + * pathname exceeds the system's path length + * limit (On most Linux systems this will be 4096). + * + * @function dirname + * @usage path.dirname(arg[0]) + * @tparam string path The path to process. + */ +static int +path_dirname(lua_State *L) +{ + const char *ret; + char *path; /* parameter 1 (string) */ + + path = strndup(luaL_checkstring(L, 1), lua_rawlen(L, 1)); + ret = dirname(path); + + if (ret == NULL && errno == ENAMETOOLONG) /* check if path is too long */ + return lfail(L, E_PATHNAMETOOLONG); + + lua_pushstring(L, ret); + return 1; +} + +static const luaL_Reg pathlib[] = { + {"basename", path_basename}, + {"dirname", path_dirname}, + {NULL, NULL} +}; + +int +luaopen_path(lua_State *L) +{ + luaL_newlib(L, pathlib); + return 1; +}