From patchwork Mon Oct 25 14:45:29 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnaud Charlet X-Patchwork-Id: 69104 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 6CD52B70A8 for ; Tue, 26 Oct 2010 01:45:43 +1100 (EST) Received: (qmail 19966 invoked by alias); 25 Oct 2010 14:45:38 -0000 Received: (qmail 19957 invoked by uid 22791); 25 Oct 2010 14:45:37 -0000 X-SWARE-Spam-Status: No, hits=-1.5 required=5.0 tests=AWL, BAYES_00, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mel.act-europe.fr (HELO mel.act-europe.fr) (194.98.77.210) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 25 Oct 2010 14:45:31 +0000 Received: from localhost (localhost [127.0.0.1]) by filtered-smtp.eu.adacore.com (Postfix) with ESMTP id 485F8CB02A4; Mon, 25 Oct 2010 16:45:29 +0200 (CEST) Received: from mel.act-europe.fr ([127.0.0.1]) by localhost (smtp.eu.adacore.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id OZZRM8DYhXPK; Mon, 25 Oct 2010 16:45:29 +0200 (CEST) Received: from saumur.act-europe.fr (saumur.act-europe.fr [10.10.0.183]) by mel.act-europe.fr (Postfix) with ESMTP id 2C2F9CB0263; Mon, 25 Oct 2010 16:45:29 +0200 (CEST) Received: by saumur.act-europe.fr (Postfix, from userid 525) id 0D1D8D9BB5; Mon, 25 Oct 2010 16:45:29 +0200 (CEST) Date: Mon, 25 Oct 2010 16:45:29 +0200 From: Arnaud Charlet To: gcc-patches@gcc.gnu.org Cc: Pascal Obry Subject: [Ada] Improve __gnat_stat() on windows Message-ID: <20101025144529.GA14254@adacore.com> Mime-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.9i X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org The stat() routine is slow (compared to say GNU/Linux) on Windows. This patch implements stat() using the GetFileAttributesEx() which is a bit faster. The main benefit is that we can remove some stat() bug workaround put in place. The first clean-up is in the __gnat_stat() routine itself where we do not need to check for directory separators nor for Windows UNC path. The GetFileAttributesEx() routine properly cover those cases. Manually tested on i686-pc-mingw32, Tested on x86_64-pc-linux-gnu, committed on trunk 2010-10-25 Pascal Obry * adaint.c (__gnat_stat_to_attr): Can set the timestamp on Windows now. (f2t): New routine. (__gnat_stat): Rewrite Win32 version. Index: adaint.c =================================================================== --- adaint.c (revision 165916) +++ adaint.c (working copy) @@ -1112,8 +1112,6 @@ __gnat_stat_to_attr (int fd, char* name, attr->executable = (!ret && (statbuf.st_mode & S_IXUSR)); #endif -#if !defined (_WIN32) || defined (RTX) - /* on Windows requires extra system call, see __gnat_file_time_name_attr */ if (ret != 0) { attr->timestamp = (OS_Time)-1; } else { @@ -1124,8 +1122,6 @@ __gnat_stat_to_attr (int fd, char* name, attr->timestamp = (OS_Time)statbuf.st_mtime; #endif } -#endif - } /**************************************************************** @@ -1345,6 +1341,19 @@ win32_filetime (HANDLE h) return (time_t) (t_write.ull_time / 10000000ULL - w32_epoch_offset); return (time_t) 0; } + +/* As above but starting from a FILETIME. */ +static void f2t (const FILETIME *ft, time_t *t) +{ + union + { + FILETIME ft_time; + unsigned long long ull_time; + } t_write; + + t_write.ft_time = *ft; + *t = (time_t) (t_write.ull_time / 10000000ULL - w32_epoch_offset); +} #endif /* Return a GNAT time stamp given a file name. */ @@ -1687,15 +1696,10 @@ int __gnat_stat (char *name, GNAT_STRUCT_STAT *statbuf) { #ifdef __MINGW32__ - /* Under Windows the directory name for the stat function must not be - terminated by a directory separator except if just after a drive name - or with UNC path without directory (only the name of the shared - resource), for example: \\computer\share\ */ - + WIN32_FILE_ATTRIBUTE_DATA fad; TCHAR wname [GNAT_MAX_PATH_LEN + 2]; - int name_len, k; - TCHAR last_char; - int dirsep_count = 0; + int name_len; + BOOL res; S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2); name_len = _tcslen (wname); @@ -1703,29 +1707,43 @@ __gnat_stat (char *name, GNAT_STRUCT_STA if (name_len > GNAT_MAX_PATH_LEN) return -1; - last_char = wname[name_len - 1]; + ZeroMemory (statbuf, sizeof(GNAT_STRUCT_STAT)); - while (name_len > 1 && (last_char == _T('\\') || last_char == _T('/'))) - { - wname[name_len - 1] = _T('\0'); - name_len--; - last_char = wname[name_len - 1]; - } + res = GetFileAttributesEx (wname, GetFileExInfoStandard, &fad); - /* Count back-slashes. */ + if (res == FALSE) + switch (GetLastError()) { + case ERROR_ACCESS_DENIED: + case ERROR_SHARING_VIOLATION: + case ERROR_LOCK_VIOLATION: + case ERROR_SHARING_BUFFER_EXCEEDED: + return EACCES; + case ERROR_BUFFER_OVERFLOW: + return ENAMETOOLONG; + case ERROR_NOT_ENOUGH_MEMORY: + return ENOMEM; + default: + return ENOENT; + } + + f2t (&fad.ftCreationTime, &statbuf->st_ctime); + f2t (&fad.ftLastWriteTime, &statbuf->st_mtime); + f2t (&fad.ftLastAccessTime, &statbuf->st_atime); - for (k=0; kst_size = (off_t)fad.nFileSizeLow; - /* Only a drive letter followed by ':', we must add a directory separator - for the stat routine to work properly. */ - if ((name_len == 2 && wname[1] == _T(':')) - || (name_len > 3 && wname[0] == _T('\\') && wname[1] == _T('\\') - && dirsep_count == 3)) - _tcscat (wname, _T("\\")); + /* We do not have the S_IEXEC attribute, but this is not used on GNAT. */ + statbuf->st_mode = S_IREAD; - return _tstat (wname, (struct _stat *)statbuf); + if (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + statbuf->st_mode |= S_IFDIR; + else + statbuf->st_mode |= S_IFREG; + + if (!(fad.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) + statbuf->st_mode |= S_IWRITE; + + return 0; #else return GNAT_STAT (name, statbuf);