Mailing-List: contact cygwin-developers-help AT sourceware DOT cygnus DOT com; run by ezmlm List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-developers-owner AT sourceware DOT cygnus DOT com Delivered-To: mailing list cygwin-developers AT sourceware DOT cygnus DOT com To: cygwin-developers AT sourceware DOT cygnus DOT com Subject: allow utimes() to set times of a read only file. Mime-Version: 1.0 (generated by tm-edit 7.106) Content-Type: text/plain; charset=US-ASCII From: Kazuhiro Fujieda Date: 25 Sep 1999 05:55:40 +0900 Message-ID: Lines: 182 X-Mailer: Gnus v5.3/Emacs 19.34 The following patch allow utimes() to set access and modification times of a read only file. I tested this patch by `tar', `touch -a', and `touch -m'. `touch' without any options can't work for read only files, because it doesn't use utime() but utime_now() defined in touch.c which set their times by reading and writing their contents. --- times.cc- Tue Aug 24 10:46:25 1999 +++ times.cc Sat Sep 25 03:58:13 1999 @@ -15,6 +15,7 @@ details. */ #include #include #include +#include #include "winsup.h" #define FACTOR (0x19db1ded53ea710LL) @@ -453,20 +454,45 @@ extern "C" int utimes (const char *path, struct timeval *tvp) { - int res = 0; + int res = -1; struct timeval tmp[2]; - path_conv win32 (path); + path_conv win32_path (path); + HANDLE h = INVALID_HANDLE_VALUE; + int unixattr = -1; + DWORD saved_attr; + uid_t saved_uid = 0; + uid_t saved_gid = 0; + + if (win32_path.error) + { + set_errno (win32_path.error); + goto done; + } + /* FIXME: This makes utimes on a device succeed always. */ + if (win32_path.is_device ()) + { + res = 0; + goto done; + } - if (win32.error) + saved_attr = win32_path.file_attributes (); + if (saved_attr == (DWORD)-1) + { + __seterrno (); + goto done; + } + if (saved_attr & FILE_ATTRIBUTE_READONLY && + !SetFileAttributesA (win32_path.get_win32 (), + saved_attr & ~FILE_ATTRIBUTE_READONLY)) { - set_errno (win32.error); - syscall_printf ("-1 = utimes (%s, %x)", path, tvp); - return -1; + __seterrno (); + goto done; } /* MSDN suggests using FILE_FLAG_BACKUP_SEMANTICS for accessing the times of directories. FIXME: what about Win95??? */ - HANDLE h = CreateFileA (win32.get_win32 (), +retry: + h = CreateFileA (win32_path.get_win32 (), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &sec_none_nih, @@ -476,54 +502,71 @@ utimes (const char *path, struct timeval if (h == INVALID_HANDLE_VALUE) { - if ((res = GetFileAttributes (win32.get_win32 ())) != -1 && - (res & FILE_ATTRIBUTE_DIRECTORY)) + if (allow_ntsec && win32_path.has_acls () && + unixattr == -1 && GetLastError () == ERROR_ACCESS_DENIED) { - /* What we can do with directories more? */ - res = 0; + unixattr = 0; + if (get_file_attribute (TRUE, win32_path.get_win32 (), &unixattr)) + { + unixattr = -1; + goto recover; + } + saved_uid = get_file_owner (TRUE, win32_path.get_win32 ()); + saved_gid = get_file_group (TRUE, win32_path.get_win32 ()); + if (set_file_attribute (TRUE, win32_path.get_win32 (), + saved_uid, saved_gid, + unixattr | S_IWUSR)) + { + unixattr = -1; + goto recover; + } + goto retry; } - else + if ((res = GetFileAttributes (win32_path.get_win32 ())) != -1 && + (res & FILE_ATTRIBUTE_DIRECTORY)) { - res = -1; - __seterrno (); + /* What we can do with directories more? */ + res = 0; + goto recover; } + __seterrno (); + goto recover; } - else + if (tvp == 0) { - if (tvp == 0) - { - gettimeofday (&tmp[0], 0); - tmp[1] = tmp[0]; - tvp = tmp; - } + gettimeofday (&tmp[0], 0); + tmp[1] = tmp[0]; + tvp = tmp; + } - FILETIME lastaccess; - FILETIME lastwrite; + FILETIME lastaccess; + FILETIME lastwrite; - timeval_to_filetime (tvp + 0, &lastaccess); - timeval_to_filetime (tvp + 1, &lastwrite); + timeval_to_filetime (tvp + 0, &lastaccess); + timeval_to_filetime (tvp + 1, &lastwrite); - debug_printf ("incoming lastaccess %08x %08x", - tvp->tv_sec, - tvp->tv_usec); + debug_printf ("incoming lastaccess %08x %08x", + tvp->tv_sec, + tvp->tv_usec); // dump_filetime (lastaccess); // dump_filetime (lastwrite); - /* FIXME: SetFileTime needs a handle with a write lock - on the file whose time is being modified. So calls to utime() - fail for read only files. */ + if (!SetFileTime (h, 0, &lastaccess, &lastwrite)) + __seterrno (); + else + res = 0; + CloseHandle (h); - if (!SetFileTime (h, 0, &lastaccess, &lastwrite)) - { - __seterrno (); - res = -1; - } - else - res = 0; - CloseHandle (h); - } +recover: + if (saved_attr & FILE_ATTRIBUTE_READONLY) + SetFileAttributesA (win32_path.get_win32 (), saved_attr); + + if (unixattr != -1) + set_file_attribute (TRUE, win32_path.get_win32 (), + saved_uid, saved_gid, unixattr); +done: syscall_printf ("%d = utimes (%s, %x); (h%d)", res, path, tvp, h); return res; ____ | AIST Kazuhiro Fujieda | HOKURIKU School of Information Science o_/ 1990 Japan Advanced Institute of Science and Technology