2 * Copyright (c) 2000, Red Hat, Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * A copy of the GNU General Public License can be found at
12 * Written by Ron Parker <parkerrd@hotmail.com>
29 #include <sys/types.h>
35 #include "zlib/zlib.h"
37 #define CYGNUS_KEY "Software\\Cygnus Solutions"
38 #define DEF_ROOT "C:\\cygwin"
39 #define DOWNLOAD_SUBDIR "latest/"
40 #define SCREEN_LINES 25
41 #define COMMAND9X "command.com /E:4096 /c "
44 #define NFILE_LIST 10000
54 static int downloaddir (const char *url
);
56 static SA files
= {NULL
, 0, 0};
57 static FILE *logfp
= NULL
;
58 static HANDLE devnull
= NULL
;
59 static HINTERNET session
= NULL
;
62 warning (const char *fmt
, ...)
66 vfprintf (stderr
, fmt
, args
);
68 vfprintf (logfp
, fmt
, args
);
72 create_shortcut (const char *target
, const char *shortcut
)
78 if (!SUCCEEDED (CoInitialize (NULL
)))
82 CoCreateInstance (&CLSID_ShellLink
, NULL
,
83 CLSCTX_INPROC_SERVER
, &IID_IShellLink
, (LPVOID
*) & sl
);
90 /* Get the command only. */
91 path
= xstrdup (target
);
92 for (c
= path
; quoted
|| (*c
!= ' ' && *c
); ++c
)
105 sl
->lpVtbl
->SetPath (sl
, path
);
106 sl
->lpVtbl
->SetArguments (sl
, args
);
109 hres
= sl
->lpVtbl
->QueryInterface (sl
, &IID_IPersistFile
, &pf
);
111 if (SUCCEEDED (hres
))
113 WCHAR widepath
[_MAX_PATH
];
115 // Ensure that the string is Unicode.
116 MultiByteToWideChar (CP_ACP
, 0, shortcut
, -1, widepath
, MAX_PATH
);
118 // Save the link by calling IPersistFile::Save.
119 hres
= pf
->lpVtbl
->Save (pf
, widepath
, TRUE
);
120 pf
->lpVtbl
->Release (pf
);
122 sl
->lpVtbl
->Release (sl
);
127 return SUCCEEDED (hres
);
132 output_file (HMODULE h
, LPCTSTR type
, LPTSTR name
, LONG lparam
)
141 if ((rsrc
= FindResource (NULL
, name
, "FILE"))
142 && (res
= LoadResource (NULL
, rsrc
))
143 && (data
= (char *) LockResource (res
)) && (out
= fopen (strlwr (name
), "w+b")))
147 size_t bytes
= SizeofResource (NULL
, rsrc
);
149 if (bytes
!= fwrite (data
, 1, bytes
, out
))
150 warning ("Unable to write %s: %s", name
, _strerror (""));
152 bytes_needed
= *(int *) ((char *) data
+ bytes
- sizeof (int));
153 buffer
= (char *) xmalloc (bytes_needed
);
156 gzf
= gzdopen (_dup (fileno (out
)), "rb");
157 if (gzf
&& (size_t) gzread (gzf
, buffer
, bytes_needed
) == bytes_needed
)
160 if (fseek (out
, 0, SEEK_SET
)
161 || fwrite (buffer
, 1, bytes_needed
, out
) != bytes_needed
)
163 warning ("Unable to write decompressed file to %s: %s",
164 name
, _strerror (""));
172 const char *msg
= gzerror (gzf
, &errnum
);
173 warning ("bytes_needed = %d, ", bytes_needed
);
174 warning ("Unable to decompress %s: Error #%d, %s\n", name
,
182 warning ("Unable to write %s: %s", name
, _strerror (""));
189 xumount (const char *mountexedir
, const char *unixpath
)
191 char *umount
= pathcat (mountexedir
, "umount");
194 sprintf (buffer
, "%s %s", umount
, unixpath
);
195 (void) xcreate_process (1, NULL
, devnull
, devnull
, buffer
);
200 tarx (const char *dir
, const char *fn
)
204 char *buffer
= buffer0
+ 1;
210 dpath
= pathcat (dir
, fn
);
211 path
= dtoupath (dpath
);
212 sprintf (buffer
, "%s xvfUz \"%s\"", tarpgm
, path
);
216 printf ("Installing %s\n", fn
);
218 if (_pipe (hpipe
, 256, O_TEXT
) == -1)
221 hin
= (HANDLE
) _get_osfhandle (hpipe
[1]);
222 if (xcreate_process (0, NULL
, hin
, hin
, buffer
) == 0)
224 warning ("Unable to extract \"%s\": %s", fn
, _strerror (""));
228 fp
= fdopen (hpipe
[0], "rt");
230 filehere
= files
.index
;
231 while (fgets (buffer
, sizeof (buffer0
), fp
))
233 char *s
= strchr (buffer
, '\n');
238 if (strchr (buffer
, ':') != NULL
)
241 fprintf (stderr
, "%s\n", s
);
246 if (++files
.index
>= files
.count
)
247 files
.array
= realloc (files
.array
,
248 NFILE_SLOP
+ (files
.count
+= NFILE_LIST
));
252 #if 0 /* too simplistic */
253 e
= strchr (s
, '\0') - 1;
254 if (e
> s
&& *e
== '/')
261 s
= files
.array
[files
.index
] = utodpath (s
);
264 fprintf (logfp
, "%s\n", s
);
268 while (++filehere
<= files
.index
)
269 if (chmod (files
.array
[filehere
], 0777))
270 warning ("Unable to reset protection on '%s' - %s\n",
271 files
.array
[filehere
], _strerror (""));
277 recurse_dirs (const char *dir
)
282 char *pattern
= pathcat (dir
, "*");
285 WIN32_FIND_DATA find_data
;
288 handle
= FindFirstFile (pattern
, &find_data
);
289 if (handle
!= INVALID_HANDLE_VALUE
)
291 /* Recurse through all subdirectories */
294 if (strcmp (find_data
.cFileName
, ".") == 0
295 || strcmp (find_data
.cFileName
, "..") == 0)
298 if (find_data
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
299 /* && strlen(find_data.cFileName) */ )
301 char *subdir
= pathcat (dir
, find_data
.cFileName
);
304 if (!recurse_dirs (subdir
))
317 while (FindNextFile (handle
, &find_data
) && !err
);
320 /* Look for .tar.gz files */
324 pattern
= pathcat (dir
, "*.tar.gz");
325 handle
= FindFirstFile (pattern
, &find_data
);
326 if (handle
!= INVALID_HANDLE_VALUE
)
332 /* Skip source archives and meta-directories */
333 if (strstr (find_data
.cFileName
, "-src.tar.gz")
334 || strstr (find_data
.cFileName
, "-src-")
335 || strcmp (find_data
.cFileName
, ".") == 0
336 || strcmp (find_data
.cFileName
, "..") == 0)
341 if (!tarx (dir
, find_data
.cFileName
))
347 while (FindNextFile (handle
, &find_data
));
365 setpath (const char *element
)
367 char *buffer
= xmalloc (strlen (element
) + 7);
369 sprintf (buffer
, "PATH=%s", element
);
376 prompt (const char *text
, const char *def
)
378 char buffer
[_MAX_PATH
];
381 printf ((def
? "%s? [%s] " : "%s? "), text
, def
);
382 fgets (buffer
, sizeof (buffer
), stdin
);
383 buffer
[strcspn (buffer
, "\r\n")] = '\0';
385 /* Duplicate the entered value or the default if nothing was entered. */
386 return xstrdup (strlen (buffer
) ? buffer
: def
? def
: "");
390 optionprompt (const char *text
, SA
* options
)
392 size_t n
, lbound
, response
;
402 { CONTINUE
, REPEAT
, ALL
}
408 for (n
= 0; n
< base
+ SCREEN_LINES
- 2 && n
< options
->count
; ++n
)
409 printf ("\t%d. %s\n", n
+ 1, options
->array
[n
]);
411 lbound
= n
- (SCREEN_LINES
- (base
? 2 : 3));
412 if (n
< options
->count
)
415 or = " or [continue]";
417 else if (options
->count
> SCREEN_LINES
- 2)
427 printf ("Select an option from %d-%d%s: ", lbound
, n
, or);
428 if (!fgets (buf
, sizeof (buf
), stdin
))
431 if (mode
== CONTINUE
&& (!isalnum (*buf
) || strchr ("cC", *buf
)))
433 else if (mode
== REPEAT
&& (!isalnum (*buf
) || strchr ("rR", *buf
)))
439 response
= atoi (buf
);
441 while (response
< lbound
|| response
> n
);
447 geturl (const char *url
, const char *file
, int verbose
)
450 int authenticated
= 0;
452 static HINTERNET connect
;
454 int is_ftp
= strnicmp (url
, "ftp", 3) == 0;
455 static int saw_first_ftp
= 0;
456 char connect_buffer
[sizeof ("Connecting to http site... ")];
465 p
= strchr (url
, ':');
470 sprintf (connect_buffer
, "Connecting to %.*s%ssite...", n
, url
, n
? " " : "");
471 fputs (connect_buffer
, stdout
);
477 for (tries
= 1; tries
<= 40; tries
++)
479 DWORD flags
= INTERNET_FLAG_DONT_CACHE
|
480 INTERNET_FLAG_KEEP_CONNECTION
|
481 INTERNET_FLAG_PRAGMA_NOCACHE
|
482 INTERNET_FLAG_RELOAD
;
485 flags
|= INTERNET_FLAG_EXISTING_CONNECT
|
486 INTERNET_FLAG_PASSIVE
;
488 connect
= InternetOpenUrl (session
, url
, NULL
, 0, flags
, 0);
491 if (!verbose
|| tries
== 1)
494 printf ("\r%s(try %d) \b\b", connect_buffer
, tries
);
496 printf ("\r%s(try %d)", connect_buffer
, tries
);
501 puts ("\nCouldn't connect to ftp site."); fflush (stdout
);
509 printf ("\r%s \b\b\b\b\b\b\b\b", connect_buffer
);
510 printf ("Done.\n"); fflush (stdout
);
512 while (!authenticated
)
514 size
= sizeof (type
);
515 if (!InternetQueryOption
516 (connect
, INTERNET_OPTION_HANDLE_TYPE
, &type
, &size
))
524 case INTERNET_HANDLE_TYPE_HTTP_REQUEST
:
525 case INTERNET_HANDLE_TYPE_CONNECT_HTTP
:
526 size
= sizeof (DWORD
);
528 (connect
, HTTP_QUERY_STATUS_CODE
| HTTP_QUERY_FLAG_NUMBER
,
534 else if (type
== HTTP_STATUS_PROXY_AUTH_REQ
)
538 if (!InternetQueryDataAvailable (connect
, &len
, 0, 0))
545 char *user
, *password
;
547 /* Have to read any pending data, WININET peculiarity. */
548 char *buffer
= xmalloc (len
);
551 InternetReadFile (connect
, buffer
, len
, &size
);
556 puts ("Proxy authentication is required.\n");
558 user
= prompt ("Proxy username", NULL
);
559 if (!InternetSetOption
560 (connect
, INTERNET_OPTION_PROXY_USERNAME
, user
,
570 password
= prompt ("Proxy password", NULL
);
571 if (!InternetSetOption
572 (connect
, INTERNET_OPTION_PROXY_PASSWORD
,
575 || !HttpSendRequest (connect
, NULL
, 0, NULL
, 0))
585 else if (type
!= HTTP_STATUS_OK
)
587 warning ("Error retrieving \"%s\".\n", url
);
599 /* Now that authentication is complete read the file. */
600 if (!InternetQueryDataAvailable (connect
, &size
, 0, 0))
604 char *buffer
= xmalloc (size
);
606 FILE *out
= fopen (file
, "wb");
608 warning ("Unable to open \"%s\" for output: %s\n", file
,
616 if (!InternetReadFile (connect
, buffer
, size
, &readbytes
))
623 else if (fwrite (buffer
, 1, readbytes
, out
) != readbytes
)
625 warning ("Error writing \"%s\": %s\n", file
,
637 InternetCloseHandle (connect
);
647 findhref (char *buffer
, char *date
, size_t *filesize
)
653 while ((p
= strchr (p
, '<')) != NULL
)
658 if (tolower (ch
) != 'a')
665 for (++p
; isspace (*p
); p
++)
668 if (strnicmp (p
, "href=", 5) == 0)
680 char *diglast
= digits
+ sizeof (digits
) - 1;
683 ref
+= ref
[5] == '"' ? 6 : 5;
685 len
= strcspn (ref
, "\" >");
693 if (anchor
== buffer
|| !isspace (anchor
[-1]))
698 for (p
= anchor
, q
= diglast
; --p
>= buffer
; )
709 *filesize
= atoi (q
);
716 needfile (const char *filename
, char *date
, size_t filesize
)
720 if (!filesize
|| _stat (filename
, &st
))
721 return 1; /* file doesn't exist or is somehow not accessible */
722 return st
.st_size
!= filesize
;
726 processdirlisting (const char *urlbase
, const char *file
)
730 static enum {UNKNOWN
, ALWAYS
, NEVER
} download_when
= {UNKNOWN
};
732 FILE *in
= fopen (file
, "rt");
734 while (fgets (buffer
, sizeof (buffer
), in
))
738 char *ref
= findhref (buffer
[0] ? buffer
: buffer
+ 1, filedate
, &filesize
);
740 DWORD urlspace
= sizeof (url
);
743 if (!ref
|| strnicmp (ref
, "http:", 5) == 0)
746 if (!InternetCombineUrl
747 (urlbase
, ref
, url
, &urlspace
,
748 ICU_BROWSER_MODE
| ICU_ENCODE_SPACES_ONLY
| ICU_NO_META
))
750 warning ("Unable to download from %s", ref
);
753 else if (ref
[strlen (ref
) - 1] == '/')
755 if (strcmp (url
+ strlen (url
) - 2, "./") != 0)
758 else if (strstr (url
, ".tar.gz") && !strstr (url
, "-src"))
761 char *filename
= strrchr (url
, '/') + 1;
762 if (download_when
== ALWAYS
|| needfile (filename
, filedate
, filesize
))
766 char text
[_MAX_PATH
];
769 if (download_when
== NEVER
)
770 answer
= xstrdup ("N");
773 sprintf (text
, "Replace %s from the Internet (ynAN)", filename
);
774 answer
= prompt (text
, "y");
783 download_when
= ALWAYS
;
784 /* purposely fall through */
790 download_when
= NEVER
;
791 warning ("Skipping %s\n", filename
);
803 for (;;) /* file retrieval loop */
806 warning ("Downloading: %s...", filename
);
808 res
= geturl (url
, filename
, 0);
809 if ((res
&& !filesize
) || !needfile (filename
, filedate
, filesize
))
813 for (;;) /* prompt loop */
818 warning ("Download failed.\n");
820 fprintf (logfp
, "Downloaded file size does not match (%ld).\n",
822 answer
= prompt (res
? "Downloaded file size does not match (Abort, Retry, Fail)" :
823 "Download failed (Abort, Retry, Fail)", "R");
824 a
= toupper (*answer
);
829 break; /* try it again */
831 exit (1); /* abort program */
833 warning ("Deleting %s.\n", filename
);
835 goto noget
; /* Keep trying to download the rest */
837 continue; /* erroneous response */
840 break; /* from prompt loop */
845 break; /* Leave from file retrieval for loop.
846 Either we successfully downloaded the file
847 or the user said don't bother. */
863 return _tempnam (NULL
, "su");
867 downloaddir (const char *url
)
870 char *file
= tmpfilename ();
872 if (geturl (url
, file
, 1))
874 retval
= processdirlisting (url
, file
);
886 return InternetOpen ("Cygwin Setup", INTERNET_OPEN_TYPE_PRECONFIG
, NULL
,
891 downloadfrom (const char *url
)
894 char *file
= tmpfilename ();
896 if (geturl (url
, file
, 1))
898 retval
= processdirlisting (url
, file
);
908 reverse_sort (const void *arg1
, const void *arg2
)
910 return -strcmp (*(char **) arg1
, *(char **) arg2
);
914 create_uninstall (const char *wd
, const char *folder
, const char *shellscut
,
915 const char *shortcut
)
918 char buffer
[MAX_PATH
];
922 warning ("Creating the uninstall file...");
931 getcwd (cwd
, sizeof (cwd
));
932 uninstfile
= pathcat (cwd
, "uninst.bat");
933 uninst
= fopen (uninstfile
, "wt");
937 unsigned percent
= 0;
940 files
.array
[++files
.index
] = pathcat (cwd
, "bin\\cygwin.bat");
941 files
.count
= files
.index
+ 1;
942 qsort (files
.array
, files
.count
, sizeof (char *), reverse_sort
);
945 "@echo off\n" "%c:\n" "cd \"%s\"\n", *cwd
, cwd
);
946 for (n
= 0; n
< files
.count
; ++n
)
950 if (n
&& !strcmp (files
.array
[n
], files
.array
[n
- 1]))
953 dpath
= files
.array
[n
];
955 if (_stat (dpath
, &st
) == 0 && st
.st_mode
& _S_IFDIR
)
956 fprintf (uninst
, "rmdir \"%s\"\n", dpath
);
959 if (access (dpath
, 6) != 0)
960 fprintf (uninst
, "attrib -r \"%s\"\n", dpath
);
961 fprintf (uninst
, "del \"%s\"\n", dpath
);
968 "del %s\n", shortcut
, shellscut
,
972 create_shortcut (uninstfile
, shortcut
);
986 /* Writes the startup batch file. */
988 do_start_menu (const char *root
)
991 char *batch_name
= pathcat (root
, "bin\\cygwin.bat");
994 /* Create the batch file for the start menu. */
997 batch
= fopen (batch_name
, "wt");
1000 LPITEMIDLIST progfiles
;
1001 char pfilespath
[_MAX_PATH
];
1006 "SET MAKE_MODE=unix\n"
1007 "SET PATH=%s\\bin;%s\\usr\\local\\bin;%%PATH%%\n"
1008 "bash\n", root
, root
);
1011 /* Create a shortcut to the batch file */
1012 SHGetSpecialFolderLocation (NULL
, CSIDL_PROGRAMS
, &progfiles
);
1013 SHGetPathFromIDList (progfiles
, pfilespath
);
1015 folder
= pathcat (pfilespath
, "Cygnus Solutions");
1019 mkdir (folder
); /* Ignore the result, it may exist. */
1021 shortcut
= pathcat (folder
, "Cygwin 1.1.0.lnk");
1025 OSVERSIONINFO verinfo
;
1026 verinfo
.dwOSVersionInfoSize
= sizeof (verinfo
);
1028 /* If we are running Win9x, build a command line. */
1029 GetVersionEx (&verinfo
);
1030 if (verinfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
1031 cmdline
= xstrdup (batch_name
);
1035 char windir
[MAX_PATH
];
1036 GetWindowsDirectory (windir
, sizeof (windir
));
1038 pccmd
= pathcat (windir
, COMMAND9X
);
1040 xmalloc (strlen (pccmd
) + strlen (batch_name
) + 1);
1041 strcat (strcpy (cmdline
, pccmd
), batch_name
);
1045 if (create_shortcut (cmdline
, shortcut
))
1048 pathcat (folder
, "Uninstall Cygwin 1.1.0.lnk");
1051 if (create_uninstall
1052 (wd
, folder
, shortcut
, uninstscut
))
1070 getdownloadsource ()
1072 char *retval
= NULL
;
1073 char *filename
= tmpfilename ();
1075 /* Initialize session one time and one time only */
1076 session
= opensession ();
1084 if (!geturl ("http://sourceware.cygnus.com/cygwin/mirrors.html",
1086 fputs ("Unable to retrieve the list of cygwin mirrors.\n", stderr
);
1089 FILE *in
= fopen (filename
, "rt");
1092 warning ("Unable to open %s for input.\n", filename
);
1098 SA urls
, names
; /* These must stay sync'd. */
1103 while (fgets (buf
, sizeof (buf
), in
))
1107 if (strstr (buf
, "Mirror Sites:"))
1112 char *ref
= findhref (buf
, NULL
, NULL
);
1116 size_t len
= strlen (ref
);
1118 if (ref
[len
- 1] == '/')
1121 char *url
= xmalloc (len
+ 13);
1123 strcat (strcpy (url
, ref
), DOWNLOAD_SUBDIR
);
1124 sa_add (&urls
, url
);
1126 /* Get just the sites name. */
1127 name
= strstr (url
, "//");
1132 *strchr (name
, '/') = '\0';
1133 sa_add (&names
, url
);
1141 sa_add (&urls
, "Other");
1142 sa_add (&names
, "Other");
1144 optionprompt ("Select a download location close to you:", &names
);
1145 if (option
== urls
.count
- 1)
1146 retval
= prompt ("Download url", NULL
);
1148 retval
= xstrdup (urls
.array
[option
]);
1151 sa_cleanup (&names
);
1160 /* Basically a mkdir -p /somedir function. */
1162 mkdirp (const char *dir
)
1164 if (mkdir (dir
) == -1 && errno
!= EEXIST
)
1166 char *parent
= strdup (dir
);
1167 char *slash
= strrchr (parent
, '\\');
1181 /* This routine assumes that the cwd is the root directory. */
1183 mkmount (const char *mountexedir
, const char *root
, const char *dospath
,
1184 const char *unixpath
, int force
)
1186 char *mount
, *bslashed
, *fulldospath
, *p
;
1190 fulldospath
= xstrdup (dospath
);
1193 xumount (mountexedir
, unixpath
);
1194 /* Make sure the mount point exists. */
1195 mount
= utodpath (unixpath
);
1198 fulldospath
= pathcat (root
, dospath
);
1201 /* Make sure the target path exists. */
1202 mkdirp (fulldospath
);
1204 /* Mount the directory. */
1205 mount
= pathcat (mountexedir
, "mount");
1206 sprintf (buffer
, "%s %s -b \"%s\" %s", mount
, force
? "-f" : "",
1207 fulldospath
, unixpath
);
1209 xfree (fulldospath
);
1211 return xcreate_process (1, NULL
, NULL
, NULL
, buffer
) != 0;
1214 static char rev
[] = "$Revision$ ";
1219 int retval
= 1; /* Default to error code */
1221 char *logpath
= NULL
;
1223 int fd
= _open ("nul", _O_WRONLY
| _O_BINARY
);
1225 devnull
= (HANDLE
) _get_osfhandle (fd
);
1227 setbuf (stdout
, NULL
);
1228 SetEnvironmentVariable ("CYGWIN", NULL
);
1229 revn
= strchr (rev
, ':');
1230 if (!revn
|| (p
= strchr (revn
+ 2, ' ')) == NULL
)
1235 memcpy (revn
, " (v", 3);
1241 "This is the Cygwin setup utility%s,\n"
1242 "built on " __DATE__
" " __TIME__
".\n\n"
1243 "Use this program to install the latest version of the Cygwin Utilities\n"
1244 "from the Internet.\n\n"
1245 "Alternatively, if you already have already downloaded the appropriate files\n"
1246 "to the current directory (and subdirectories below it), this program can use
1247 those as the basis for your installation.\n\n"
1248 "If you are installing from the Internet, please run this program in an empty\n"
1249 "temporary directory.\n\n", revn
);
1252 if (!EnumResourceNames (NULL
, "FILE", output_file
, 0))
1258 char *defroot
, *update
;
1261 HKEY cu
= NULL
, lm
= NULL
;
1263 wd
= _getcwd (NULL
, 0);
1266 logpath
= pathcat (wd
, "setup.log");
1267 tarpgm
= pathcat (wd
, "tar.exe");
1270 logfp
= fopen (logpath
, "wt");
1274 fprintf (stderr
, "Unable to open log file '%s' for writing - %s\n",
1275 logpath
, _strerror (""));
1279 /* Begin prompting user for setup requirements. */
1280 printf ("Press <enter> to accept the default value.\n");
1282 /* If some Cygnus software has been installed, assume there is a root
1283 mount in the registry. Otherwise use C:\cygwin for the default root
1285 if (RegOpenKey (HKEY_CURRENT_USER
, CYGNUS_KEY
, &cu
) == ERROR_SUCCESS
1286 || RegOpenKey (HKEY_LOCAL_MACHINE
, CYGNUS_KEY
,
1287 &lm
) == ERROR_SUCCESS
)
1289 defroot
= utodpath ("/");
1296 defroot
= xstrdup (DEF_ROOT
);
1298 /* Get the root directory and warn the user if there are any spaces in
1300 for (done
= 0; !done
;)
1302 root
= prompt ("Root directory", defroot
);
1303 if (strcmpi (root
, wd
) == 0)
1305 printf ("Please do not use the current directory as the root directory.\n"
1306 "You should run setup.exe from a temporary directory.\n");
1309 if (strchr (root
, ' '))
1314 ("Using spaces in the root directory path may cause problems."
1315 " Continue anyway", "no");
1316 if (toupper (*temp
) == 'Y')
1325 /* Create the root directory. */
1326 mkdir (root
); /* Ignore any return value since it may
1328 mkmount (wd
, "", root
, "/", 1);
1331 prompt ("Install from the current directory (d) or from the Internet (i)", "i");
1332 if (toupper (*update
) == 'I')
1334 char *dir
= getdownloadsource ();
1338 fprintf (stderr
, "Couldn't connect to download site.\n");
1343 InternetCloseHandle (session
);
1348 /* Make the root directory the current directory so that recurse_dirs
1349 will * extract the packages into the correct path. */
1350 if (chdir (root
) == -1)
1352 warning ("Unable to make \"%s\" the current directory: %s\n",
1353 root
, _strerror (""));
1359 _chdrive (toupper (*root
) - 'A' + 1);
1361 xumount (wd
, "/usr");
1362 xumount (wd
, "/var");
1363 xumount (wd
, "/lib");
1364 xumount (wd
, "/bin");
1366 /* Make /bin point to /usr/bin and /lib point to /usr/lib. */
1367 mkmount (wd
, root
, "bin", "/usr/bin", 1);
1368 mkmount (wd
, root
, "lib", "/usr/lib", 1);
1370 mkdirp ("var\\run");
1371 /* Create /var/run/utmp */
1372 fp
= fopen ("var\\run\\utmp", "wb");
1376 files
.count
= NFILE_LIST
;
1377 files
.array
= calloc (sizeof (char *), NFILE_LIST
+ NFILE_SLOP
);
1380 /* Extract all of the packages that are stored with setup or in
1381 subdirectories of its location */
1382 if (recurse_dirs (wd
))
1387 /* Mount the new root directory. */
1388 mount
= pathcat (wd
, "mount");
1389 sprintf (buffer
, "%s -f -b \"%s\" /", mount
, root
);
1391 if (xsystem (buffer
))
1394 ("Unable to mount \"%s\" as the root directory: %s",
1395 root
, _strerror (""));
1400 /* bash expects a /tmp */
1401 char *tmpdir
= pathcat (root
, "tmp");
1405 files
.array
[++files
.index
] = tmpdir
;
1406 mkdir (tmpdir
); /* Ignore the result, it may
1410 files
.array
[++files
.index
] = pathcat (root
, "usr\\local");
1411 files
.array
[++files
.index
] = pathcat (root
, "usr\\local\\bin");
1412 files
.array
[++files
.index
] = pathcat (root
, "usr\\local\\lib");
1413 files
.array
[++files
.index
] = pathcat (root
, "usr\\local\\etc");
1414 mkdirp (files
.array
[files
.index
]);
1415 mkdir (files
.array
[files
.index
- 1]);
1417 if (do_start_menu (root
))
1418 retval
= 0; /* Everything worked return
1427 _chdrive (toupper (*wd
) - 'A' + 1);
1431 printf ("\nInstallation took %.0f seconds.\n",
1432 (double) (clock () - start
) / CLK_TCK
);