diff options
Diffstat (limited to 'Build/source/libs/libgnuw32/volume.c')
-rw-r--r-- | Build/source/libs/libgnuw32/volume.c | 244 |
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; +} |