Mailing-List: contact cygwin-developers-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-developers-owner AT cygwin DOT com Delivered-To: mailing list cygwin-developers AT cygwin DOT com Date: Mon, 22 Jul 2002 12:41:57 -0400 From: Jason Tishler Subject: path_conv::check() gets confused by recently removed files To: Cygwin-Developers Mail-followup-to: Cygwin-Developers Message-id: <20020722164156.GI1680@tishler.net> MIME-version: 1.0 Content-type: multipart/mixed; boundary="Boundary_(ID_anaKV4EUkCCb+eZCqXcLMA)" User-Agent: Mutt/1.4i --Boundary_(ID_anaKV4EUkCCb+eZCqXcLMA) Content-type: text/plain; charset=us-ascii Content-transfer-encoding: 7BIT Content-disposition: inline I guess that I found the complement of the following: http://cygwin.com/ml/cygwin-developers/2002-05/msg00008.html while tracking down some regressions with Cygwin Python CVS. :,) The attached test program, j7.cc, demonstrates the problem: $ >file $ j7 file dir The root cause of the problem is that symlink_info::check() ignores the ERROR_ACCESS_DENIED case in the following: fileattr = GetFileAttributes (suffix.path); if (fileattr == INVALID_FILE_ATTRIBUTES) { /* The GetFileAttributes call can fail for reasons that don't matter, so we just return 0. For example, getting the attributes of \\HOST will typically fail. */ debug_printf ("GetFileAttributes (%s) failed", suffix.path); error = geterrno_from_win_error (GetLastError (), EACCES); continue; } The above causes path_conv::check() to the lop off the tail component of the recently deleted file so that path_conv::fileattr incorrectly indicates a directory instead of a file. This in turn, causes fstat() to incorrectly indicate that the file descriptor is a directory instead of a file. Unfortunately, once again I do not know the best way to fix this problem. Should fstat() (and cousins) just return EACCES in this case? BTW, this would fix the Cygwin Python regressions: static PyFileObject* dircheck(PyFileObject* f) { struct stat buf; if (f->f_fp == NULL) return f; if (fstat(fileno(f->f_fp), &buf) == 0 && ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ S_ISDIR(buf.st_mode)) { char *msg = strerror(EISDIR); PyObject *exc = PyObject_CallFunction(PyExc_IOError, ... PyErr_SetObject(PyExc_IOError, exc); return NULL; } return f; } Thanks, Jason --Boundary_(ID_anaKV4EUkCCb+eZCqXcLMA) Content-type: text/plain; charset=us-ascii; NAME=j7.cc Content-transfer-encoding: 7BIT Content-disposition: attachment; filename=j7.cc #include #include #include int main(int argc, char* argv[]) { char* file = argv[1]; FILE* fp = fopen(file, "wb+"); if (!fp) { printf("fopen(%s) failed with errno = %d\n", file, errno); return 1; } int status = remove(file); if (status < 0) { printf("remove(%s) failed with errno = %d\n", file, errno); return 2; } struct stat buf; status = fstat(fileno(fp), &buf); if (status < 0) printf("fstat() failed with errno = %d\n", errno); if (S_ISDIR(buf.st_mode)) printf("dir\n"); else printf("not dir\n"); return 0; } --Boundary_(ID_anaKV4EUkCCb+eZCqXcLMA)--