aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--auto.def2
-rw-r--r--jim-file.c47
-rw-r--r--jim_tcl.txt15
3 files changed, 60 insertions, 4 deletions
diff --git a/auto.def b/auto.def
index 1dbbae9..8ffc98d 100644
--- a/auto.def
+++ b/auto.def
@@ -101,7 +101,7 @@ cc-check-functions ualarm lstat fork vfork system select execvpe
cc-check-functions backtrace geteuid mkstemp realpath strptime isatty
cc-check-functions regcomp waitpid sigaction sys_signame sys_siglist isascii
cc-check-functions syslog opendir readlink sleep usleep pipe getaddrinfo utimes
-cc-check-functions shutdown socketpair isinf isnan
+cc-check-functions shutdown socketpair isinf isnan link symlink
if {[cc-check-functions sysinfo]} {
cc-with {-includes sys/sysinfo.h} {
diff --git a/jim-file.c b/jim-file.c
index ea65f49..2fd051f 100644
--- a/jim-file.c
+++ b/jim-file.c
@@ -528,6 +528,44 @@ static int file_cmd_rename(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
return JIM_OK;
}
+#if defined(HAVE_LINK) && defined(HAVE_SYMLINK)
+static int file_cmd_link(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ int ret;
+ const char *source;
+ const char *dest;
+ static const char * const options[] = { "-hard", "-symbolic", NULL };
+ enum { OPT_HARD, OPT_SYMBOLIC, };
+ int option = OPT_HARD;
+
+ if (argc == 3) {
+ if (Jim_GetEnum(interp, argv[0], options, &option, NULL, JIM_ENUM_ABBREV | JIM_ERRMSG) != JIM_OK) {
+ return JIM_ERR;
+ }
+ argv++;
+ argc--;
+ }
+
+ dest = Jim_String(argv[0]);
+ source = Jim_String(argv[1]);
+
+ if (option == OPT_HARD) {
+ ret = link(source, dest);
+ }
+ else {
+ ret = symlink(source, dest);
+ }
+
+ if (ret != 0) {
+ Jim_SetResultFormatted(interp, "error linking \"%#s\" to \"%#s\": %s", argv[0], argv[1],
+ strerror(errno));
+ return JIM_ERR;
+ }
+
+ return JIM_OK;
+}
+#endif
+
static int file_stat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb)
{
const char *path = Jim_String(filename);
@@ -825,6 +863,15 @@ static const jim_subcmd_type file_command_table[] = {
3,
/* Description: Renames a file */
},
+#if defined(HAVE_LINK) && defined(HAVE_SYMLINK)
+ { "link",
+ "?-symbolic|-hard? newname target",
+ file_cmd_link,
+ 2,
+ 3,
+ /* Description: Creates a hard or soft link */
+ },
+#endif
#if defined(HAVE_READLINK)
{ "readlink",
"name",
diff --git a/jim_tcl.txt b/jim_tcl.txt
index d1eb687..2305b88 100644
--- a/jim_tcl.txt
+++ b/jim_tcl.txt
@@ -2243,11 +2243,12 @@ abbreviation for +'option'+ is acceptable. The valid options are:
Copies file +'source'+ to file +'target'+. The source file must exist.
The target file must not exist, unless +-force+ is specified.
-+*file delete ?-force?* 'name\...'+::
++*file delete ?-force? ?--?* 'name\...'+::
Deletes file or directory +'name'+. If the file or directory doesn't exist, nothing happens.
If it can't be deleted, an error is generated. Non-empty directories will not be deleted
unless the +-force+ options is given. In this case no errors will be generated, even
- if the file/directory can't be deleted.
+ if the file/directory can't be deleted. Use +'--'+ if there is any possibility of
+ the first name being +'-force'+.
+*file dirname* 'name'+::
Return all of the characters in +'name'+ up to but not including
@@ -2281,6 +2282,12 @@ abbreviation for +'option'+ is acceptable. The valid options are:
an absolute path, the preceding components are ignored.
Thus +"`file` join /tmp /root"+ returns +"/root"+.
++*file link* ?*-hard|-symbolic*? 'newname target'+::
+ Creates a hard link (default) or symbolic link from +'newname'+ to +'target'+.
+ Note that the sense of this command is the opposite of `file rename` and `file copy`
+ and also of `ln`, but this is compatible with Tcl.
+ An error is returned if +'target'+ doesn't exist or +'newname'+ already exists.
+
+*file lstat* 'name varName'+::
Same as 'stat' option (see below) except uses the +'lstat'+
kernel call instead of +'stat'+. This means that if +'name'+
@@ -2324,8 +2331,10 @@ abbreviation for +'option'+ is acceptable. The valid options are:
an error is returned. On systems that don't support symbolic links
this option is undefined.
-+*file rename* 'oldname' 'newname'+::
++*file rename* ?*-force*? 'oldname' 'newname'+::
Renames the file from the old name to the new name.
+ If +'newname'+ already exists, an error is returned unless +'-force'+ is
+ specified.
+*file rootname* 'name'+::
Return all of the characters in +'name'+ up to but not including