--- old/common/src/fixpath.c 2014-04-07 15:10:14.530555800 -0700 +++ new/common/src/fixpath.c 2014-04-07 15:10:14.030555800 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ #include #include -void report_error() +void report_error(char const * msg) { LPVOID lpMsgBuf; DWORD dw = GetLastError(); @@ -46,8 +46,8 @@ NULL); fprintf(stderr, - "Could not start process! Failed with error %d: %s\n", - dw, lpMsgBuf); + "%s Failed with error %d: %s\n", + msg, dw, lpMsgBuf); LocalFree(lpMsgBuf); } @@ -56,7 +56,7 @@ * Test if pos points to /cygdrive/_/ where _ can * be any character. */ -int is_cygdrive_here(int pos, char *in, int len) +int is_cygdrive_here(int pos, char const *in, int len) { // Length of /cygdrive/c/ is 12 if (pos+12 > len) return 0; @@ -81,16 +81,17 @@ * Works in place since drive letter is always * shorter than /cygdrive/ */ -char *replace_cygdrive_cygwin(char *in) +char *replace_cygdrive_cygwin(char const *in) { - int len = strlen(in); - char *out = malloc(len+1); + size_t len = strlen(in); + char *out = (char*) malloc(len+1); int i,j; if (len < 12) { - strcpy(out, in); + memmove(out, in, len + 1); return out; } + for (i = 0, j = 0; i *bl) { *bl *= 2; - *b = realloc(*b, *bl); + *b = (char*) realloc(*b, *bl); } memcpy(*b+*u, add, addlen); *u += addlen; @@ -125,7 +126,7 @@ int in_len = strlen(in); int sub_len = strlen(sub); int rep_len = strlen(rep); - char *out = malloc(in_len - sub_len + rep_len + 1); + char *out = (char *) malloc(in_len - sub_len + rep_len + 1); char *p; if (!(p = strstr(in, sub))) { @@ -145,7 +146,7 @@ char* msys_path_list; // @-separated list of paths prefix to look for char* msys_path_list_end; // Points to last \0 in msys_path_list. -void setup_msys_path_list(char* argument) +void setup_msys_path_list(char const * argument) { char* p; char* drive_letter_pos; @@ -173,7 +174,7 @@ } while (p != NULL); } -char *replace_cygdrive_msys(char *in) +char *replace_cygdrive_msys(char const *in) { char* str; char* prefix; @@ -195,12 +196,12 @@ return str; } -char*(*replace_cygdrive)(char *in) = NULL; +char*(*replace_cygdrive)(char const *in) = NULL; char *files_to_delete[1024]; int num_files_to_delete = 0; -char *fix_at_file(char *in) +char *fix_at_file(char const *in) { char *tmpdir; char name[2048]; @@ -222,9 +223,13 @@ exit(-1); } - tmpdir = getenv("TMP"); + tmpdir = getenv("TEMP"); if (tmpdir == NULL) { +#if _WIN64 + tmpdir = "c:/cygwin64/tmp"; +#else tmpdir = "c:/cygwin/tmp"; +#endif } _snprintf(name, sizeof(name), "%s\\atfile_XXXXXX", tmpdir); @@ -240,7 +245,7 @@ exit(-1); } - buffer = malloc(buflen); + buffer = (char*) malloc(buflen); while((blocklen = fread(block,1,sizeof(block),atin)) > 0) { append(&buffer, &buflen, &used, block, blocklen); } @@ -257,34 +262,107 @@ fclose(atout); free(fixed); free(buffer); - files_to_delete[num_files_to_delete] = malloc(strlen(name)+1); + files_to_delete[num_files_to_delete] = (char*) malloc(strlen(name)+1); strcpy(files_to_delete[num_files_to_delete], name); num_files_to_delete++; - atname = malloc(strlen(name)+2); + atname = (char*) malloc(strlen(name)+2); atname[0] = '@'; strcpy(atname+1, name); return atname; } -int main(int argc, char **argv) +// given an argument, convert it to the windows command line safe quoted version +// using rules from: +// http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx +// caller is responsible for freeing both input and output. +char * quote_arg(char const * in_arg) { + char *quoted = NULL; + char *current = quoted; + int pass; + + if(strpbrk(in_arg, " \t\n\v\r\\\"") == NULL) { + return _strdup(in_arg); + } + + // process the arg twice. Once to calculate the size and then to copy it. + for(pass=1; pass<=2; pass++) { + char const *arg = in_arg; + + // initial " + if(pass == 2) { + *current = '\"'; + } + current++; + + // process string to be quoted until NUL + do { + int escapes = 0; + + while (*arg == '\\') { + // count escapes. + escapes++; + arg++; + } + + if (*arg == '\0') { + // escape the escapes before final " + escapes *= 2; + } else if (*arg == '"') { + // escape the escapes and the " + escapes = escapes * 2 + 1; + } else { + // escapes aren't special, just echo them. + } + + // emit some escapes + while (escapes > 0) { + if (pass == 2) { + *current = '\\'; + } + current++; + escapes--; + } + + // and the current char + if (pass == 2) { + *current = *arg; + } + current++; + } while( *arg++ != '\0'); + + // allocate the buffer + if (pass == 1) { + size_t alloc = (size_t) (current - quoted + (ptrdiff_t) 2); + current = quoted = (char*) calloc(alloc, sizeof(char)); + } + } + + // final " and \0 + *(current - 1) = '"'; + *current = '\0'; + + return quoted; +} + +int main(int argc, char const ** argv) { STARTUPINFO si; PROCESS_INFORMATION pi; unsigned short rc; - char *new_at_file; - char *old_at_file; char *line; - int i; + char *current; + int i, cmd; DWORD exitCode; - if (argc<3 || argv[1][0] != '-' || (argv[1][1] != 'c' && argv[1][1] != 'm')) { - fprintf(stderr, "Usage: fixpath -c|m /cygdrive/c/WINDOWS/notepad.exe /cygdrive/c/x/test.txt\n"); + if (argc<2 || argv[1][0] != '-' || (argv[1][1] != 'c' && argv[1][1] != 'm')) { + fprintf(stderr, "Usage: fixpath -c|m /cygdrive/c/WINDOWS/notepad.exe [/cygdrive/c/x/test.txt|@/cygdrive/c/x/atfile]\n"); exit(0); } if (getenv("DEBUG_FIXPATH") != NULL) { - fprintf(stderr, "fixpath input line >%s<\n", strstr(GetCommandLine(), argv[1])); + char const * cmdline = GetCommandLine(); + fprintf(stderr, "fixpath input line >%s<\n", strstr( cmdline , argv[1])); } if (argv[1][1] == 'c' && argv[1][2] == '\0') { @@ -302,16 +380,71 @@ fprintf(stderr, "Unknown mode: %s\n", argv[1]); exit(-1); } - line = replace_cygdrive(strstr(GetCommandLine(), argv[2])); - for (i=1; i%s<\n", line); @@ -327,14 +460,14 @@ 0, TRUE, 0, - 0, - 0, + NULL, + NULL, &si, &pi); if(!rc) { // Could not start process for some reason. Try to report why: - report_error(); - exit(rc); + report_error("Could not start process!"); + exit(126); } WaitForSingleObject(pi.hProcess,INFINITE); @@ -345,12 +478,18 @@ fprintf(stderr, "Not deleting temporary fixpath file %s\n", files_to_delete[i]); } - } - else { + } else { for (i=0; i