On Tue, 22 Jan 2019 11:39:28, Corinna Vinschen wrote: > > On Jan 22 11:20, Houder wrote: > > On Tue, 22 Jan 2019 10:41:57, Corinna Vinschen wrote: > > > On Jan 22 10:25, Houder wrote: > > [snip] > > > > > > Curious! It fails (for me) on W7 ... > > > > > > It works for me just as well on W7: [snip]
> Maybe you should run the above shell session under strace and see if > something unusual crops up. BLODA? NO BLODA. Ok, for the record (as this is W7, i.e. pre-pre-W10 :-) Using my original STC again: (source code included below) - create file (in /tmp) write-only, write "Hello, world!" to file, close fd - open file once more read-only - unlink file - open file, using /dev/fd/N, read-write <==== succeeds (and the handle shown by fcntl is read-write) - write "*****" to file (using the fd obtained in the previous line), lseek to begin of file - write fails w/ "Permission denied" <==== so ... the file cannot be written to? - read file (using the same fd) Regards, Henri 64-@@ uname -a CYGWIN_NT-6.1 Seven 2.12.0s(0.333/5/3) 2019-01-21 10:25 x86_64 Cygwin ----- >From the output of strace: ----- # write ... fails 74 25044 [main] stc 1368 write: write(4, 0x100403117, 14) 31 25075 [main] stc 1368 seterrno_from_nt_status: /ext/build/mknetrel/src/cygwin-snapshot-20190121-1/winsup/cygwin/fhandler.cc:294 status 0xC0000022 -> windows error 5 29 25104 [main] stc 1368 geterrno_from_win_error: windows error 5 == errno 13 27 25131 [main] stc 1368 write: -1 = write(4, 0x100403117, 14), errno 13 i.e. the STC fails in fhandler_base::raw_write() in winsup/cygwin/fhandler.cc, right after NtWriteFile() ... Btw, earlier on, when /tmp/stc.txt is unlinked, an "Sharing violation" occurs: 32 21456 [main] stc 1368 unlink_nt: Trying to delete \??\E:\Cygwin64\tmp\stc.txt, isdir = 0 ----- # Sharing violation? in unlink_nt() in winsup/cygwin/syscalls.cc, after the 3rd call to NtOpenfile() 50 21506 [main] stc 1368 unlink_nt: Sharing violation when opening \??\E:\Cygwin64\tmp\stc.txt 443 21949 [main] stc 1368 try_to_bin: \??\E:\Cygwin64\tmp\stc.txt, return bin_status 2 ### "has been moved"? 35 21984 [main] stc 1368 unlink_nt: \??\E:\Cygwin64\tmp\stc.txt, return status = 0x0 28 22012 [main] stc 1368 unlink: 0 = unlink(/tmp/stc.txt) ----- Output of the STC: 64-@@ ./stc # source code included below ... Invoked from: /usr/bin/bash (parent process) flagsfl2 = 0x118000 devfile = /dev/fd/3 flagsfl3 = 0x118002 /dev/fd/3: Cannot write!, id = openfd3, errno = 13, errstr = Permission denied buf = Hello, world! 64-@@ # this is odd: open("/dev/fd/3", O_RDWR) succeeds ... write(4, ...) does not # fail w/ "Bad file descriptor", but w/ "Permission denied"! ----- If the STC is put "on hold" right before termination (before closing the file descriptors), the "bin" shows: 64-@@ pwd /drv/e/$RECYCLE.BIN/S-1-5-21-91509220-1575020443-2714799223-1000 64-@@ ls -al total 6 drwx------+ 1 Henri None 0 Jan 27 17:27 . drwxrwx---+ 1 Henri None 0 Jan 27 08:47 .. -rw-r----- 1 Unknown+User Unknown+Group 14 Jan 27 17:27 .???017d00000001f91f4e494283f3b8a953 -rwx------+ 1 Henri None 129 Jan 27 08:33 desktop.ini This file cannot be accessed (read) ... (can be read by STC, but NOT written to!). 64-@@ icacls . . BUILTIN\Administrators:(OI)(CI)(F) NT AUTHORITY\SYSTEM:(OI)(CI)(F) Seven\Henri:(OI)(CI)(F) Mandatory Label\Low Mandatory Level:(OI)(CI)(IO)(NW) Successfully processed 1 files; Failed processing 0 files 64-@@ getfacl . # file: . # owner: Henri # group: None user::rwx group::--- group:SYSTEM:rwx #effective:--- group:Administrators:rwx #effective:--- mask::--- other::--- default:user::rwx default:group::--- default:group:SYSTEM:rwx #effective:--- default:group:Administrators:rwx #effective:--- default:mask::--- default:other::--- ----- source code of STC: // gcc -Wall -o stc stc.c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> // strerror() #include <errno.h> #include <fcntl.h> // NOTE: my text uses "fd 2" for a file descriptor that equals 2; and fd2 for variable fd2 /* LPI, 5.11 The /dev/fd Directory (Linux Programming Interface, Michael Kerrisk) ... FIXME: No, on Linux the file is "reopened": a new open file description is created! Cygwin/ W7 file deleted: (fd2 is opened before file deletion) - file can be written to via fd3 iff fd2 has been opened read-write file NOT deleted: - file can be written to via fd3, even if fd2 has been opened read-only */ /* - create file (in /tmp) write-only, write "Hello, world!" to file, close fd - open file once more read-only (or read-write) - unlink file - open file, using /dev/fd/N (or /proc/<pid>/fd/N), read-write - write "*****" to file (using the fd obtained in the previous line), lseek to begin of file - read file (using the same fd) */ void errExit(const char *str) { fprintf(stderr, "id = %s, errno = %d, errstr = %s\n", str, errno, strerror(errno)); exit(EXIT_FAILURE); } int main(int argc, char *argv[]) { #if 1 { char tmp0[30] = { 0 }; char tmp1[30] = { 0 }; if (snprintf(tmp0, sizeof(tmp0), "/proc/%u/exe", (unsigned int)getppid() ) == -1 ) errExit("sprintf-tmp0"); //printf("tmp0 = %s\n", tmp0); if (strlen(tmp0) == sizeof(tmp0) ) errExit("strlen-tmp0"); if (readlink(tmp0, tmp1, sizeof(tmp1) - 1) == -1) errExit("readlink-tmp1"); //printf("tmp1 = %s\n", tmp1); if (strlen(tmp1) == sizeof(tmp1) ) errExit("strlen-tmp1"); fprintf(stderr, "Invoked from: %s (parent process)\n", tmp1); } #endif int fd1, fd2, fd3; errno = 0; // kludge (ignore error if file does not exist) ... if (unlink("/tmp/stc.txt") == -1) { if (errno != 2) errExit("unlink"); else errno = 0; } // create a tmpfile in the same way that bash would do ... fd1 = open("/tmp/stc.txt", O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); if (fd1 == -1) errExit("openfd1"); if (write(fd1, "Hello, world!\n", 14) == -1) errExit("writefd1"); // close fd1 like bash would do ... if (close(fd1) == -1) errExit("closefd1"); // also open this tmpfile for reading like bash would do ... fd2 = open("/tmp/stc.txt", O_RDONLY); //fd2 = open("/tmp/stc.txt", O_RDWR); if (fd2 == -1) errExit("openfd2"); #if 1 int flagsfl2; if ( (flagsfl2 = fcntl(fd2, F_GETFL)) == -1) errExit("fcntlfd1-getfl2"); fprintf(stderr, "flagsfl2 = 0x%x\n", flagsfl2); // Linux: /usr/include/bits/fcntl-linux.h // Cygwin: /usr/include/sys/_default_fcntl.h #endif // delete the tmpfile like bash would do ... if (unlink("/tmp/stc.txt") == -1) errExit("unlink"); // kludge: compose a string (using fd2) representing "the device file" // in /dev/fd (a symlnk to /proc/self/fd) for file descriptor fd2 which // is still open ... char devfile[16] = "/dev/fd/"; devfile[8] = fd2 + 0x30; devfile[9] = '\0'; //char devfile[16] = "/proc/self/fd/"; devfile[14] = fd2 + 0x30; devfile[15] = '\0'; fprintf(stderr, "devfile = %s\n", devfile); // open this device file; it succeeds on Linux, but fails on Cygwin (that // is, it failed before 20190107?) //fd3 = open(devfile, O_RDONLY); // this failed before 20190107? fd3 = open(devfile, O_RDWR); // odd: succeeds on W7 (fd2 is read-only!) if (fd3 == -1) { // does not happen beyond 20190106 const char *id = "openfd3"; #if 1 fprintf(stderr, "%s: Cannot open!, id = %s, errno = %d, errstr = %s\n", devfile, id, errno, strerror(errno)); /* previously, (before 20190107?) it was not even possible to open the file, using either "/dev/fd/N" or "/proc/self/fd/N" if the target had been unlink'ed ... Now it is possible to open the file as indicated, but it can only be read. On Linux however, it is even possible to open it "read-write" ... (where fd3 will point to a brand-new open file handle) */ errno = 0; char buf[16] = { 0 }; if (read(fd2, buf, sizeof(buf) ) == -1) errExit("readfd2"); fprintf(stderr, "buf = %s", buf); if (close(fd2) == -1) fprintf(stderr, "closefd2 failed\n"); exit(EXIT_FAILURE); #else errExit(id); #endif } #if 0 { char buf[16] = { 0 }; if (read(fd2, buf, sizeof(buf) ) == -1) errExit("readfd2"); fprintf(stderr, "buf = %s", buf); } #endif #if 1 int flagsfl3; if ( (flagsfl3 = fcntl(fd3, F_GETFL)) == -1) errExit("fcntlfd3-getfl3"); fprintf(stderr, "flagsfl3 = 0x%x\n", flagsfl3); // Linux: /usr/include/bits/fcntl-linux.h // Cygwin: /usr/include/sys/_default_fcntl.h #endif // option: write using fd3 #if 1 // failure unless fd2 has been opened read-write (and file has been deleted) // W7: fd3 will be a duplicate of fd2 in that case ... if (write(fd3, "*****\n", 14) == -1) { const char *id = "openfd3"; #if 1 fprintf(stderr, "%s: Cannot write!, id = %s, errno = %d, errstr = %s\n", devfile, id, errno, strerror(errno)); errno = 0; #else errExit(id); #endif } // required because of write() -- reset file offset if (lseek(fd3, 0, SEEK_SET) == -1) errExit("lseekfd3"); #endif // end - option: write using fd3 char buf[16] = { 0 }; if (read(fd3, buf, sizeof(buf) ) == -1) errExit("readfd3"); fprintf(stderr, "buf = %s", buf); //sleep(30); if (close(fd3) == -1) fprintf(stderr, "closefd3 failed\n"); if (close(fd2) == -1) fprintf(stderr, "closefd2 failed\n"); } //===== -- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple