1 /* Utility and Unix shadow routines for XEmacs on Windows NT.
2 Copyright (C) 1994, 1995 Free Software Foundation, Inc.
4 This file is part of XEmacs.
6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with XEmacs; see the file COPYING. If not, write to the Free
18 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22 Geoff Voelker (voelker@cs.washington.edu) 7-29-94 */
24 /* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */
25 /* Sync'ed with Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */
26 /* Adapted to fpTeX 0.4 by Fabrice Popineau <Fabrice.Popineau@supelec.fr> */
30 #include <kpathsea/config.h>
31 #include <kpathsea/c-proto.h>
32 #include <kpathsea/win32lib.h>
33 #include <kpathsea/lib.h>
35 /* #### This is an evil dirty hack. We must get rid of it.
36 Word "munging" is not in XEmacs lexicon. - kkm */
38 /* Internal MSVC data and functions for low-level descriptor munging */
40 extern char _osfile[];
42 extern int __cdecl _set_osfhnd (int fd, long h);
43 extern int __cdecl _free_osfhnd (int fd);
46 /* parallel array of private info on file handles */
54 /* parallel array of private info on file handles */
55 filedesc fd_info [ MAXDESC ];
58 /* Global referenced by various functions. */
59 volume_info_data volume_info;
61 /* Vector to indicate which drives are local and fixed (for which cached
62 data never expires). */
63 static BOOL fixed_drives[26];
65 /* Consider cached volume information to be stale if older than 10s,
66 at least for non-local drives. Info for fixed drives is never stale. */
67 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
68 #define VOLINFO_STILL_VALID( root_dir, info ) \
69 ( ( isalpha (root_dir[0]) && \
70 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
71 || GetTickCount () - info->timestamp < 10000 )
73 /* Cache support functions. */
75 /* Simple linked list with linear search is sufficient. */
76 static volume_info_data *volume_cache = NULL;
78 static volume_info_data *
79 lookup_volume_info (char * root_dir)
81 volume_info_data * info;
83 for (info = volume_cache; info; info = info->next)
84 if (stricmp (info->root_dir, root_dir) == 0)
90 add_volume_info (char * root_dir, volume_info_data * info)
92 info->root_dir = xstrdup (root_dir);
93 info->next = volume_cache;
98 /* Wrapper for GetVolumeInformation, which uses caching to avoid
99 performance penalty (~2ms on 486 for local drives, 7.5ms for local
100 cdrom drive, ~5-10ms or more for remote drives on LAN). */
102 GetCachedVolumeInformation (char * root_dir)
104 volume_info_data * info;
105 char default_root[ MAX_PATH ];
107 /* NULL for root_dir means use root from current directory. */
108 if (root_dir == NULL)
110 if (GetCurrentDirectory (MAX_PATH, default_root) == 0)
112 _parse_root (default_root, &root_dir);
114 root_dir = default_root;
117 /* Local fixed drives can be cached permanently. Removable drives
118 cannot be cached permanently, since the volume name and serial
119 number (if nothing else) can change. Remote drives should be
120 treated as if they are removable, since there is no sure way to
121 tell whether they are or not. Also, the UNC association of drive
122 letters mapped to remote volumes can be changed at any time (even
123 by other processes) without notice.
125 As a compromise, so we can benefit from caching info for remote
126 volumes, we use a simple expiry mechanism to invalidate cache
127 entries that are more than ten seconds old. */
130 /* No point doing this, because WNetGetConnection is even slower than
131 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
132 GetDriveType is about the only call of this type which does not
133 involve network access, and so is extremely quick). */
135 /* Map drive letter to UNC if remote. */
136 if ( isalpha( root_dir[0] ) && !fixed[ DRIVE_INDEX( root_dir[0] ) ] )
138 char remote_name[ 256 ];
139 char drive[3] = { root_dir[0], ':' };
141 if (WNetGetConnection (drive, remote_name, sizeof (remote_name))
147 info = lookup_volume_info (root_dir);
149 if (info == NULL || ! VOLINFO_STILL_VALID (root_dir, info))
157 /* Info is not cached, or is stale. */
158 if (!GetVolumeInformation (root_dir,
163 type, sizeof (type)))
166 /* Cache the volume information for future use, overwriting existing
170 info = (volume_info_data *) xmalloc (sizeof (volume_info_data));
171 add_volume_info (root_dir, info);
179 info->name = xstrdup (name);
180 info->serialnum = serialnum;
181 info->maxcomp = maxcomp;
183 info->type = xstrdup (type);
184 info->timestamp = GetTickCount ();
190 /* Get information on the volume where name is held; set path pointer to
191 start of pathname in name (past UNC header\volume header if present). */
193 get_volume_info (const char * name, const char ** pPath)
196 char *rootname = NULL; /* default to current volume */
197 volume_info_data * info;
202 /* find the root name of the volume if given */
203 if (isalpha (name[0]) && name[1] == ':')
211 else if (IS_DIR_SEP (name[0]) && IS_DIR_SEP (name[1]))
218 if (IS_DIR_SEP (*name) && --slashes == 0)
231 info = GetCachedVolumeInformation (rootname);
234 /* Set global referenced by other functions. */
241 /* Determine if volume is FAT format (ie. only supports short 8.3
242 names); also set path pointer to start of pathname in name. */
244 is_fat_volume (const char * name, const char ** pPath)
246 if (get_volume_info (name, pPath))
247 return (volume_info.maxcomp == 12);