[v2 PATCH] cmd: Implement builtin mklink command

Alistair Leslie-Hughes <[email protected]>
Newsgroups gmane.comp.emulators.wine.patches
Message-ID <SL2P216MB07465E9422421DC697E147BA93450@SL2P216MB0746.KORP216.PROD.OUTLOOK.COM>
v2: Fixed create logic

Signed-off-by: Alistair Leslie-Hughes <[email protected]>
---
 programs/cmd/builtins.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++
 programs/cmd/cmd.rc     | 11 ++++++++++-
 programs/cmd/wcmd.h     |  4 +++-
 programs/cmd/wcmdmain.c |  3 +++
 4 files changed, 68 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..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 1180251..7a02a01 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 102e485..108d5f8 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.