X-Git-Url: https://cygwin.com/git/?a=blobdiff_plain;f=install.cc;h=b53c39ca3510d4c5af6cf1583c77a3513adc3605;hb=ab57ceaa5cea4f0b4fab4cea27df76daba3587a7;hp=7b1b4c4c543e0b5524dddcd3eeeb8573398fec49;hpb=f57c332f26e12c5cee592ac560f7afc7e387bdea;p=cygwin-apps%2Fsetup.git diff --git a/install.cc b/install.cc index 7b1b4c4c..b53c39ca 100644 --- a/install.cc +++ b/install.cc @@ -17,16 +17,24 @@ the install list (in ini.h). Note that we use a separate thread to maintain the progress dialog, so we avoid the complexity of handling two tasks in one thread. We also create or update all the - files in /etc/setup/* and create the mount points. */ + files in /etc/setup/\* and create the mount points. */ + +#if 0 +static const char *cvsid = + "\n%%% $Id$\n"; +#endif #include "win32.h" #include "commctrl.h" #include #include +#include #include #include #include +#include + #include "zlib/zlib.h" #include "resource.h" @@ -36,137 +44,63 @@ #include "geturl.h" #include "mkdir.h" #include "state.h" -#include "tar.h" #include "diskfull.h" #include "msg.h" #include "mount.h" +#include "log.h" +#include "mount.h" +#include "filemanip.h" +#include "io_stream.h" +#include "compress.h" +#include "compress_gz.h" +#include "archive.h" +#include "archive_tar.h" + +#include "package_db.h" +#include "package_meta.h" +#include "package_version.h" +#include "package_source.h" -static HWND ins_dialog = 0; -static HWND ins_pkgname = 0; -static HWND ins_filename = 0; -static HWND ins_pprogress = 0; -static HWND ins_iprogress = 0; -static HWND ins_diskfull = 0; -static HANDLE init_event; +#include "port.h" + +#include "threebar.h" +extern ThreeBarProgressPage Progress; static int total_bytes = 0; static int total_bytes_sofar = 0; static int package_bytes = 0; -static BOOL -dialog_cmd (HWND h, int id, HWND hwndctl, UINT code) -{ - switch (id) - { - case IDCANCEL: - ExitProcess(0); - } -} - -static BOOL CALLBACK -dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam) -{ - int i, j; - HWND listbox; - switch (message) - { - case WM_INITDIALOG: - ins_dialog = h; - ins_pkgname = GetDlgItem (h, IDC_INS_PKG); - ins_filename = GetDlgItem (h, IDC_INS_FILE); - ins_pprogress = GetDlgItem (h, IDC_INS_PPROGRESS); - ins_iprogress = GetDlgItem (h, IDC_INS_IPROGRESS); - ins_diskfull = GetDlgItem (h, IDC_INS_DISKFULL); - SetEvent (init_event); - return FALSE; - case WM_COMMAND: - return HANDLE_WM_COMMAND(h, wParam, lParam, dialog_cmd); - } - return FALSE; -} - -static WINAPI DWORD -dialog (void *) -{ - int rv = 0; - MSG m; - HANDLE ins_dialog = CreateDialog (hinstance, MAKEINTRESOURCE (IDD_INSTATUS), - 0, dialog_proc); - if (ins_dialog == 0) - fatal ("create dialog"); - ShowWindow (ins_dialog, SW_SHOWNORMAL); - UpdateWindow (ins_dialog); - while (GetMessage (&m, 0, 0, 0) > 0) { - TranslateMessage (&m); - DispatchMessage (&m); - } -} - -static DWORD start_tics; - static void init_dialog () { - if (ins_dialog == 0) - { - DWORD tid; - HANDLE thread; - init_event = CreateEvent (0, 0, 0, 0); - thread = CreateThread (0, 0, dialog, 0, 0, &tid); - WaitForSingleObject (init_event, 10000); - CloseHandle (init_event); - SendMessage (ins_pprogress, PBM_SETRANGE, 0, MAKELPARAM (0, 100)); - SendMessage (ins_iprogress, PBM_SETRANGE, 0, MAKELPARAM (0, 100)); - SendMessage (ins_diskfull, PBM_SETRANGE, 0, MAKELPARAM (0, 100)); - } - - SetWindowText (ins_pkgname, ""); - SetWindowText (ins_filename, ""); - SendMessage (ins_pprogress, PBM_SETPOS, (WPARAM) 0, 0); - SendMessage (ins_iprogress, PBM_SETPOS, (WPARAM) 0, 0); - SendMessage (ins_diskfull, PBM_SETPOS, (WPARAM) 0, 0); - ShowWindow (ins_dialog, SW_SHOWNORMAL); - SetForegroundWindow (ins_dialog); + Progress.SetText2 (""); + Progress.SetText3 (""); } static void progress (int bytes) { - int perc; - - if (package_bytes > 100) + if (package_bytes > 0) { - perc = bytes / (package_bytes / 100); - SendMessage (ins_pprogress, PBM_SETPOS, (WPARAM) perc, 0); + Progress.SetBar1 (bytes, package_bytes); } - if (total_bytes > 100) + if (total_bytes > 0) { - perc = (total_bytes_sofar + bytes) / (total_bytes / 100); - SendMessage (ins_iprogress, PBM_SETPOS, (WPARAM) perc, 0); + Progress.SetBar2 (total_bytes_sofar + bytes, total_bytes); } - - int df = diskfull (root_dir); - SendMessage (ins_diskfull, PBM_SETPOS, (WPARAM) df, 0); } -static void -badrename (char *o, char *n) -{ - char buf[1000]; - char *err = strerror (errno); - if (!err) - err = "(unknown error)"; - note (IDS_ERR_RENAME, o, n, err); -} - -static char *standard_dirs[] = { +static const char *standard_dirs[] = { "/bin", "/etc", "/lib", "/tmp", + "/usr", "/usr/bin", "/usr/lib", + "/usr/src", + "/usr/local", "/usr/local/bin", "/usr/local/etc", "/usr/local/lib", @@ -176,175 +110,316 @@ static char *standard_dirs[] = { 0 }; -#define pi (package[i].info[package[i].trust]) - -#define LOOP_PACKAGES \ - for (i=0; ierror ()) + { + delete lst; + lst = NULL; + } } - /* Create /var/run/utmp */ - char *utmp = concat (root_dir, "/var/run/utmp", 0); - FILE *ufp = fopen (utmp, "wb"); - if (ufp) - fclose (ufp); - free (utmp); + package_bytes = source.size; - dismiss_url_status_dialog (); + char msg[64]; + strcpy (msg, "Installing"); + Progress.SetText1 (msg); + log (0, "%s%s", msg, source.Cached ()); + io_stream *tmp = io_stream::open (source.Cached (), "rb"); + archive *thefile = 0; + if (tmp) + { + io_stream *tmp2 = compress::decompress (tmp); + if (tmp2) + thefile = archive::extract (tmp2); + else + thefile = archive::extract (tmp); + } + /* FIXME: potential leak of either *tmp or *tmp2 */ + if (thefile) + { + const char *fn; + while ((fn = thefile->next_file_name ())) + { + if (lst) + lst->write (concat (fn, "\n", 0), strlen (fn) + 1); - init_dialog (); + /* FIXME: concat leaks memory */ + Progress.SetText3 (concat (prefix, fn, 0)); + log (LOG_BABBLE, "Installing file %s%s", prefix, fn); + if (archive::extract_file (thefile, prefix) != 0) + { + log (0, "Unable to install file %s%s", prefix, fn); + errors++; + } - total_bytes = 0; - total_bytes_sofar = 0; + progress (tmp->tell ()); + num_installs++; + } + delete thefile; - LOOP_PACKAGES - { - total_bytes += pi.install_size; + total_bytes_sofar += package_bytes; } - LOOP_PACKAGES - { - char *local = pi.install, *cp, *fn, *base; - base = local; - for (cp=pi.install; *cp; cp++) - if (*cp == '/' || *cp == '\\' || *cp == ':') - base = cp+1; - SetWindowText (ins_pkgname, base); + progress (0); - gzFile lst = gzopen (concat (root_dir, "/etc/setup/", - package[i].name, ".lst.gz", 0), - "wb9"); + int df = diskfull (get_root_dir ()); + Progress.SetBar3 (df); - package_bytes = pi.install_size; + if (lst) + delete lst; - tar_open (local); - while (fn = tar_next_file ()) - { - char *dest_file; + return errors; +} - while (*fn == '/' || *fn == '\\') - fn++; +/* install a package, install both the binary and source aspects if needed */ +static int +install_one (packagemeta & pkg) +{ + int errors = 0; - if (lst) - gzprintf(lst, "%s\n", fn); + if (pkg.desired->binpicked) + { + errors += + install_one_source (pkg, pkg.desired->bin, "cygfile:///", + package_binary); + if (!errors) + pkg.installed = pkg.desired; + } + if (pkg.desired->srcpicked) + errors += + install_one_source (pkg, pkg.desired->src, "cygfile:///usr/src", + package_source); + + /* FIXME: make a upgrade method and reinstate this */ +#if 0 + char msg[64]; + if (!pkg->installed) + strcpy (msg, "Installing"); + else + { + int n = strcmp (pi->version, pkg->installed->version); + if (n < 0) + strcpy (msg, "Reverting"); + else if (n == 0) + strcpy (msg, "Reinstalling"); + else + strcpy (msg, "Upgrading"); + } - if (strncmp (fn, "usr/bin/", 8) == 0) - dest_file = concat(root_dir, "/bin/", fn+8, 0); - else if (strncmp (fn, "usr/lib/", 8) == 0) - dest_file = concat(root_dir, "/lib/", fn+8, 0); - else - dest_file = concat(root_dir, "/", fn, 0); + switch (pkg->action) + { + case ACTION_PREV: + strcat (msg, " previous version..."); + break; + case ACTION_CURR: + strcat (msg, "..."); + break; + case ACTION_TEST: + strcat (msg, " test version..."); + break; + default: + /* FIXME: log this somehow */ + break; + } + SetWindowText (ins_action, msg); + log (0, "%s%s", msg, file); +#endif - SetWindowText (ins_filename, dest_file); - tar_read_file (dest_file); + return errors; +} - progress (tar_ftell ()); - num_installs ++; +static void +check_for_old_cygwin () +{ + char buf[_MAX_PATH + sizeof ("\\cygwin1.dll")]; + if (!GetSystemDirectory (buf, sizeof (buf))) + return; + strcat (buf, "\\cygwin1.dll"); + if (_access (buf, 0) != 0) + return; + + char msg[sizeof (buf) + 132]; + sprintf (msg, + "An old version of cygwin1.dll was found here:\r\n%s\r\nDelete?", + buf); + switch (MessageBox + (NULL, msg, "What's that doing there?", + MB_YESNO | MB_ICONQUESTION | MB_TASKMODAL)) + { + case IDYES: + if (!DeleteFile (buf)) + { + sprintf (msg, "Couldn't delete file %s.\r\n" + "Is the DLL in use by another application?\r\n" + "You should delete the old version of cygwin1.dll\r\n" + "at your earliest convenience.", buf); + MessageBox (NULL, buf, "Couldn't delete file", + MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL); } - tar_close (); + break; + default: + break; + } - total_bytes_sofar += pi.install_size; - progress (0); + return; +} - if (lst) - gzclose (lst); - } +static void +do_install_thread (HINSTANCE h, HWND owner) +{ + int i; + int errors = 0; - ShowWindow (ins_dialog, SW_HIDE); + num_installs = 0, num_uninstalls = 0; - if (num_installs == 0) + next_dialog = IDD_DESKTOP; + + mkdir_p (1, get_root_dir ()); + + for (i = 0; standard_dirs[i]; i++) { - exit_msg = IDS_NOTHING_INSTALLED; - return; + char *p = cygpath (standard_dirs[i], 0); + mkdir_p (1, p); + free (p); } - char *odbn = concat (root_dir, "/etc/setup/installed.db", 0); - char *ndbn = concat (root_dir, "/etc/setup/installed.db.new", 0); - char *sdbn = concat (root_dir, "/etc/setup/installed.db.old", 0); + /* Create /var/run/utmp */ + io_stream *utmp = io_stream::open ("cygfile:///var/run/utmp", "wb"); + delete utmp; - mkdir_p (0, ndbn); + init_dialog (); + + total_bytes = 0; + total_bytes_sofar = 0; - FILE *odb = fopen (odbn, "rt"); - FILE *ndb = fopen (ndbn, "wb"); + int df = diskfull (get_root_dir ()); + Progress.SetBar3 (df); + + int istext = (root_text == IDC_ROOT_TEXT) ? 1 : 0; + int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0; - if (!ndb) + create_mount ("/", get_root_dir (), istext, issystem); + create_mount ("/usr/bin", cygpath ("/bin", 0), istext, issystem); + create_mount ("/usr/lib", cygpath ("/lib", 0), istext, issystem); + set_cygdrive_flags (istext, issystem); + + packagedb db; + for (size_t n = 1; n < db.packages.number (); n++) { - char *err = strerror (errno); - if (!err) - err = "(unknown error)"; - fatal (IDS_ERR_OPEN_WRITE, ndb, err); + packagemeta & pkg = *db.packages[n]; + + if (pkg.desired && (pkg.desired->srcpicked || pkg.desired->binpicked)) + { + if (pkg.desired->srcpicked) + total_bytes += pkg.desired->src.size; + if (pkg.desired->binpicked) + total_bytes += pkg.desired->bin.size; + } } - if (odb) + for (size_t n = 1; n < db.packages.number (); n++) { - char line[1000], pkg[1000]; - int printit; - while (fgets (line, 1000, odb)) + packagemeta & pkg = *db.packages[n]; + if (pkg.installed && (!pkg.desired || pkg.desired != pkg.installed)) { - printit = 1; - sscanf(line, "%s", pkg); - LOOP_PACKAGES + uninstall_one (pkg); + } + + if (pkg.desired && (pkg.desired->srcpicked || pkg.desired->binpicked)) + { + int e = 0; + e += install_one (pkg); + if (e) { - if (strcmp (pkg, package[i].name) == 0) - { - printit = 0; - break; - } + errors++; } - if (printit) - fputs (line, ndb); } - + } // end of big package loop + + int temperr; + if ((temperr = db.flush ())) + { + const char *err = strerror (temperr); + if (!err) + err = "(unknown error)"; + fatal (owner, IDS_ERR_OPEN_WRITE, err); } - LOOP_PACKAGES + + if (!errors) + check_for_old_cygwin (); + if (num_installs == 0 && num_uninstalls == 0) { - fprintf (ndb, "%s %s %d\n", package[i].name, - pi.install, pi.install_size); + exit_msg = IDS_NOTHING_INSTALLED; + return; } + if (num_installs == 0) + { + exit_msg = IDS_UNINSTALL_COMPLETE; + return; + } + + if (errors) + exit_msg = IDS_INSTALL_INCOMPLETE; + else + exit_msg = IDS_INSTALL_COMPLETE; +} - if (odb) - fclose (odb); - fclose (ndb); +static void +do_install_reflector (void *p) +{ + HANDLE *context; + context = (HANDLE *) p; - remove (sdbn); - if (odb && rename (odbn, sdbn)) - badrename (odbn, sdbn); + do_install_thread ((HINSTANCE) context[0], (HWND) context[1]); - remove (odbn); - if (rename (ndbn, odbn)) - badrename (ndbn, odbn); + // Tell the progress page that we're done downloading + Progress.PostMessage (WM_APP_INSTALL_THREAD_COMPLETE); - remove_mount ("/"); - remove_mount ("/usr"); - remove_mount ("/usr/bin"); - remove_mount ("/usr/lib"); - remove_mount ("/var"); - remove_mount ("/lib"); - remove_mount ("/bin"); - remove_mount ("/etc"); + _endthread (); +} - int istext = (root_text == IDC_ROOT_TEXT) ? 1 : 0; - int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0; +static HANDLE context[2]; - create_mount ("/", root_dir, istext, issystem); - create_mount ("/usr/bin", concat (root_dir, "/bin", 0), istext, issystem); - create_mount ("/usr/lib", concat (root_dir, "/lib", 0), istext, issystem); +void +do_install (HINSTANCE h, HWND owner) +{ + context[0] = h; + context[1] = owner; - exit_msg = IDS_INSTALL_COMPLETE; + _beginthread (do_install_reflector, 0, context); }