Web lists-archives.com

Setup.exe: solution to misbehaviour




L.S.,

Setup.exe writes "user defaults" to /etc/setup/setup.rc in the root
directory. Among these user defaults (which should override program
defaults) are "last-action" and "last-cache".

last-cache is an alias for the Local Package Directory (abbreviated
to local directory), the directory where the tarballs (or packages)
will be stored.

When setup.exe starts, one has to choose between "Download to local
directory", "Install fr. local directory" or "Download end Install".

As a reminder, setup.exe will show you the "last-action", i.e. what
action was chosen by you when you last invoked setup.exe.

However "all of the above" is in vain, if setup.exe fails to select
the correct root directory.

Currently, setup.exe fails to honour the -R option, which one uses
to specify a different location for the root directory.

setup.exe also fails to look for /etc/setup/setup.rc in the current
directory when setup.exe is started from the root directory.

I have written about this misbehaviour of setup.exe here:

    https://cygwin.com/ml/cygwin/2019-04/msg00032.html
    ( Setup: why consult registry (rootdir) if -R has been specified? )

Attached (I hope) to this post you will find a corrected version of
the UserSettings::open_settings() method; it determines the location
of the root directory as follows:

 - read /etc/setup/setup.rc from the specified root directory (-R)
   and if file exists
  - insert root directory in mount_table
 - else read /etc/setup/setup.rc from the current directory and if
   file exist
  - insert root directory in mount_table
 - else fall back to the whacky default (rootdir from registry)
   (root directory inserted in mount_table)

Good luck.

Henri
...

// Henri: required
#include "mount.h" // set_root_dir()
#include "getopt++/StringOption.h" // RootOption
extern StringOption RootOption;

...

// Henri: original function replaced by this one (more clear than modifying the existing function)
#if 1
io_stream *
UserSettings::open_settings (const char *filename, std::string &pathname)
{
/*
  Obtain user settings (last-action, last-cache -- aka local directory, last-mirror etc.) from /etc/setup/setup.rc
   - at startup (setup.exe), the root directory may have been specified explicitly (-R) or it may have been specified
     implicitly by starting setup.exe from the root directory, or its value may be present in registry ("rootdir")
   - if all options fail, it will default to either X:\Cygwin64 or X:\Cygwin (where X is the system drive)
   Note:
   - although the value of the root directory can be overruled in the Root Page later on, /etc/setup/setup.rc is read
     at startup from the root directory as explained above
   - however, said value can NOT be overruled in case of "Download to Local directory"
   Algorithm:
   - read /etc/setup/setup.rc from the specified root directory (-R) and if file exists
    - note: the root directory is NOT the Unix root; it is the Windows directory where the Cygwin packages
      have been, or will be installed
   - else read /etc/setup/setup.rc from the current directory and if file exists
    - this makes only sense if the current directory equals the root directory (i.e. this is the directory where
      the file /etc/setup/setup.rc will be written!)
   - else fall back to the whacky default (rootdir from registry)
 */
  io_stream *f = NULL; // Henri
  bool found = false; // Henri

  // Henri: take root directory seriously if explicitly specified (-R) ! ... setup mount_table (mount.cc)
  std::string my_RD;
  if (std::string (RootOption).size ()) {
    my_RD = std::string (RootOption);
    //LogPlainPrintf("UserSettings::open_settings: my_RD = %s\n", my_RD.c_str() );
    pathname = "file://" + my_RD + "/etc/setup/" + filename;
    f = io_stream::open(pathname, "rt", 0);
    //LogPlainPrintf("UserSettings::open_settings: 1. pathname = %s\n", pathname.c_str() );
    if (f) {
        found = true;
        set_root_dir(my_RD); // required in case of download
    }
  }

  // Henri: current directory (should!) equals the root directory ... setup mount_table
  // Henri: this is specifying the root directory implicitly ...
  if (found == false) {
  // Henri:  original code + correction (basically a daft option)
    pathname = "file://";
    pathname += cwd;
    if (!isdirsep (cwd[cwd.size () - 1]) && !isdirsep (filename[0]))
        pathname += "/";
    pathname += "etc/setup/"; // Henri: heck! "etc/setup/" was missing in pathname ...
    pathname += filename;
    //LogPlainPrintf("UserSettings::open_settings: 2. pathname = %s\n", pathname.c_str() );
    f = io_stream::open(pathname, "rt", 0);
    if (f) {
        found = true;
        set_root_dir(cwd); // required in case of download
    }
  }
  
  if (!f) // found == false
    {
      pathname = "cygfile:///etc/setup/";
      pathname += filename;
      //LogPlainPrintf(" *** WARNING *** UserSettings::open_settings: 3. pathname = %s\n", pathname.c_str() );
#if 0
      LogPlainPrintf(" *** WARNING ***\n");
      LogPlainPrintf("     rootdir from registry will be used as the root directory. Defaults will be\n");
      LogPlainPrintf("     obtained from /etc/setup/setup.rc over there.\n");
      LogPlainPrintf("     Defaults will also be written over there, unless another root directory is\n");
      LogPlainPrintf("     chosen later on (Not possible in case of Download to Local Directory).\n");
      LogPlainPrintf(" END WARNING\n");
#endif
      f = io_stream::open (pathname, "rt", 0); // Henri: creates mount_table where / maps to rootdir from registry
    }
  //if (!f) pathname = ""; // Henri: dont lie! (however, lying is prerequisite to keep setup.exe working)
  /*
   - ignore error if file does not exist ...
   - an exception occured if the file did not exist ... however, a non-existing mount-point was fine ... Hark!
    - a null pointer is returned if the file does not exist, while a (valid) pointer is returned in case of a
      non-existing mount-point ...
   - this software is garbage
   */

  return f;
}
#endif // Henri: end replace open_settings

#if 0 // Henri: put out the garbage ...
io_stream *
UserSettings::open_settings (const char *filename, std::string &pathname)
{
  pathname = "file://";
  pathname += cwd;
  if (!isdirsep (cwd[cwd.size () - 1]) && !isdirsep (filename[0]))
    pathname += "/"; // Henri: WRONG: missing "etc/setup/" in pathname!
  pathname += filename;
  io_stream *f = io_stream::open(pathname, "rt", 0);
  if (!f)
    {
      pathname = "cygfile:///etc/setup/";
      pathname += filename;
      f = io_stream::open (pathname, "rt", 0);
    }
  return f; // Henri: no reset of pathname if a null pointer is returned
            // Henri: Oh hell, a (valid) pointer is returned in case of a NON-existing mount-point ...
}
#endif

// Henri: relevance of cwd? As local directory: None! As root directory, only if the current directory equals the root directory
// Henri: why? /etc/setup/setup.rc is eventually written out to /etc/setup/setup.rc in the root directory; by definition the root
// Henri: can be equal to the current directory (start directory of setup.exe), but it does not require that!
// Henri: it is a daft option! And only useful if one wants to escape the dictation by registry.
UserSettings::UserSettings (std::string local_dir) // Henri: basically the start directory (cwd) of setup.exe is provided here
  : table (NULL), table_len (-1), cwd (local_dir)
{
  global = this;
  extend_table (0);
  io_stream *f = open_settings ("setup.rc", filename); // Henri: Jezus C.! This initializes the member variable ... Tada!
...

=====
--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple