KO Myung-Hun wrote:
> On OS/2, there are maximum 26 CWDs, one CWD per drive[A to Z]. So
> it is needed to save and restore all of them as well as a CWD of a
> current drive.
> 
> For examples,
> 
>   1. CWD is C:\CWD
>   2. Call save_cwd()
>   3. Change drive to drive D: whose CWD was D:\
>   4. Change directory to D:\CWD
>   5. Now, CWD is D:\CWD
>   6. Call restore_cwd()
>   7. Now CWD is C:\CWD. But CWD of drive D: is still D:\CWD not D:\.
> 
> * lib/save-cwd.c (save_cwd): Save all CWDs of each drive.
> (restore_cwd): Restore all CWDs of each drive.
> (free_cwd): Free allocated name_with_drvie.
> * lib/save-cwd.h (struct save_cwd): Add current_drive and
> name_with_drive member.

Updated to suppress hard error pop-ups.

-- 
KO Myung-Hun

Using Mozilla SeaMonkey 2.7.2
Under OS/2 Warp 4 for Korean with FixPak #15
In VirtualBox v4.1.32 on Intel Core i7-3615QM 2.30GHz with 8GB RAM

Korean OS/2 User Community : http://www.ecomstation.co.kr

From f3db99fc8c274391b8918fda4738814182cca403 Mon Sep 17 00:00:00 2001
From: KO Myung-Hun <k...@chollian.net>
Date: Tue, 2 Dec 2014 11:45:48 +0900
Subject: [PATCH] save_cwd: save/restore all CWDs of each drive on EMX

On OS/2, there are maximum 26 CWDs, one CWD per drive[A to Z]. So
it is needed to save and restore all of them as well as a CWD of a
current drive.

For examples,

  1. CWD is C:\CWD
  2. Call save_cwd()
  3. Change drive to drive D: whose CWD was D:\
  4. Change directory to D:\CWD
  5. Now, CWD is D:\CWD
  6. Call restore_cwd()
  7. Now CWD is C:\CWD. But CWD of drive D: is still D:\CWD not D:\.

* lib/save-cwd.c (save_cwd): Save all CWDs of each drive.
(restore_cwd): Restore all CWDs of each drive.
(free_cwd): Free allocated name_with_drvie.
* lib/save-cwd.h (struct save_cwd): Add current_drive and
name_with_drive member.
---
 lib/save-cwd.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/save-cwd.h |  4 ++++
 2 files changed, 71 insertions(+)

diff --git a/lib/save-cwd.c b/lib/save-cwd.c
index 7aafacd..5832227 100644
--- a/lib/save-cwd.c
+++ b/lib/save-cwd.c
@@ -38,6 +38,12 @@
 # define GNULIB_FCNTL_SAFER 0
 #endif
 
+#ifdef __EMX__
+# define INCL_DOS
+# define INCL_DOSUNDOCUEMENTED  /* for DosSysCtl() */
+# include <os2.h>
+#endif
+
 /* Record the location of the current working directory in CWD so that
    the program may change to other directories and later use restore_cwd
    to return to the recorded location.  This function may allocate
@@ -62,6 +68,47 @@
 int
 save_cwd (struct saved_cwd *cwd)
 {
+#ifdef __EMX__
+  /* On OS/2, there are maximum 26 CWDs, one CWD per drive[A to Z]. Here save
+     all the CWDs of each drive.  */
+
+  char drive;
+  ULONG saved_dos_error = FERR_ENABLEHARDERR; /* Default value */
+
+  /* Save a current drive.  */
+  cwd->current_drive = _getdrive ();
+
+  /* Undocumented feature. Query current DosError() state.
+     See <http://wiki.netlabs.org/index.php/Query_the_DosError%28%29_state> */
+  DosSysCtl(27, &saved_dos_error);
+
+  /* Disable hard error pop-ups.  */
+  DosError(FERR_DISABLEHARDERR);
+
+  /* Save CWD with a drive name of each drive.  */
+  for (drive = 0; drive <= 'Z' - 'A'; drive++)
+    {
+      /* _chdrive() always returns 0.  */
+      _chdrive (drive + 'A');
+
+      /* Ignore ENOENT due to empty removable drives such as CD-ROM.  */
+      if (!(cwd->name_with_drive[drive] = _getcwd2 (NULL, 0))
+          && errno == ENOMEM)
+        {
+          while (drive-- > 0)
+            free (cwd->name_with_drive[drive]);
+
+          return -1;
+        }
+    }
+
+  /* Restore DosError() state.  */
+  DosError(saved_dos_error);
+
+  /* Restore a current drive.  */
+  _chdrive (cwd->current_drive);
+#endif
+
   cwd->name = NULL;
 
   cwd->desc = open (".", O_SEARCH);
@@ -84,6 +131,19 @@ save_cwd (struct saved_cwd *cwd)
 int
 restore_cwd (const struct saved_cwd *cwd)
 {
+#ifdef __EMX__
+  char drive;
+
+  /* Restore CWD of each drive.  */
+  for (drive = 0; drive <= 'Z' - 'A'; drive++)
+    if (cwd->name_with_drive[drive])
+      if (chdir_long (cwd->name_with_drive[drive]))
+        return -1;
+
+  /* Restore a current drive.  */
+  _chdrive (cwd->current_drive);
+#endif
+
   if (0 <= cwd->desc)
     return fchdir (cwd->desc);
   else
@@ -93,6 +153,13 @@ restore_cwd (const struct saved_cwd *cwd)
 void
 free_cwd (struct saved_cwd *cwd)
 {
+#ifdef __EMX__
+  char drive;
+
+  for (drive = 0; drive <= 'Z' - 'A'; drive++)
+    free (cwd->name_with_drive[drive]);
+#endif
+
   if (cwd->desc >= 0)
     close (cwd->desc);
   free (cwd->name);
diff --git a/lib/save-cwd.h b/lib/save-cwd.h
index 6b84e46..492772f 100644
--- a/lib/save-cwd.h
+++ b/lib/save-cwd.h
@@ -25,6 +25,10 @@ struct saved_cwd
   {
     int desc;
     char *name;
+# ifdef __EMX__
+    char current_drive;
+    char *name_with_drive['Z' - 'A' + 1]; /* for drive A to Z */
+# endif
   };
 
 int save_cwd (struct saved_cwd *cwd);
-- 
1.8.5.2

Reply via email to