Skip to content

Commit 4774eaf

Browse files
committed
FIX: better fix of reading list of logical drives on Windows
fixes: Oldes/Rebol-issues#2031
1 parent 94c3622 commit 4774eaf

File tree

5 files changed

+70
-47
lines changed

5 files changed

+70
-47
lines changed

src/core/p-dir.c

+9
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,15 @@
6060

6161
dir->data = (REBYTE*)(&file);
6262

63+
#ifdef TO_WINDOWS
64+
REBCHR *cp = file.file.path;
65+
if (cp[0] == '/' && cp[1] == 0) {
66+
// special case: reading drive letters -> read %/
67+
// https://github.com/Oldes/Rebol-issues/issues/2031
68+
SET_FLAG(dir->modes, RFM_DRIVES);
69+
}
70+
#endif
71+
6372
while ((result = OS_DO_DEVICE(dir, RDC_READ)) == 0 && !GET_FLAG(dir->flags, RRF_DONE)) {
6473
len = (REBCNT)LEN_STR(file.file.path);
6574
if (GET_FLAG(file.modes, RFM_DIR)) len++;

src/core/s-file.c

-7
Original file line numberDiff line numberDiff line change
@@ -143,13 +143,6 @@
143143
out = UNI_HEAD(dst);
144144
#ifdef TO_WINDOWS
145145
i++;
146-
if (len == 1 && !full) {
147-
// special case: reading drive letters -> read %/
148-
// https://github.com/rebol/rebol-issues/issues/2031
149-
out[0] = 0;
150-
SERIES_TAIL(dst) = 0;
151-
return dst;
152-
}
153146
if (i < len) {
154147
c = GET_CHAR_UNI(uni, bp, i);
155148
i++;

src/include/reb-file.h

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ enum {
3838
RFM_RESEEK, // file index has moved, reseek
3939
RFM_NAME_MEM, // converted name allocated in mem
4040
RFM_DIR = 16,
41+
RFM_DRIVES, // used only on Windows to get logical drives letters (read %/)
4142
};
4243

4344
// RFE - REBOL File Error

src/os/win32/dev-file.c

+50-40
Original file line numberDiff line numberDiff line change
@@ -138,50 +138,18 @@ static BOOL Seek_File_64(REBREQ *file)
138138

139139
if (!h) {
140140
file->modes = 0;
141-
if (dir->file.path[0] == 0) {
142-
// Reading drives.. Rebol code: read %/
143-
len = (1 + GetLogicalDriveStrings(0, NULL)) << 1;
144-
h = MAKE_MEM(len);
145-
GetLogicalDriveStrings(len, h);
146-
dir->length = len;
147-
dir->actual = 0;
148-
file->modes = 0;
149-
SET_FLAG(file->modes, RFM_DIR);
150-
} else {
151-
// Read first file entry:
152-
h = FindFirstFile(dir->file.path, &info);
153-
if (h == INVALID_HANDLE_VALUE) {
154-
dir->error = -RFE_OPEN_FAIL;
155-
return DR_ERROR;
156-
}
157-
cp = info.cFileName;
141+
// Read first file entry:
142+
h = FindFirstFile(dir->file.path, &info);
143+
if (h == INVALID_HANDLE_VALUE) {
144+
dir->error = -RFE_OPEN_FAIL;
145+
return DR_ERROR;
158146
}
147+
cp = info.cFileName;
159148
dir->handle = h;
160149
CLR_FLAG(dir->flags, RRF_DONE);
161150
}
162-
163-
if (dir->length > 0) {
164-
// Drive names processing...
165-
cp = (REBCHR*)h + dir->actual;
166-
file->file.path = cp;
167-
if (cp[0] == 0 || dir->length <= dir->actual) {
168-
// end
169-
FREE_MEM(dir->handle);
170-
dir->handle = NULL;
171-
SET_FLAG(dir->flags, RRF_DONE); // no more files
172-
return DR_DONE;
173-
}
174-
while (cp[0] != 0 && dir->length > dir->actual) {
175-
cp++; dir->actual++;
176-
}
177-
cp[-2] = 0; // the names are as: "C:\" but we want just "C", so just terminate the string sooner
178-
dir->actual++; // skip the null after current drive name
179-
return DR_DONE;
180-
}
181-
// regular DIR processing follows...
182151
// Skip over the . and .. dir cases:
183152
while (cp == 0 || (cp[0] == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))) {
184-
185153
// Read next file entry, or error:
186154
if (!FindNextFile(h, &info)) {
187155
dir->error = GetLastError();
@@ -193,7 +161,6 @@ static BOOL Seek_File_64(REBREQ *file)
193161
return DR_DONE;
194162
}
195163
cp = info.cFileName;
196-
197164
}
198165

199166
file->modes = 0;
@@ -204,6 +171,46 @@ static BOOL Seek_File_64(REBREQ *file)
204171
return DR_DONE;
205172
}
206173

174+
/***********************************************************************
175+
**
176+
*/ static int Read_Drives(REBREQ *dir, REBREQ *file)
177+
/*
178+
** Reading list of logical drives.. Rebol code: read %/
179+
**
180+
***********************************************************************/
181+
{
182+
HANDLE h= (HANDLE)(dir->handle);
183+
REBCHR *cp = 0;
184+
REBCNT len;
185+
if (!h) {
186+
len = (1 + GetLogicalDriveStrings(0, NULL)) << 1;
187+
h = MAKE_MEM(len);
188+
GetLogicalDriveStrings(len, h);
189+
dir->length = len;
190+
dir->actual = 0;
191+
dir->handle = h;
192+
file->modes = 0;
193+
CLR_FLAG(dir->flags, RRF_DONE);
194+
}
195+
// Drive names processing...
196+
cp = (REBCHR*)h + dir->actual;
197+
file->file.path = cp;
198+
if (cp[0] == 0 || dir->length <= dir->actual) {
199+
// end
200+
FREE_MEM(dir->handle);
201+
dir->handle = NULL;
202+
SET_FLAG(dir->flags, RRF_DONE); // no more files
203+
return DR_DONE;
204+
}
205+
while (cp[0] != 0 && dir->length > dir->actual) {
206+
cp++; dir->actual++;
207+
}
208+
// the names are as: "C:\" but we want "C/"
209+
cp[-2] = '/';
210+
cp[-1] = 0;
211+
dir->actual++; // skip the null after current drive name
212+
return DR_DONE;
213+
}
207214

208215
/***********************************************************************
209216
**
@@ -314,7 +321,10 @@ static BOOL Seek_File_64(REBREQ *file)
314321
***********************************************************************/
315322
{
316323
if (GET_FLAG(file->modes, RFM_DIR)) {
317-
return Read_Directory(file, (REBREQ*)file->data);
324+
if (!GET_FLAG(file->modes, RFM_DRIVES))
325+
return Read_Directory(file, (REBREQ*)file->data);
326+
else
327+
return Read_Drives(file, (REBREQ*)file->data);
318328
}
319329

320330
if (!file->handle) {

src/tests/units/port-test.r3

+10
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,16 @@ Rebol [
5757
not error? try [delete-dir %units/temp-dir/]
5858
not exists? %units/temp-dir/
5959
]
60+
if system/platform = 'Windows [
61+
--test-- "read %/"
62+
;@@ https://github.com/Oldes/Rebol-issues/issues/2031
63+
--assert all [
64+
block? drives: read %/
65+
not empty? drives
66+
2 = length? drives/1
67+
#"/" = last drives/1
68+
]
69+
]
6070

6171
===end-group===
6272

0 commit comments

Comments
 (0)