From 234074f6834dfd090bc6780ffe667b11d3b7c101 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Sat, 8 Feb 2014 20:57:27 +0000 Subject: [PATCH] * 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. --- winsup/cygwin/ChangeLog | 8 ++++ winsup/cygwin/miscfuncs.cc | 78 +++++++++++++++++++++++++++++++++++- winsup/cygwin/miscfuncs.h | 20 +++++++++- winsup/cygwin/mount.cc | 82 +++----------------------------------- 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 + + * 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 * 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; }