diff options
| author | Geoff Voelker | 1996-01-21 00:31:34 +0000 |
|---|---|---|
| committer | Geoff Voelker | 1996-01-21 00:31:34 +0000 |
| commit | 00b3b7b3ae95a8c044ca548209a18732c2a19d27 (patch) | |
| tree | 41e16a53f5bca1524ca8e2252216341a2e2d3375 /src | |
| parent | daf3806631cc516b09c804b156610a0d722314fe (diff) | |
| download | emacs-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.c | 121 |
1 files changed, 112 insertions, 9 deletions
| @@ -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 | |||
| 30 | static int is_toplevel_share_name (char *); | ||
| 31 | static int stat_toplevel_share (char *, void *); | ||
| 32 | |||
| 27 | int | 33 | int |
| 28 | nt_stat (char *filename, struct stat *statbuf) | 34 | nt_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 | ||
| 77 | extern int report_file_error (char *, Lisp_Object); | 84 | extern int report_file_error (char *, Lisp_Object); |
| 78 | 85 | ||
| 86 | /* Routines for extending stat above. */ | ||
| 87 | static int | ||
| 88 | get_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 | |||
| 103 | void dostounix_filename (char *); | ||
| 104 | |||
| 105 | /* Return nonzero if NAME is of the form \\host\share (forward slashes | ||
| 106 | also valid), otherwise return 0. */ | ||
| 107 | static int | ||
| 108 | is_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... */ | ||
| 139 | static int | ||
| 140 | stat_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. */ |
| 80 | int | 183 | int |
| 81 | getwd (char *dir) | 184 | getwd (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 | ||