From f3db99fc8c274391b8918fda4738814182cca403 Mon Sep 17 00:00:00 2001
From: KO Myung-Hun
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
+#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 */
+ 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