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