diff options
-rw-r--r-- | src/main.c | 145 |
1 files changed, 143 insertions, 2 deletions
diff --git a/src/main.c b/src/main.c index 94a48f174..ea103e7ae 100644 --- a/src/main.c +++ b/src/main.c @@ -100,6 +100,21 @@ #define DEFAULT_MAXREDIRS 50L +#ifdef __DJGPP__ +void *xmalloc(size_t); +char *msdosify(char *); +char *rename_if_dos_device_name(char *); +void xfree(void *); +#include <limits.h> +#include <fcntl.h> +struct pollfd { + int fd; + int events; /* in param: what to poll for */ + int revents; /* out param: what events occured */ + }; +int poll (struct pollfd *, int, int); +#endif /* __DJGPP__ */ + #ifndef __cplusplus /* (rabe) */ #ifndef typedef_bool typedef char bool; @@ -2704,6 +2719,16 @@ operate(struct Configurable *config, int argc, char *argv[]) helpf("Remote file name has no length!\n"); return CURLE_WRITE_ERROR; } +#if defined(__DJGPP__) + { + /* This is for DOS, and then we do some major replacing of + bad characters in the file name before using it */ + char *file1=xmalloc(PATH_MAX); + strcpy(file1, msdosify(outfile)); + strcpy(outfile, rename_if_dos_device_name(file1)); + xfree(file1); + } +#endif /* __DJGPP__ */ } else if(urls) { /* fill '#1' ... '#9' terms from URL pattern */ @@ -2877,11 +2902,11 @@ operate(struct Configurable *config, int argc, char *argv[]) if(!config->errors) config->errors = stderr; -#if defined(WIN32) && !defined(__CYGWIN32__) +#ifdef O_BINARY if(!outfile && !(config->conf & CONF_GETTEXT)) { /* We get the output to stdout and we have not got the ASCII/text flag, then set stdout to be binary */ - setmode( 1, O_BINARY ); + setmode( fileno(stdout), O_BINARY ); } #endif @@ -3312,3 +3337,119 @@ static int create_dir_hierarchy(char *outfile) return result; /* 0 is fine, -1 is badness */ } +#ifdef __DJGPP__ +/* The following functions are taken with modification from the DJGPP + * port of tar 1.12. They use algorithms originally from DJTAR. */ + +char * +msdosify (char *file_name) +{ + static char dos_name[PATH_MAX]; + static char illegal_chars_dos[] = ".+, ;=[]|<>\\\":?*"; + static char *illegal_chars_w95 = &illegal_chars_dos[8]; + int idx, dot_idx; + char *s = file_name, *d = dos_name; + char *illegal_aliens = illegal_chars_dos; + size_t len = sizeof (illegal_chars_dos) - 1; + int lfn = 0; + + /* Support for Windows 9X VFAT systems, when available. */ + if (_use_lfn (file_name)) + lfn = 1; + if (lfn) { + illegal_aliens = illegal_chars_w95; + len -= (illegal_chars_w95 - illegal_chars_dos); + } + + /* Get past the drive letter, if any. */ + if (s[0] >= 'A' && s[0] <= 'z' && s[1] == ':') { + *d++ = *s++; + *d++ = *s++; + } + + for (idx = 0, dot_idx = -1; *s; s++, d++) { + if (memchr (illegal_aliens, *s, len)) { + /* Dots are special: DOS doesn't allow them as the leading character, + and a file name cannot have more than a single dot. We leave the + first non-leading dot alone, unless it comes too close to the + beginning of the name: we want sh.lex.c to become sh_lex.c, not + sh.lex-c. */ + if (*s == '.') { + if (idx == 0 && (s[1] == '/' || (s[1] == '.' && s[2] == '/'))) { + /* Copy "./" and "../" verbatim. */ + *d++ = *s++; + if (*s == '.') + *d++ = *s++; + *d = *s; + } + else if (idx == 0) + *d = '_'; + else if (dot_idx >= 0) { + if (dot_idx < 5) { /* 5 is a heuristic ad-hoc'ery */ + d[dot_idx - idx] = '_'; /* replace previous dot */ + *d = '.'; + } + else + *d = '-'; + } + else + *d = '.'; + + if (*s == '.') + dot_idx = idx; + } + else if (*s == '+' && s[1] == '+') { + if (idx - 2 == dot_idx) { /* .c++, .h++ etc. */ + *d++ = 'x'; + *d = 'x'; + } + else { + /* libg++ etc. */ + memcpy (d, "plus", 4); + d += 3; + } + s++; + idx++; + } + else + *d = '_'; + } + else + *d = *s; + if (*s == '/') { + idx = 0; + dot_idx = -1; + } + else + idx++; + } + + *d = '\0'; + return dos_name; +} + +char * +rename_if_dos_device_name (char *file_name) +{ + /* We could have a file whose name is a device on MS-DOS. Trying to + * retrieve such a file would fail at best and wedge us at worst. We need + * to rename such files. */ + extern char *basename (const char *); + char *base; + struct stat st_buf; + char fname[PATH_MAX]; + + strcpy (fname, file_name); + base = basename (fname); + if (((stat(base, &st_buf)) == 0) && (S_ISCHR(st_buf.st_mode))) { + size_t blen = strlen (base); + + /* Prepend a '_'. */ + memmove (base + 1, base, blen + 1); + base[0] = '_'; + strcpy (file_name, fname); + } + return file_name; +} + +#endif /* __DJGPP__ */ |