diff options
-rw-r--r-- | lib.c | 4 | ||||
-rw-r--r-- | lib.h | 1 | ||||
-rw-r--r-- | parser.c | 3 | ||||
-rw-r--r-- | socket.c | 5 | ||||
-rw-r--r-- | stream.c | 58 | ||||
-rw-r--r-- | sysif.c | 129 | ||||
-rw-r--r-- | sysif.h | 1 | ||||
-rw-r--r-- | txr.1 | 6 | ||||
-rw-r--r-- | unwind.c | 3 |
9 files changed, 144 insertions, 66 deletions
@@ -108,6 +108,7 @@ val error_s, type_error_s, internal_error_s, panic_s; val numeric_error_s, range_error_s; val query_error_s, file_error_s, process_error_s, syntax_error_s; val timeout_error_s, system_error_s, alloc_error_s; +val path_not_found_s, path_exists_s, path_permission_s; val warning_s, defr_warning_s, restart_s, continue_s; val gensym_counter_s, nullify_s, from_list_s, lambda_set_s, length_s; val rplaca_s, rplacd_s, seq_iter_s; @@ -10844,6 +10845,9 @@ static void obj_init(void) system_error_s = intern(lit("system-error"), user_package); timeout_error_s = intern(lit("timeout-error"), user_package); alloc_error_s = intern(lit("alloc-error"), user_package); + path_not_found_s = intern(lit("path-not-found"), user_package); + path_exists_s = intern(lit("path-exists"), user_package); + path_permission_s = intern(lit("path-permission"), user_package); assert_s = intern(lit("assert"), user_package); warning_s = intern(lit("warning"), user_package); defr_warning_s = intern(lit("defr-warning"), user_package); @@ -497,6 +497,7 @@ extern val error_s, type_error_s, internal_error_s, panic_s; extern val numeric_error_s, range_error_s; extern val query_error_s, file_error_s, process_error_s, syntax_error_s; extern val timeout_error_s, system_error_s, alloc_error_s; +extern val path_not_found_s, path_exists_s, path_permission_s; extern val warning_s, defr_warning_s, restart_s, continue_s; extern val gensym_counter_s; extern val rplaca_s, rplacd_s, seq_iter_s; @@ -498,7 +498,8 @@ void open_txr_file(val spec_file, val *txr_lisp_p, val *name, val *stream) #ifdef ENOENT except: #endif - uw_throwf(file_error_s, lit("unable to open ~a"), spec_file_try, nao); + uw_throwf(errno_to_file_error(errno), + lit("unable to open ~a"), spec_file_try, nao); } *stream = make_stdio_stream(in, spec_file_try); @@ -770,9 +770,10 @@ static val open_sockfd(val fd, val family, val type, val mode_str) FILE *f = (errno = 0, w_fdopen(c_num(fd), c_str(normalize_mode(&m, mode_str, m_rpb)))); if (!f) { + int eno = errno; close(c_num(fd)); - uw_throwf(file_error_s, lit("error creating stream for socket ~a: ~d/~s"), - fd, num(errno), string_utf8(strerror(errno)), nao); + uw_throwf(errno_to_file_error(eno), lit("error creating stream for socket ~a: ~d/~s"), + fd, num(eno), string_utf8(strerror(eno)), nao); } return set_mode_props(m, make_sock_stream(f, family, type)); @@ -3881,9 +3881,12 @@ val open_directory(val path) { DIR *d = w_opendir(c_str(path)); - if (!d) - uw_throwf(file_error_s, lit("error opening directory ~a: ~d/~s"), - path, num(errno), string_utf8(strerror(errno)), nao); + if (!d) { + int eno = errno; + uw_throwf(errno_to_file_error(eno), + lit("error opening directory ~a: ~d/~s"), + path, num(eno), string_utf8(strerror(eno)), nao); + } return make_dir_stream(d); } @@ -3893,9 +3896,11 @@ val open_file(val path, val mode_str) struct stdio_mode m, m_r = stdio_mode_init_r; FILE *f = w_fopen(c_str(path), c_str(normalize_mode(&m, mode_str, m_r))); - if (!f) - uw_throwf(file_error_s, lit("error opening ~a: ~d/~s"), - path, num(errno), string_utf8(strerror(errno)), nao); + if (!f) { + int eno = errno; + uw_throwf(errno_to_file_error(eno), lit("error opening ~a: ~d/~s"), + path, num(eno), string_utf8(strerror(eno)), nao); + } return set_mode_props(m, make_stdio_stream(f, path)); } @@ -3906,9 +3911,10 @@ val open_fileno(val fd, val mode_str) FILE *f = (errno = 0, w_fdopen(c_num(fd), c_str(normalize_mode(&m, mode_str, m_r)))); if (!f) { + int eno = errno; close(c_num(fd)); - uw_throwf(file_error_s, lit("error opening descriptor ~a: ~d/~s"), - fd, num(errno), string_utf8(strerror(errno)), nao); + uw_throwf(errno_to_file_error(eno), lit("error opening descriptor ~a: ~d/~s"), + fd, num(eno), string_utf8(strerror(eno)), nao); } return set_mode_props(m, make_stdio_stream(f, format(nil, @@ -4020,9 +4026,11 @@ val open_command(val path, val mode_str) f = w_popen(c_str(path), c_str(mode)); - if (!f) - uw_throwf(file_error_s, lit("error opening pipe ~a: ~d/~s"), - path, num(errno), string_utf8(strerror(errno)), nao); + if (!f) { + int eno = errno; + uw_throwf(errno_to_file_error(eno), lit("error opening pipe ~a: ~d/~s"), + path, num(eno), string_utf8(strerror(eno)), nao); + } uw_unwind { fds_restore(&sfds); @@ -4063,9 +4071,11 @@ val open_process(val name, val mode_str, val args) argv = coerce(char **, chk_xalloc(nargs + 1, sizeof *argv, self)); if (pipe(fd) == -1) { + int eno = errno; free(argv); - uw_throwf(file_error_s, lit("opening pipe ~a, pipe syscall failed: ~d/~s"), - name, num(errno), string_utf8(strerror(errno)), nao); + uw_throwf(errno_to_file_error(eno), + lit("opening pipe ~a, pipe syscall failed: ~d/~s"), + name, num(eno), string_utf8(strerror(eno)), nao); } for (i = 0, iter = cons(name, args); iter; i++, iter = cdr(iter)) { @@ -4080,7 +4090,7 @@ val open_process(val name, val mode_str, val args) for (i = 0; i < nargs; i++) free(argv[i]); free(argv); - uw_throwf(file_error_s, lit("opening pipe ~a, fork syscall failed: ~d/~s"), + uw_throwf(process_error_s, lit("opening pipe ~a, fork syscall failed: ~d/~s"), name, num(errno), string_utf8(strerror(errno)), nao); } @@ -4276,7 +4286,7 @@ static val run(val name, val args) for (i = 0; i < nargs; i++) free(argv[i]); free(argv); - uw_throwf(file_error_s, lit("opening process ~a, fork syscall failed: ~d/~s"), + uw_throwf(process_error_s, lit("opening process ~a, fork syscall failed: ~d/~s"), name, num(errno), string_utf8(strerror(errno)), nao); } @@ -4369,9 +4379,11 @@ static val sh(val command) val remove_path(val path, val throw_on_error) { if (w_remove(c_str(path)) < 0) { - if (default_null_arg(throw_on_error) || errno != ENOENT) - uw_throwf(file_error_s, lit("trying to remove ~a: ~d/~s"), - path, num(errno), string_utf8(strerror(errno)), nao); + if (default_null_arg(throw_on_error) || errno != ENOENT) { + int eno = errno; + uw_throwf(errno_to_file_error(eno), lit("trying to remove ~a: ~d/~s"), + path, num(eno), string_utf8(strerror(eno)), nao); + } return nil; } @@ -4380,9 +4392,13 @@ val remove_path(val path, val throw_on_error) val rename_path(val from, val to) { - if (w_rename(c_str(from), c_str(to)) < 0) - uw_throwf(file_error_s, lit("trying to rename ~a to ~a: ~d/~s"), - from, to, num(errno), string_utf8(strerror(errno)), nao); + if (w_rename(c_str(from), c_str(to)) < 0) { + int eno = errno; + uw_throwf(errno_to_file_error(eno), + lit("trying to rename ~a to ~a: ~d/~s"), + from, to, num(eno), string_utf8(strerror(eno)), nao); + } + return t; } @@ -235,6 +235,25 @@ static val env_hash(void) return hash; } +val errno_to_file_error(int err) +{ + switch (err) { +#ifdef ENOENT + case ENOENT: return path_not_found_s; +#endif +#ifdef EEXIST + case EEXIST: return path_exists_s; +#endif +#ifdef EPERM + case EPERM: return path_permission_s; +#endif +#ifdef EACCES + case EACCES: return path_permission_s; +#endif + default: return file_error_s; + } +} + #if HAVE_MKDIR static val mkdir_wrap(val path, val mode) { @@ -243,9 +262,11 @@ static val mkdir_wrap(val path, val mode) int err = mkdir(u8path, cmode); free(u8path); - if (err < 0) - uw_throwf(file_error_s, lit("mkdir ~a: ~d/~s"), - path, num(errno), string_utf8(strerror(errno)), nao); + if (err < 0) { + int eno = errno; + uw_throwf(errno_to_file_error(eno), lit("mkdir ~a: ~d/~s"), + path, num(eno), string_utf8(strerror(eno)), nao); + } return t; } @@ -255,9 +276,11 @@ static val mkdir_wrap(val path, val mode) int err = _wmkdir(c_str(path)); (void) mode; - if (err < 0) - uw_throwf(file_error_s, lit("mkdir ~a: ~d/~s"), - path, num(errno), string_utf8(strerror(errno)), nao); + if (err < 0) { + int eno = errno; + uw_throwf(errno_to_file_error(eno), lit("mkdir ~a: ~d/~s"), + path, num(eno), string_utf8(strerror(eno)), nao); + } return t; } @@ -316,10 +339,12 @@ static val ensure_dir(val path, val mode) partial_path, sep, pop(&split_path), nao); } - if (ret != t) - uw_throwf(file_error_s, + if (ret != t) { + int eno = c_num(ret); + uw_throwf(errno_to_file_error(eno), lit("ensure-dir: ~a: ~d/~s"), path, ret, - string_utf8(strerror(c_num(ret))), nao); + string_utf8(strerror(eno)), nao); + } return ret; } @@ -332,9 +357,12 @@ static val chdir_wrap(val path) int err = chdir(u8path); free(u8path); - if (err < 0) - uw_throwf(file_error_s, lit("chdir ~a: ~d/~s"), - path, num(errno), string_utf8(strerror(errno)), nao); + if (err < 0) { + int eno = errno; + uw_throwf(errno_to_file_error(eno), lit("chdir ~a: ~d/~s"), + path, num(eno), string_utf8(strerror(eno)), nao); + } + return t; } @@ -346,9 +374,10 @@ val getcwd_wrap(void) char *u8buf = coerce(char *, chk_malloc(guess)); if (getcwd(u8buf, guess) == 0) { + int eno = errno; free(u8buf); - if (errno != ERANGE) { - uw_throwf(file_error_s, lit("getcwd: ~d/~s"), + if (eno != ERANGE) { + uw_throwf(errno_to_file_error(eno), lit("getcwd: ~d/~s"), num(errno), string_utf8(strerror(errno)), nao); } if (2 * guess > guess) @@ -393,16 +422,18 @@ static val mknod_wrap(val path, val mode, val dev) int err = mknod(u8path, cmode, cdev); free(u8path); - if (err < 0) + if (err < 0) { + int eno = errno; #if HAVE_MAKEDEV - uw_throwf(file_error_s, lit("mknod ~a ~a ~a (~d:~d): ~d/~s"), - path, mode, dev, major_wrap(dev), minor_wrap(dev), num(errno), - string_utf8(strerror(errno)), nao); + uw_throwf(errno_to_file_error(eno), lit("mknod ~a ~a ~a (~d:~d): ~d/~s"), + path, mode, dev, major_wrap(dev), minor_wrap(dev), num(eno), + string_utf8(strerror(eno)), nao); #else - uw_throwf(file_error_s, lit("mknod ~a ~a ~a: ~d/~s"), - path, mode, dev, num(errno), - string_utf8(strerror(errno)), nao); + uw_throwf(errno_to_file_error(eno), lit("mknod ~a ~a ~a: ~d/~s"), + path, mode, dev, num(eno), + string_utf8(strerror(eno)), nao); #endif + } return t; } @@ -418,9 +449,12 @@ static val chmod_wrap(val path, val mode) int err = chmod(u8path, cmode); free(u8path); - if (err < 0) - uw_throwf(file_error_s, lit("chmod ~a #o~o: ~d/~s"), - path, mode, num(errno), string_utf8(strerror(errno)), nao); + if (err < 0) { + int eno = errno; + uw_throwf(errno_to_file_error(eno), lit("chmod ~a #o~o: ~d/~s"), + path, mode, num(eno), string_utf8(strerror(eno)), nao); + } + return t; } @@ -437,9 +471,13 @@ static val symlink_wrap(val target, val to) int err = symlink(u8target, u8to); free(u8target); free(u8to); - if (err < 0) - uw_throwf(file_error_s, lit("symlink ~a ~a: ~d/~s"), - target, to, num(errno), string_utf8(strerror(errno)), nao); + + if (err < 0) { + int eno = errno; + uw_throwf(errno_to_file_error(eno), lit("symlink ~a ~a: ~d/~s"), + target, to, num(eno), string_utf8(strerror(eno)), nao); + } + return t; } @@ -452,9 +490,13 @@ static val link_wrap(val target, val to) int err = link(u8target, u8to); free(u8target); free(u8to); - if (err < 0) - uw_throwf(file_error_s, lit("link ~a ~a: ~d/~s"), - target, to, num(errno), string_utf8(strerror(errno)), nao); + + if (err < 0) { + int eno = errno; + uw_throwf(errno_to_file_error(eno), lit("link ~a ~a: ~d/~s"), + target, to, num(eno), string_utf8(strerror(eno)), nao); + } + return t; } @@ -474,9 +516,10 @@ static val readlink_wrap(val path) else uw_throwf(file_error_s, lit("readlink: weird problem"), nao); } else if (bytes <= 0) { + int eno = errno; free(u8buf); - uw_throwf(file_error_s, lit("readlink ~a: ~d/~s"), - path, num(errno), string_utf8(strerror(errno)), nao); + uw_throwf(errno_to_file_error(eno), lit("readlink ~a: ~d/~s"), + path, num(eno), string_utf8(strerror(eno)), nao); } else { val out; u8buf[bytes] = 0; @@ -572,7 +615,7 @@ val exec_wrap(val file, val args_opt) val args = default_null_arg(args_opt); int nargs = c_num(length(args)) + 1; char **argv = if3(nargs < 0 || nargs == INT_MAX, - (uw_throwf(file_error_s, lit("~a: argument list overflow"), + (uw_throwf(process_error_s, lit("~a: argument list overflow"), self, nao), convert(char **, 0)), coerce(char **, chk_xalloc(nargs + 1, sizeof *argv, self))); val iter; @@ -585,9 +628,9 @@ val exec_wrap(val file, val args_opt) argv[i] = 0; if (execvp(argv[0], argv) < 0) - uw_throwf(file_error_s, lit("~s ~a: ~d/~s"), + uw_throwf(process_error_s, lit("~s ~a: ~d/~s"), self, file, num(errno), string_utf8(strerror(errno)), nao); - uw_throwf(file_error_s, lit("~s ~a returned"), self, file, nao); + uw_throwf(process_error_s, lit("~s ~a returned"), self, file, nao); } static val exit_star_wrap(val status) @@ -704,9 +747,11 @@ static val stat_impl(val obj, int (*statfn)(val, struct stat *), struct stat st; int res = statfn(obj, &st); - if (res == -1) - uw_throwf(file_error_s, lit("unable to ~a ~a: ~d/~s"), - name, obj, num(errno), string_utf8(strerror(errno)), nao); + if (res == -1) { + int eno = errno; + uw_throwf(errno_to_file_error(eno), lit("unable to ~a ~a: ~d/~s"), + name, obj, num(eno), string_utf8(strerror(eno)), nao); + } return if3(opt_compat && opt_compat <= 113, stat_to_list(st), stat_to_struct(st, path)); @@ -749,9 +794,11 @@ static val umask_wrap(val mask) static val pipe_wrap(void) { int fd[2]; - if (pipe(fd) < 0) - uw_throwf(file_error_s, lit("pipe failed: ~d/~s"), - num(errno), string_utf8(strerror(errno)), nao); + if (pipe(fd) < 0) { + int eno = errno; + uw_throwf(errno_to_file_error(eno), lit("pipe failed: ~d/~s"), + num(eno), string_utf8(strerror(eno)), nao); + } return cons(num(fd[0]), num(fd[1])); } @@ -43,6 +43,7 @@ typedef long off_t; #define OFF_T_MIN (-OFF_T_MAX) #endif +val errno_to_file_error(int err); val getenv_wrap(val name); val at_exit_call(val func); val at_exit_do_not_call(val func); @@ -38478,7 +38478,11 @@ subtype of every exception type: | +--- query-error | - +--- file-error + +--- file-error -------+--- path-not-found + | | + | +--- path-exists + | | + | +--- path-permission | +--- process-error | @@ -1177,6 +1177,9 @@ void uw_init(void) uw_register_subtype(timeout_error_s, error_s); uw_register_subtype(assert_s, error_s); uw_register_subtype(syntax_error_s, error_s); + uw_register_subtype(path_not_found_s, file_error_s); + uw_register_subtype(path_exists_s, file_error_s); + uw_register_subtype(path_permission_s, file_error_s); } void uw_late_init(void) |