David Kastrup wrote on 24 Jun 2005 23:01:50 +0200: > I fail to see the advantage of using chown, or using fopen and > fchown. In both cases the file name can be changed to refer to > something else before the operation starts. > > The only situation where fchown offers any advantage is where you > _already_ have a file open, like when you write the file after fopen, > and then change its permissions.
Yes, that is true. But we are exactly in the situation were fchown is useful. > That is, the owner change must be accomplished in something like > write-region, or it is pointless. As an isolated operation, > fopen/fchown offers no advantage whatsoever. Yes, fopen/fchown would be the same as calling chown. But here we have just created a new file, and we want to change it's owner, so this should be done with fchown. The code is: | Fcopy_file (file, newname, | /* We have already prompted if it was an integer, | so don't have copy-file prompt again. */ | NILP (ok_if_already_exists) ? Qnil : Qt, | Qt, Qnil); | | /* Preserve owner and group, if possible (if we are root). */ | if (stat (SDATA (encoded_file), &data) >= 0) | chown (SDATA (encoded_file), data.st_uid, data.st_gid); | | Fdelete_file (file); So, we first open a file and write something in it inside Fcopy_file, then we call chown on the same path. But the file that is at this path could be something else that what the we created in Fcopy_file. We should keep that file open, and call fchown on its filedescriptor, instead of calling chown on it's path. This will need some change in Fcopy_file, to be able to do something with the filedescriptor before the file is closed; the most easy way seems to make a subroutine that does the job of Fcopy_file and returns the fd before closing it, and use this subroutine both in Fcopy_file and here in Frename_file. We also have the same kind of thing inside Fcopy_file (and this one is also in stable emacs) where we call chmod on the file path just after closing the file. [I have replaced some part of the code with //... to make it shorter] | #ifdef VMS | // ... | #else | #ifdef MSDOS | // ... | #else /* not MSDOS */ | ofd = emacs_open (SDATA (encoded_newname), | O_WRONLY | O_TRUNC | O_CREAT | | (EQ (mustbenew, Qexcl) ? O_EXCL : 0), | 0666); | #endif /* not MSDOS */ | #endif /* VMS */ | if (ofd < 0) | report_file_error ("Opening output file", Fcons (newname, Qnil)); | | record_unwind_protect (close_file_unwind, make_number (ofd)); | | immediate_quit = 1; | QUIT; | while ((n = emacs_read (ifd, buf, sizeof buf)) > 0) | if (emacs_write (ofd, buf, n) != n) | report_file_error ("I/O error", Fcons (newname, Qnil)); | immediate_quit = 0; | | /* Closing the output clobbers the file times on some systems. */ | if (emacs_close (ofd) < 0) | report_file_error ("I/O error", Fcons (newname, Qnil)); | | if (input_file_statable_p) | { | if (!NILP (keep_time)) | { | // ... | } | #ifndef MSDOS | chmod (SDATA (encoded_newname), st.st_mode & 07777); | #else /* MSDOS */ | // ... | #endif /* MSDOS */ | } Here the change is very easy: we should just do fchmod(ofd,...) before emacs_close(ofd). -- Gaëtan LEURENT _______________________________________________ Emacs-devel mailing list Emacs-devel@gnu.org http://lists.gnu.org/mailman/listinfo/emacs-devel