summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/ChangeLog8
-rw-r--r--winsup/cygwin/miscfuncs.cc78
-rw-r--r--winsup/cygwin/miscfuncs.h20
-rw-r--r--winsup/cygwin/mount.cc82
4 files changed, 109 insertions, 79 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index d2e188499..415051420 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,11 @@
+2014-02-08 Corinna Vinschen <corinna@vinschen.de>
+
+ * miscfuncs.h (class NT_readline): New class to implement line-wise
+ reading from file using native NT functions.
+ * miscfuncs.cc (NT_readline::init): New method.
+ * mount.cc (mount_info::from_fstab): Utilize NT_readline to read
+ fstab files.
+
2014-02-06 Corinna Vinschen <corinna@vinschen.de>
* fhandler_disk_file.cc (fhandler_disk_file::fchown): Fix typo in
diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc
index b2da91846..241819460 100644
--- a/winsup/cygwin/miscfuncs.cc
+++ b/winsup/cygwin/miscfuncs.cc
@@ -1,7 +1,7 @@
/* miscfuncs.cc: misc funcs that don't belong anywhere else
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
- 2007, 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc.
+ 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
This file is part of Cygwin.
@@ -384,6 +384,82 @@ WritePipeOverlapped (HANDLE h, LPCVOID buf, DWORD len, LPDWORD ret_len,
return ret;
}
+bool
+NT_readline::init (POBJECT_ATTRIBUTES attr, PCHAR in_buf, ULONG in_buflen)
+{
+ NTSTATUS status;
+ IO_STATUS_BLOCK io;
+
+ 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))
+ {
+ paranoid_printf ("NtOpenFile(%S) failed, status %y",
+ &attr->ObjectName, status);
+ return false;
+ }
+ buf = in_buf;
+ buflen = in_buflen;
+ got = end = buf;
+ len = 0;
+ line = 1;
+ return true;
+}
+
+PCHAR
+NT_readline::gets ()
+{
+ IO_STATUS_BLOCK io;
+
+ while (true)
+ {
+ /* len == 0 indicates we have to read from the file. */
+ if (!len)
+ {
+ if (!NT_SUCCESS (NtReadFile (fh, NULL, NULL, NULL, &io, got,
+ (buflen - 2) - (got - buf), NULL, NULL)))
+ return NULL;
+ 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 = end = buf;
+ }
+ else
+ {
+ got = end + 1;
+ ++line;
+ }
+ /* Still some valid full line? */
+ if (got < buf + len)
+ {
+ if ((end = strchr (got, '\n')))
+ {
+ end[end[-1] == '\r' ? -1 : 0] = '\0';
+ return got;
+ }
+ /* Last line missing a \n at EOF? */
+ if (len < buflen - 2)
+ {
+ len = 0;
+ return got;
+ }
+ }
+ /* 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';
+ len = 0;
+ }
+}
+
/* backslashify: Convert all forward slashes in src path to back slashes
in dst path. Add a trailing slash to dst when trailing_slash_p arg
is set to 1. */
diff --git a/winsup/cygwin/miscfuncs.h b/winsup/cygwin/miscfuncs.h
index bc36a1987..66dfc900a 100644
--- a/winsup/cygwin/miscfuncs.h
+++ b/winsup/cygwin/miscfuncs.h
@@ -1,7 +1,7 @@
/* miscfuncs.h: main Cygwin header file.
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
- 2007, 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc.
+ 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
This file is part of Cygwin.
@@ -23,6 +23,24 @@ BOOL WINAPI ReadPipeOverlapped (HANDLE h, PVOID buf, DWORD len,
BOOL WINAPI WritePipeOverlapped (HANDLE h, LPCVOID buf, DWORD len,
LPDWORD ret_len, DWORD timeout);
+/* class for per-line reading using native functions. The caller provides
+ the file as an POBJECT_ATTRIBUTES, and the buffer space. */
+class NT_readline
+{
+ HANDLE fh;
+ PCHAR buf;
+ PCHAR got;
+ PCHAR end;
+ ULONG buflen;
+ ULONG len;
+ ULONG line;
+public:
+ NT_readline () : fh (NULL) {}
+ bool init (POBJECT_ATTRIBUTES attr, char *buf, ULONG buflen);
+ PCHAR gets ();
+ ~NT_readline () { if (fh) NtClose (fh); }
+};
+
extern "C" void yield ();
#define import_address(x) __import_address ((void *)(x))
diff --git a/winsup/cygwin/mount.cc b/winsup/cygwin/mount.cc
index 4abc77e68..60ccdd505 100644
--- a/winsup/cygwin/mount.cc
+++ b/winsup/cygwin/mount.cc
@@ -1177,10 +1177,9 @@ mount_info::from_fstab (bool user, WCHAR fstab[], PWCHAR fstab_end)
{
UNICODE_STRING upath;
OBJECT_ATTRIBUTES attr;
- IO_STATUS_BLOCK io;
- NTSTATUS status;
- HANDLE fh;
+ NT_readline rl;
tmp_pathbuf tp;
+ char *buf = tp.c_get ();
if (user)
{
@@ -1195,81 +1194,10 @@ 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);
- 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))
+ if (rl.init (&attr, buf, NT_MAX_PATH))
+ while ((buf = rl.gets ()))
+ if (!from_fstab_line (buf, user))
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;
}