diff options
-rw-r--r-- | ChangeLog | 17 | ||||
-rw-r--r-- | eval.c | 14 | ||||
-rw-r--r-- | stream.c | 84 | ||||
-rw-r--r-- | stream.h | 9 | ||||
-rw-r--r-- | txr.1 | 144 |
5 files changed, 263 insertions, 5 deletions
@@ -1,5 +1,22 @@ 2014-02-24 Kaz Kylheku <kaz@kylheku.com> + * eval.c (eval_init): Register forgotten s_ifsock variable. + Register mkdir_wrap, chdir_wrap, getcwd_wrap, makedev_wrap, minor_wrap, + major_wrap and mknod_wrap. + + * stream.c (mkdir_wrap, chdir_wrap, getcwd_wrap, makedev_wrap, + minor_wrap, major_wrap, mknod_wrap): New functions. + (stream_init): Initialize forgotten variable s-ifsock. + + * stream.h (s_ifsock): Declared. + (mkdir_wrap, chdir_wrap, getcwd_wrap, makedev_wrap, + minor_wrap, major_wrap, mknod_wrap): Declared. + + * txr.1: Forgotten documentation for remove-path and rename-path + added. Forgotten mention of s-ifsock. Documented new Unix functions. + +2014-02-24 Kaz Kylheku <kaz@kylheku.com> + * parser.l: Support octal and binary numbers. * txr.1: Documented. @@ -3383,6 +3383,7 @@ void eval_init(void) reg_fun(intern(lit("stream-get-prop"), user_package), func_n2(stream_get_prop)); reg_fun(intern(lit("make-catenated-stream"), user_package), func_n0v(make_catenated_stream)); reg_var(intern(lit("s-ifmt"), user_package), &s_ifmt); + reg_var(intern(lit("s-ifsock"), user_package), &s_ifsock); reg_var(intern(lit("s-iflnk"), user_package), &s_iflnk); reg_var(intern(lit("s-ifreg"), user_package), &s_ifreg); reg_var(intern(lit("s-ifblk"), user_package), &s_ifblk); @@ -3590,6 +3591,19 @@ void eval_init(void) reg_fun(intern(lit("daemon"), user_package), func_n2(daemon_wrap)); #endif +#ifdef HAVE_SYS_STAT + reg_fun(intern(lit("mkdir"), user_package), func_n2o(mkdir_wrap, 1)); +#endif + +#ifdef HAVE_UNISTD_H + reg_fun(intern(lit("chdir"), user_package), func_n1(chdir_wrap)); + reg_fun(intern(lit("pwd"), user_package), func_n0(getcwd_wrap)); + reg_fun(intern(lit("makedev"), user_package), func_n2(makedev_wrap)); + reg_fun(intern(lit("minor"), user_package), func_n1(minor_wrap)); + reg_fun(intern(lit("major"), user_package), func_n1(major_wrap)); + reg_fun(intern(lit("mknod"), user_package), func_n3(mknod_wrap)); +#endif + #if HAVE_SYSLOG reg_var(intern(lit("log-pid"), user_package), &log_pid_v); reg_var(intern(lit("log-cons"), user_package), &log_cons_v); @@ -2378,6 +2378,86 @@ val rename_path(val from, val to) return t; } +#if HAVE_SYS_STAT +val mkdir_wrap(val path, val mode) +{ + char *u8path = utf8_dup_to(c_str(path)); + int err = mkdir(u8path, c_num(default_arg(mode, num_fast(0777)))); + free(u8path); + + if (err < 0) + uw_throwf(file_error_s, lit("mkdir ~a: ~a/~s"), + path, num(errno), string_utf8(strerror(errno)), nao); + + return t; +} +#endif + +#if HAVE_UNISTD_H +val chdir_wrap(val path) +{ + char *u8path = utf8_dup_to(c_str(path)); + int err = chdir(u8path); + free(u8path); + + if (err < 0) + uw_throwf(file_error_s, lit("chdir ~a: ~a/~s"), + path, num(errno), string_utf8(strerror(errno)), nao); + return t; +} + +val getcwd_wrap(void) +{ + size_t guess = 256; + + for (;;) { + char *u8buf = (char *) chk_malloc(guess); + if (getcwd(u8buf, 256) < 0) { + free(u8buf); + if (errno != ERANGE) { + uw_throwf(file_error_s, lit("getcwd: ~a/~s"), + num(errno), string_utf8(strerror(errno)), nao); + } + if (2 * guess > guess) + guess = 2 * guess; + } else { + val out = string_utf8(u8buf); + free(u8buf); + return out; + } + } +} + +val makedev_wrap(val major, val minor) +{ + return num(makedev(c_num(major), c_num(minor))); +} + +val minor_wrap(val dev) +{ + return num(minor(c_num(dev))); +} + +val major_wrap(val dev) +{ + return num(major(c_num(dev))); +} + +val mknod_wrap(val path, val mode, val dev) +{ + char *u8path = utf8_dup_to(c_str(path)); + int err = mknod(u8path, c_num(mode), c_num(default_arg(dev, zero))); + free(u8path); + + if (err < 0) + uw_throwf(file_error_s, lit("mknod ~a ~a ~a (~a:~a): ~a/~s"), + path, mode, dev, major_wrap(dev), minor_wrap(dev), num(errno), + string_utf8(strerror(errno)), nao); + + return t; +} + +#endif void stream_init(void) { @@ -2410,6 +2490,10 @@ void stream_init(void) s_ifmt = num(S_IFMT); +#ifdef S_IFSOCK + s_ifsock = num(S_IFSOCK); +#endif + #ifdef S_IFLNK s_iflnk = num(S_IFLNK); #endif @@ -56,7 +56,7 @@ extern val atime_k, mtime_k, ctime_k; extern val from_start_k, from_current_k, from_end_k; extern val real_time_k, name_k; -extern val s_ifmt, s_iflnk, s_ifreg, s_ifblk, s_ifdir; +extern val s_ifmt, s_ifsock, s_iflnk, s_ifreg, s_ifblk, s_ifdir; extern val s_ifchr, s_ififo, s_isuid, s_isgid, s_isvtx, s_irwxu; extern val s_irusr, s_iwusr, s_ixusr, s_irwxg, s_irgrp, s_iwgrp; extern val s_ixgrp, s_irwxo, s_iroth, s_iwoth, s_ixoth; @@ -101,5 +101,12 @@ val open_process(val path, val mode_str, val args); val make_catenated_stream(val stream_list); val remove_path(val path); val rename_path(val from, val to); +val mkdir_wrap(val path, val mode); +val chdir_wrap(val path); +val getcwd_wrap(void); +val makedev_wrap(val major, val minor); +val minor_wrap(val dev); +val major_wrap(val dev); +val mknod_wrap(val path, val mode, val dev); void stream_init(void); @@ -11673,10 +11673,10 @@ as the st_dev field. The following variables exist, having integer values. These are bitmasks which can be applied against the value given by the :mode property -in the property list returned by the function stat: s-ifmt, s-iflnk, s-ifreg, -s-ifblk, s-ifdir, s-ifchr, s-ififo, s-isuid, s-isgid, s-isvtx, s-irwxu, -s-irusr, s-iwusr, s-ixusr, s-irwxg, s-irgrp, s-iwgrp, s-ixgrp, s-irwxo, -s-iroth, s-iwoth and s-ixoth. +in the property list returned by the function stat: s-ifmt, s-ifsock, s-iflnk, +s-ifreg, s-ifblk, s-ifdir, s-ifchr, s-ififo, s-isuid, s-isgid, s-isvtx, +s-irwxu, s-irusr, s-iwusr, s-ixusr, s-irwxg, s-irgrp, s-iwgrp, s-ixgrp, +s-irwxo, s-iroth, s-iwoth and s-ixoth. These variables correspond to the C constants S_IFMT, S_IFLNK, S_IFREG and so forth. @@ -11764,6 +11764,44 @@ Caveat: since a tail stream can re-open a new file which has the same name as the original file, it will do the wrong thing if the program changes the current working directory, and the path name is relative. +.SS Function remove-path + +.TP +Syntax: + + (remove-path <path>) + +.TP +Description: + +The remove-path function tries to remove the filesystem object named +by <path>, which may be a file, directory or something else. + +If successful, it returns t. + +A failure to remove the object results in an exception of type file-error. + +.SS Function rename-path + +.TP +Syntax: + + (rename-path <from-path> <to-path>) + +.TP +Description: + +The remove-path function tries to rename filesystem path <from-path>, which may +refer to a file, directory or something else, to the path <to-path>. + +If successful, it returns t. + +A failure to rename path results in an exception of type file-error. + + +.TP +Description: + .SH COPROCESSES .SS Functions open-command, open-process @@ -12319,6 +12357,52 @@ EXIT_FAILURE, and t corresponds to EXIT_SUCCESS. These are platform-independent indicators of failed or successful termination. The numeric value 0 also indicates success. +.SS Function mkdir + +.TP +Syntax: + + (mkdir <path> [<mode>]) + +.TP +Description: + +Try to create the directory named <path> using the POSIX mkdir function. +An exception of type file_error is thrown if the function fails. Returns +t on success. + +The <mode> argument specifies the request numeric permissions +for the newly created directory. If omitted, the requested permissions are +#o777 (511): readable and writable to everyone. The requested permissions +are subject to umask. + +.SS Function chdir + +.TP +Syntax: + + (chdir <path>) + +.TP +Description: + +This changes the current working directory to <path>, and returns t, +or else throws an exception of type file-error. + +.SS Function pwd + +.TP +Syntax: + + (pwd) + +.TP +Description: + +This function retrieves the current working directory. +If the underlying getcwd system call fails with an errno other than ERANGE, +an exception will be thrown. + .SS Function daemon .TP @@ -12334,6 +12418,58 @@ This is a wrapper for the Unix function daemon of BSD origin. It returns t if successful, nil otherwise, and the errno variable is set in that case. +.SS Functions makedev, minor, major + +.TP +Syntax: + + (makedev <minor> <major>) + (minor <dev>) + (major <dev>) + +.TP +Description: + +The parameters <minor>, <major> and <dev> are all integers. The makedev +function constructs a combined device number from a minor and major pair (by +calling the Unix makedev function). This device number is suitable as an +argument to the mknod function (see below). Device numbers also appear as :dev +property returned by the stat function. + +The minor and major functions extract the minor and major device number +from a combined device number. + +.SS Function mknod + +.TP +Syntax: + + (mknod <path> <mode> [<dev>]) + +.TP +Description: + +The mknod function tries to create an entry in the filesystem: a file, +FIFO, or a device special file, under the name <path>. If it is successful, +it returns t, otherwise it throws an exception of type file-error. + +The <mode> argument is a bitwise "or" combination of the requested permisions, +and the type of object to create: one of the constants s-ifreg, s-ififo, +s-ifchr or s-ifblk or s-ifsock. The permissions are subject to the umask. + +If a block or character special device (s-ifchr or s-ifblk) is being +created, then the <dev> argument specifies the major and minor numbers +of the device. A suitable value can be constructed from a major and minor +pair using the makedev function. + +.TP +Example: + + ;; make a character device (8, 3) called /dev/foo + ;; requesting rwx------ permissions + + (mknod "dev/foo" (logior #o700 s-ifchr) (makedev 8 3)) + .SH UNIX SIGNAL HANDLING On platforms where certain advanced features of POSIX signal handling are |