[v3 PATCH] cmd: Implement builtin mklink command

Alistair Leslie-Hughes leslie_alistair at hotmail.com
Tue Nov 7 17:26:42 CST 2017


v3. Fixed help message.

Signed-off-by: Alistair Leslie-Hughes <leslie_alistair at hotmail.com>
---
 programs/cmd/builtins.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++
 programs/cmd/cmd.rc     | 12 +++++++++++-
 programs/cmd/wcmd.h     |  4 +++-
 programs/cmd/wcmdmain.c |  3 +++
 4 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c
index 1da1f67..6f7a2c9 100644
--- a/programs/cmd/builtins.c
+++ b/programs/cmd/builtins.c
@@ -94,6 +94,7 @@ const WCHAR inbuilt[][10] = {
         {'F','T','Y','P','E','\0'},
         {'M','O','R','E','\0'},
         {'C','H','O','I','C','E','\0'},
+        {'M','K','L','I','N','K','\0'},
         {'E','X','I','T','\0'}
 };
 static const WCHAR externals[][10] = {
@@ -4959,3 +4960,54 @@ void WCMD_color (void) {
       SetConsoleTextAttribute(hStdOut, color);
   }
 }
+
+void WCMD_mklink(WCHAR *args)
+{
+  int   argno = 0;
+  WCHAR *argN = args;
+  BOOL isdir = FALSE;
+  BOOL junction = FALSE;
+  BOOL hard = FALSE;
+  BOOL ret = FALSE;
+  WCHAR file1[MAX_PATH] = {0};
+  WCHAR file2[MAX_PATH];
+  static const WCHAR optD[] = {'/', 'D', '\0'};
+  static const WCHAR optH[] = {'/', 'H', '\0'};
+  static const WCHAR optJ[] = {'/', 'J', '\0'};
+
+  if (param1[0] == 0x00 || param2[0] == 0x00) {
+    WCMD_output_stderr(WCMD_LoadMessage(WCMD_NOARG));
+    return;
+  }
+
+  while (argN) {
+    WCHAR *thisArg = WCMD_parameter (args, argno++, &argN, FALSE, FALSE);
+
+    if (!argN) break;
+
+    WINE_TRACE("mklink: Processing arg '%s'\n", wine_dbgstr_w(thisArg));
+
+    if(lstrcmpiW(thisArg, optD) == 0)
+      isdir = TRUE;
+    else if(lstrcmpiW(thisArg, optH) == 0)
+      hard = TRUE;
+    else if(lstrcmpiW(thisArg, optJ) == 0)
+      junction = TRUE;
+    else {
+      if(!file1[0])
+        lstrcpyW(file1, thisArg);
+      else
+        lstrcpyW(file2, thisArg);
+    }
+  }
+
+  if(hard)
+    ret = CreateHardLinkW(file1, file2, NULL);
+  else if(!junction)
+    ret = CreateSymbolicLinkW(file1, file2, isdir);
+  else if(junction)
+    WINE_TRACE("Juction links currently not supported.\n");
+
+  if(!ret)
+    WCMD_output_stderr(WCMD_LoadMessage(WCMD_READFAIL), file1);
+}
diff --git a/programs/cmd/cmd.rc b/programs/cmd/cmd.rc
index 03388de..3f74791 100644
--- a/programs/cmd/cmd.rc
+++ b/programs/cmd/cmd.rc
@@ -310,6 +310,16 @@ CHOICE is mainly used to build a menu selection in a batch file.\n"
 "EXIT terminates the current command session and returns to the operating\n\
 system or shell from which you invoked cmd.\n"
 
+  WCMD_MKLINK,
+"Creates a symbolic link.\n\
+MKLINK [options] link_name target\n\
+Options:\n\
+/d             Creates a symbolic link.  (Default)\n\
+/h             Creates a hard link.\n\
+/j             Creates a Directory Junction.\n\
+link_name specifies the new symbolic link name.\n\
+target specifies the path that the link_name points to.\n"
+
   WCMD_ALLHELP,
 "CMD built-in commands are:\n\
 ASSOC\t\tShow or modify file extension associations\n\
@@ -328,6 +338,7 @@ ENDLOCAL\tEnd localization of environment changes in a batch file\n\
 FTYPE\t\tShow or modify open commands associated with file types\n\
 HELP\t\tShow brief help details on a topic\n\
 MD (MKDIR)\tCreate a subdirectory\n\
+MKLINK\tCreates Symbolic Links and Hard Links\n\
 MORE\t\tDisplay output in pages\n\
 MOVE\t\tMove a file, set of files or directory tree\n\
 PATH\t\tSet or show the search path\n\
@@ -348,7 +359,6 @@ VOL\t\tShow the volume label of a disk device\n\
 XCOPY\t\tCopy source files or directory trees to a destination\n\
 EXIT\t\tClose down CMD\n\n\
 Enter HELP <command> for further information on any of the above commands.\n"
-
   WCMD_CONFIRM, "Are you sure?"
   WCMD_YES, "#msgctxt#Yes key#Y"
   WCMD_NO, "#msgctxt#No key#N"
diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h
index 557be14..d4d97a0 100644
--- a/programs/cmd/wcmd.h
+++ b/programs/cmd/wcmd.h
@@ -101,6 +101,7 @@ void WCMD_type (WCHAR *);
 void WCMD_verify (const WCHAR *args);
 void WCMD_version (void);
 int  WCMD_volume (BOOL set_label, const WCHAR *args);
+void WCMD_mklink(WCHAR *args);
 
 static inline BOOL WCMD_is_console_handle(HANDLE h)
 {
@@ -266,9 +267,10 @@ extern BOOL delayedsubst;
 #define WCMD_FTYPE    42
 #define WCMD_MORE     43
 #define WCMD_CHOICE   44
+#define WCMD_MKLINK   45
 
 /* Must be last in list */
-#define WCMD_EXIT     45
+#define WCMD_EXIT     46
 
 /* Some standard messages */
 extern const WCHAR newlineW[];
diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c
index cec6df0..827ddd2 100644
--- a/programs/cmd/wcmdmain.c
+++ b/programs/cmd/wcmdmain.c
@@ -1597,6 +1597,9 @@ void WCMD_execute (const WCHAR *command, const WCHAR *redirects,
       case WCMD_CHOICE:
         WCMD_choice(p);
         break;
+      case WCMD_MKLINK:
+        WCMD_mklink(p);
+        break;
       case WCMD_EXIT:
         WCMD_exit (cmdList);
         break;
-- 
1.9.1




More information about the wine-patches mailing list