On UNIX there are two copy commands: cp and install. cp copies over the destination inode. install creates a new inode. This is important when copying new .so files while an application is using the old one.
22674 stat64("destination_file", 0xbfad201c) = -1 ENOENT (No such file or directory)
22674 stat64("source_file", {st_mode=S_IFREG|0644, st_size=1418, ...}) = 0
22674 stat64("destination_file", 0xbfad1e18) = -1 ENOENT (No such file or directory)
22674 openat(AT_FDCWD, "source_file", O_RDONLY|O_LARGEFILE) = 3
22674 fstat64(3, {st_mode=S_IFREG|0644, st_size=1418, ...}) = 0
22674 openat(AT_FDCWD, "destination_file", O_WRONLY|O_CREAT|O_EXCL|O_LARGEFILE, 0644) = 4
22674 fstat64(4, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
22674 fadvise64_64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
22674 mmap2(NULL, 139264, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f94000
22674 read(3, "file contents go here..."..., 131072) = 1418
22674 write(4, "file contents go here..."..., 1418) = 1418
22674 read(3, "", 131072) = 0
22674 close(4) = 0
22674 close(3) = 0
It doesn't do anything specific with any inodes, it just opens a file for reading (openat(AT_FDCWD, "source_file", O_RDONLY|O_LARGEFILE) = 3) and one for writing (openat(AT_FDCWD, "destination_file", O_WRONLY|O_CREAT|O_EXCL|O_LARGEFILE, 0644) = 4), copies the content from source to destination and closes both files.Running a trace on install (install source_file destination_file, abbreviated) shows exactly the same trace with the following additions:
22795 fsetxattr(4, "system.posix_acl_access", "\2\0\0\0\1\0\6\0\377\377\377\377\4\0\0\0\377\377\377\377 \0\0\0\377\377\377\377", 28, 0) = 0
...
22795 chmod("destination_file", 0755) = 0
The only difference between cp and install is that the latter sets access rights while the former leaves this up to the user (and umask). # cat >sleepy.c
#include <unistd.h>
int main(void) {
sleep(999);
return 0;
}
# cc -o sleepy sleepy.c
# ./sleepy &
Now try to overwrite it: # cp /bin/date sleepy
cp: sleepy: Text file busy
Now try with install: # install /bin/date sleepy
# ./sleepy
Install was able to get around the "Text file busy" error. Why? # touch a
# stat -f %i a
686974
# cp /etc/motd a
# stat -f %i a
686974
cp here has preserved the inode, it replaced the contents without deleting and recreating the file. Now lets try install: # stat -f %i a
686974
# install /etc/motd a
# stat -f %i a
687076
The inode changed. Why? 46785 install CALL unlink(0x7fffffffed52)
46785 install NAMI "a"
46785 install RET unlink 0
install unlinks the file first before copying the data over. Then it creates a new file/inode (F_CREAT): 46785 install CALL openat(AT_FDCWD,0x7fffffffed52,0x602<O_RDWR|O_CREAT|O_TRUNC>,0600<S_IRUSR|S_IWUSR>)
46785 install NAMI "a"
46785 install RET openat 4Application VM pages for these libraries are mapped back into the same physical DRAM pages via the MMU. Every modern OS implementation loads dynamic libraries once and then references the same pages across applications.
On disk pages matter not once the shared object is loaded by the kernel.