aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGeoff Voelker1996-01-21 00:31:34 +0000
committerGeoff Voelker1996-01-21 00:31:34 +0000
commit00b3b7b3ae95a8c044ca548209a18732c2a19d27 (patch)
tree41e16a53f5bca1524ca8e2252216341a2e2d3375 /src
parentdaf3806631cc516b09c804b156610a0d722314fe (diff)
downloademacs-00b3b7b3ae95a8c044ca548209a18732c2a19d27.tar.gz
emacs-00b3b7b3ae95a8c044ca548209a18732c2a19d27.zip
(nt_stat): Use alloca instead of xmalloc.
(get_unassigned_drive_letter, is_toplevel_share_name, stat_toplevel_share): New functions for stat on remote shares. (readdir): Use IS_ANY_SEP.
Diffstat (limited to 'src')
-rw-r--r--src/w32.c121
1 files changed, 112 insertions, 9 deletions
diff --git a/src/w32.c b/src/w32.c
index 600d308aacd..36c11cc9abb 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -21,30 +21,37 @@ Boston, MA 02111-1307, USA.
21 Geoff Voelker (voelker@cs.washington.edu) 7-29-94 21 Geoff Voelker (voelker@cs.washington.edu) 7-29-94
22*/ 22*/
23 23
24
24/* Define stat before including config.h. */ 25/* Define stat before including config.h. */
25#include <string.h> 26#include <string.h>
26#include <sys/stat.h> 27#include <sys/stat.h>
28#include <malloc.h>
29
30static int is_toplevel_share_name (char *);
31static int stat_toplevel_share (char *, void *);
32
27int 33int
28nt_stat (char *filename, struct stat *statbuf) 34nt_stat (char *filename, struct stat *statbuf)
29{ 35{
30 int r, l = strlen (filename); 36 int l = strlen (filename);
31 char *str = NULL; 37 char *str = NULL;
32 extern long *xmalloc ();
33 extern void xfree ();
34 38
35 /* stat has a bug when passed a name of a directory with a trailing 39 /* stat has a bug when passed a name of a directory with a trailing
36 backslash (but a trailing forward slash works fine). */ 40 backslash (but a trailing forward slash works fine). */
37 if (filename[l - 1] == '\\') 41 if (filename[l - 1] == '\\')
38 { 42 {
39 str = (char *) xmalloc (l + 1); 43 str = (char *) alloca (l + 1);
40 strcpy (str, filename); 44 strcpy (str, filename);
41 str[l - 1] = '/'; 45 str[l - 1] = '/';
42 r = stat (str, statbuf); 46 return stat (str, statbuf);
43 xfree (str);
44 return r;
45 } 47 }
48
49 if (stat (filename, statbuf) == 0)
50 return 0;
51 else if (is_toplevel_share_name (filename))
52 return stat_toplevel_share (filename, statbuf);
46 else 53 else
47 return stat (filename, statbuf); 54 return -1;
48} 55}
49 56
50/* Place a wrapper around the NT version of ctime. It returns NULL 57/* Place a wrapper around the NT version of ctime. It returns NULL
@@ -76,6 +83,102 @@ nt_ctime (const time_t *t)
76 83
77extern int report_file_error (char *, Lisp_Object); 84extern int report_file_error (char *, Lisp_Object);
78 85
86/* Routines for extending stat above. */
87static int
88get_unassigned_drive_letter ()
89{
90 int i;
91 unsigned int mask;
92
93 mask = GetLogicalDrives ();
94 for (i = 0; i < 26; i++)
95 {
96 if (mask & (1 << i))
97 continue;
98 break;
99 }
100 return (i == 26 ? -1 : 'A' + i);
101}
102
103void dostounix_filename (char *);
104
105/* Return nonzero if NAME is of the form \\host\share (forward slashes
106 also valid), otherwise return 0. */
107static int
108is_toplevel_share_name (char *filename)
109{
110 int len;
111 char *name;
112 char *host;
113 char *share;
114 char *suffix;
115
116 len = strlen (filename);
117 name = alloca (len + 1);
118 strcpy (name, filename);
119
120 dostounix_filename (name);
121 if (name[0] != '/' || name[1] != '/')
122 return 0;
123
124 host = strtok (&name[2], "/");
125 share = strtok (NULL, "/");
126 suffix = strtok (NULL, "/");
127 if (!host || !share || suffix)
128 return 0;
129
130 return 1;
131}
132
133
134/* FILENAME is of the form \\host\share, and stat can't handle names
135 of this form. But stat can handle \\host\share if it's been
136 assigned a drive letter. So we create a network connection to this
137 share, assign it a drive letter, stat the drive letter, and
138 disconnect from the share. Hassle... */
139static int
140stat_toplevel_share (char *filename, void *statbuf)
141{
142 NETRESOURCE net;
143 int drive_letter;
144 char drive[4];
145 int result;
146
147 drive_letter = get_unassigned_drive_letter ();
148 if (drive_letter < 0)
149 return -1;
150
151 drive[0] = drive_letter;
152 drive[1] = ':';
153 drive[2] = '\0';
154 net.dwType = RESOURCETYPE_DISK;
155 net.lpLocalName = drive;
156 net.lpRemoteName = filename;
157 net.lpProvider = NULL;
158
159 switch (WNetAddConnection2 (&net, NULL, NULL, 0))
160 {
161 case NO_ERROR:
162 break;
163 case ERROR_ALREADY_ASSIGNED:
164 default:
165 return -1;
166 }
167
168 /* Name the toplevel directory on the drive letter. */
169 drive[2] = '/';
170 drive[3] = '\0';
171 result = stat (drive, (void *) statbuf);
172
173 /* Strip the slash so we can disconnect. */
174 drive[2] = '\0';
175 if (WNetCancelConnection2 (drive, 0, TRUE) != NO_ERROR)
176 result = -1;
177
178 return result;
179}
180
181
79/* Get the current working directory. */ 182/* Get the current working directory. */
80int 183int
81getwd (char *dir) 184getwd (char *dir)
@@ -173,7 +276,7 @@ readdir (DIR *dirp)
173 276
174 strncpy (filename, dirp->dd_buf, MAXNAMLEN); 277 strncpy (filename, dirp->dd_buf, MAXNAMLEN);
175 ln = strlen (filename)-1; 278 ln = strlen (filename)-1;
176 if (filename[ln] != '\\' && filename[ln] != ':') 279 if (!IS_ANY_SEP (filename[ln]))
177 strcat (filename, "\\"); 280 strcat (filename, "\\");
178 strcat (filename, "*.*"); 281 strcat (filename, "*.*");
179 282