schoenfr%tubsibr@UUNET.UU.NET (Erik Schoenfelder) (12/14/89)
Hi! About: Problem creating the output file, if it exists and is owned by someone other, but write permission is given for the file and directory. System : Sun 3/60 SunOS 4.0.3_EXPORT Version of ld.c (from binutils.tar.Z) : -rw-rw-rw- 5381/11 128917 Oct 17 17:50 1989 binutils/ld.c Working on a project, with group permission for the members, we had the following problem: Ld generates a new output-file, but aborts with `ld: Not owner for a.out', if the output file exists and is owned by someone other. For example : (user `neitzel' and `schoenfr' are members of group `staff') % ls -dgl . drwxrwxr-x 2 neitzel staff 512 Dec 12 18:22 . % ls -lg a.out -rwxrwxr-x 1 neitzel staff 36301 Dec 12 18:22 a.out % whoami schoenfr % gcc -v foo.o gcc version 1.36 /usr/local/lib/gcc-ld -e start -dc -dp /lib/crt0.o /lib/Mcrt1.o foo.o /usr/local/lib/gcc-gnulib -lc ld: Not owner for a.out % ls -lg a.out -rwxrwxr-x 1 neitzel staff 36301 Dec 12 18:23 a.out % The problem is the `chmod()' call when setting the execute permission not being the owner. ld.c> close (outdesc); ld.c> ld.c> if (chmod (output_filename, filemode | 0111) == -1) ld.c> perror_name (output_filename); ld.c> } Clearing the permission fails too, but is not checked. Solutions : (1) Ignore the return value of chmod(). -> Bad; it is possible, that the `x' permission is not set. (2) Linking is done to a temprary file, and this is mv'd to the output-file (if this is a plain file). -> Good; an existing file is not destroyed if no new executable can be created. (i think our sun does this) (3) Unlink an existing output-file. -> Hmm; if the existing output-file is a plain file, this seems to be a useable solution (and somehow simple to implement). A fix for solution (3) would be: *** ld.c.original Tue Dec 12 16:55:39 1989 --- ld.c Wed Dec 13 04:39:22 1989 *************** *** 3274,3279 **** --- 3274,3284 ---- struct stat statbuf; int filemode; + if (stat (output_filename, &statbuf) >= 0 + && (statbuf.st_mode & S_IFMT) == S_IFREG + && unlink (output_filename) < 0) + perror_name (output_filename); + outdesc = open (output_filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (outdesc < 0) perror_name (output_filename); If the file exists, and it is a plain file, then it is removed. If it cannot be removed, this is reported as an error. I hope this helps. -- Erik