diff options
Diffstat (limited to 'winsup/cygwin/mount.cc')
-rw-r--r-- | winsup/cygwin/mount.cc | 82 |
1 files changed, 77 insertions, 5 deletions
diff --git a/winsup/cygwin/mount.cc b/winsup/cygwin/mount.cc index eecd72692..43f462686 100644 --- a/winsup/cygwin/mount.cc +++ b/winsup/cygwin/mount.cc @@ -1177,9 +1177,10 @@ mount_info::from_fstab (bool user, WCHAR fstab[], PWCHAR fstab_end) { UNICODE_STRING upath; OBJECT_ATTRIBUTES attr; - NT_readline rl; + IO_STATUS_BLOCK io; + NTSTATUS status; + HANDLE fh; tmp_pathbuf tp; - char *buf = tp.c_get (); if (user) { @@ -1194,10 +1195,81 @@ mount_info::from_fstab (bool user, WCHAR fstab[], PWCHAR fstab_end) RtlInitUnicodeString (&upath, fstab); InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE, NULL, NULL); debug_printf ("Try to read mounts from %W", fstab); - if (rl.init (&attr, buf, NT_MAX_PATH)) - while ((buf = rl.gets ())) - if (!from_fstab_line (buf, user)) + status = NtOpenFile (&fh, SYNCHRONIZE | FILE_READ_DATA, &attr, &io, + FILE_SHARE_VALID_FLAGS, + FILE_SYNCHRONOUS_IO_NONALERT + | FILE_OPEN_FOR_BACKUP_INTENT); + if (!NT_SUCCESS (status)) + { + debug_printf ("NtOpenFile(%S) failed, %y", &upath, status); + return false; + } + + char *buf = tp.c_get (); + char *got = buf; + DWORD len = 0; + unsigned line = 1; + /* Using buffer size - 2 leaves space to append two \0. */ + while (NT_SUCCESS (NtReadFile (fh, NULL, NULL, NULL, &io, got, + (NT_MAX_PATH - 2) - (got - buf), NULL, NULL))) + { + char *end; + + len = io.Information; + /* Set end marker. */ + got[len] = got[len + 1] = '\0'; + /* Set len to the absolute len of bytes in buf. */ + len += got - buf; + /* Reset got to start reading at the start of the buffer again. */ + got = buf; +retry: + bool got_nl = false; + while (got < buf + len && (end = strchr (got, '\n'))) + { + got_nl = true; + end[end[-1] == '\r' ? -1 : 0] = '\0'; + if (!from_fstab_line (got, user)) + goto done; + got = end + 1; + ++line; + } + if (len < (NT_MAX_PATH - 2)) break; + /* Check if the buffer contained at least one \n. If not, the + line length is > 32K. We don't take such long lines. Print + a debug message and skip this line entirely. */ + if (!got_nl) + { + system_printf ("%W: Line %d too long, skipping...", fstab, line); + while (NT_SUCCESS (NtReadFile (fh, NULL, NULL, NULL, &io, buf, + (NT_MAX_PATH - 2), NULL, NULL))) + { + len = io.Information; + buf[len] = buf[len + 1] = '\0'; + got = strchr (buf, '\n'); + if (got) + { + ++got; + ++line; + goto retry; + } + } + got = buf; + break; + } + /* We have to read once more. Move remaining bytes to the start of + the buffer and reposition got so that it points to the end of + the remaining bytes. */ + len = buf + len - got; + memmove (buf, got, len); + got = buf + len; + buf[len] = buf[len + 1] = '\0'; + } + /* Catch a last line without trailing \n. */ + if (got > buf) + from_fstab_line (got, user); +done: + NtClose (fh); return true; } |