[PATCH] cmd: Implement builtin mklink command

Alistair Leslie-Hughes leslie_alistair at hotmail.com
Wed Sep 27 23:30:11 CDT 2017


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

diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c
index 7301f54..33c38c6 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] = {
@@ -4874,3 +4875,50 @@ 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;
+  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 && !CreateHardLinkW(file1, file2, NULL))
+    WCMD_output_stderr(WCMD_LoadMessage(WCMD_READFAIL), file1);
+  else if(!junction && !CreateSymbolicLinkW(file1, file2, isdir))
+    WCMD_output_stderr(WCMD_LoadMessage(WCMD_READFAIL), file1);
+  else if(junction)
+    WINE_TRACE("Juction links currently not supported.\n");
+}
diff --git a/programs/cmd/cmd.rc b/programs/cmd/cmd.rc
index 03388de..3ebae5a 100644
--- a/programs/cmd/cmd.rc
+++ b/programs/cmd/cmd.rc
@@ -310,6 +310,15 @@ 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 [[/D] | [/H] | [/J]] Link Target\n\
+/D             Creates a directory symbolic link.  Default is a file symbolic link.\n\
+/H             Creates a hard link instead of a symbolic link.\n\
+/J             Creates a Directory Junction.\n\
+Link specifies the new symbolic link name.\n\
+Target specifies the path (relative or absolute) that the new link refers to.\n"
+
   WCMD_ALLHELP,
 "CMD built-in commands are:\n\
 ASSOC\t\tShow or modify file extension associations\n\
@@ -328,6 +337,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 +358,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 c135621..c299f3a 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 1aa3c1c..2a6bb1c 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