summaryrefslogtreecommitdiff
path: root/Build/source/libs/libgnuw32/volume.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/libgnuw32/volume.c')
-rw-r--r--Build/source/libs/libgnuw32/volume.c244
1 files changed, 244 insertions, 0 deletions
diff --git a/Build/source/libs/libgnuw32/volume.c b/Build/source/libs/libgnuw32/volume.c
new file mode 100644
index 00000000000..ad5e35dbc44
--- /dev/null
+++ b/Build/source/libs/libgnuw32/volume.c
@@ -0,0 +1,244 @@
+/* Utility and Unix shadow routines for XEmacs on Windows NT.
+ Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of XEmacs.
+
+XEmacs is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+XEmacs is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with XEmacs; see the file COPYING. If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+
+
+ Geoff Voelker (voelker@cs.washington.edu) 7-29-94 */
+
+/* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */
+/* Sync'ed with Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */
+/* Adapted to fpTeX 0.4 by Fabrice Popineau <Fabrice.Popineau@supelec.fr> */
+
+#include <win32lib.h>
+
+/* #### This is an evil dirty hack. We must get rid of it.
+ Word "munging" is not in XEmacs lexicon. - kkm */
+
+/* Internal MSVC data and functions for low-level descriptor munging */
+#if (_MSC_VER == 900)
+extern char _osfile[];
+#endif
+extern int __cdecl _set_osfhnd (int fd, long h);
+extern int __cdecl _free_osfhnd (int fd);
+
+#if 0
+/* parallel array of private info on file handles */
+typedef struct
+{
+ unsigned flags;
+ HANDLE hnd;
+ child_process * cp;
+} filedesc;
+
+/* parallel array of private info on file handles */
+filedesc fd_info [ MAXDESC ];
+#endif
+
+/* Global referenced by various functions. */
+volume_info_data volume_info;
+
+/* Vector to indicate which drives are local and fixed (for which cached
+ data never expires). */
+static BOOL fixed_drives[26];
+
+/* Consider cached volume information to be stale if older than 10s,
+ at least for non-local drives. Info for fixed drives is never stale. */
+#define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
+#define VOLINFO_STILL_VALID( root_dir, info ) \
+ ( ( isalpha (root_dir[0]) && \
+ fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
+ || GetTickCount () - info->timestamp < 10000 )
+
+/* Cache support functions. */
+
+/* Simple linked list with linear search is sufficient. */
+static volume_info_data *volume_cache = NULL;
+
+static volume_info_data *
+lookup_volume_info (char * root_dir)
+{
+ volume_info_data * info;
+
+ for (info = volume_cache; info; info = info->next)
+ if (stricmp (info->root_dir, root_dir) == 0)
+ break;
+ return info;
+}
+
+static void
+add_volume_info (char * root_dir, volume_info_data * info)
+{
+ info->root_dir = xstrdup (root_dir);
+ info->next = volume_cache;
+ volume_cache = info;
+}
+
+
+/* Wrapper for GetVolumeInformation, which uses caching to avoid
+ performance penalty (~2ms on 486 for local drives, 7.5ms for local
+ cdrom drive, ~5-10ms or more for remote drives on LAN). */
+volume_info_data *
+GetCachedVolumeInformation (char * root_dir)
+{
+ volume_info_data * info;
+ char default_root[ MAX_PATH ];
+
+ /* NULL for root_dir means use root from current directory. */
+ if (root_dir == NULL)
+ {
+ if (GetCurrentDirectory (MAX_PATH, default_root) == 0)
+ return NULL;
+ _parse_root (default_root, &root_dir);
+ *root_dir = 0;
+ root_dir = default_root;
+ }
+
+ /* Local fixed drives can be cached permanently. Removable drives
+ cannot be cached permanently, since the volume name and serial
+ number (if nothing else) can change. Remote drives should be
+ treated as if they are removable, since there is no sure way to
+ tell whether they are or not. Also, the UNC association of drive
+ letters mapped to remote volumes can be changed at any time (even
+ by other processes) without notice.
+
+ As a compromise, so we can benefit from caching info for remote
+ volumes, we use a simple expiry mechanism to invalidate cache
+ entries that are more than ten seconds old. */
+
+#if 0
+ /* No point doing this, because WNetGetConnection is even slower than
+ GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
+ GetDriveType is about the only call of this type which does not
+ involve network access, and so is extremely quick). */
+
+ /* Map drive letter to UNC if remote. */
+ if ( isalpha( root_dir[0] ) && !fixed[ DRIVE_INDEX( root_dir[0] ) ] )
+ {
+ char remote_name[ 256 ];
+ char drive[3] = { root_dir[0], ':' };
+
+ if (WNetGetConnection (drive, remote_name, sizeof (remote_name))
+ == NO_ERROR)
+ /* do something */ ;
+ }
+#endif
+
+ info = lookup_volume_info (root_dir);
+
+ if (info == NULL || ! VOLINFO_STILL_VALID (root_dir, info))
+ {
+ char name[ 256 ];
+ DWORD serialnum;
+ DWORD maxcomp;
+ DWORD flags;
+ char type[ 256 ];
+
+ /* Info is not cached, or is stale. */
+ if (!GetVolumeInformation (root_dir,
+ name, sizeof (name),
+ &serialnum,
+ &maxcomp,
+ &flags,
+ type, sizeof (type)))
+ return NULL;
+
+ /* Cache the volume information for future use, overwriting existing
+ entry if present. */
+ if (info == NULL)
+ {
+ info = (volume_info_data *) xmalloc (sizeof (volume_info_data));
+ add_volume_info (root_dir, info);
+ }
+ else
+ {
+ free (info->name);
+ free (info->type);
+ }
+
+ info->name = xstrdup (name);
+ info->serialnum = serialnum;
+ info->maxcomp = maxcomp;
+ info->flags = flags;
+ info->type = xstrdup (type);
+ info->timestamp = GetTickCount ();
+ }
+
+ return info;
+}
+
+/* Get information on the volume where name is held; set path pointer to
+ start of pathname in name (past UNC header\volume header if present). */
+int
+get_volume_info (const char * name, const char ** pPath)
+{
+ char temp[MAX_PATH];
+ char *rootname = NULL; /* default to current volume */
+ volume_info_data * info;
+
+ if (name == NULL)
+ return FALSE;
+
+ /* find the root name of the volume if given */
+ if (isalpha (name[0]) && name[1] == ':')
+ {
+ rootname = temp;
+ temp[0] = *name++;
+ temp[1] = *name++;
+ temp[2] = '\\';
+ temp[3] = 0;
+ }
+ else if (IS_DIR_SEP (name[0]) && IS_DIR_SEP (name[1]))
+ {
+ char *str = temp;
+ int slashes = 4;
+ rootname = temp;
+ do
+ {
+ if (IS_DIR_SEP (*name) && --slashes == 0)
+ break;
+ *str++ = *name++;
+ }
+ while ( *name );
+
+ *str++ = '\\';
+ *str = 0;
+ }
+
+ if (pPath)
+ *pPath = name;
+
+ info = GetCachedVolumeInformation (rootname);
+ if (info != NULL)
+ {
+ /* Set global referenced by other functions. */
+ volume_info = *info;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* Determine if volume is FAT format (ie. only supports short 8.3
+ names); also set path pointer to start of pathname in name. */
+int
+is_fat_volume (const char * name, const char ** pPath)
+{
+ if (get_volume_info (name, pPath))
+ return (volume_info.maxcomp == 12);
+ return FALSE;
+}