Oto coś, przez co zastanawiałem się przez chwilę:
[15:40:50][/tmp]$ mkdir a
[15:40:52][/tmp]$ strace rmdir a
execve("/usr/bin/rmdir", ["rmdir", "a"], [/* 78 vars */]) = 0
brk(0) = 0x11bb000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff3772c3000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=245801, ...}) = 0
mmap(NULL, 245801, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ff377286000
close(3) = 0
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p\36\3428<\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2100672, ...}) = 0
mmap(0x3c38e00000, 3924576, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x3c38e00000
mprotect(0x3c38fb4000, 2097152, PROT_NONE) = 0
mmap(0x3c391b4000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b4000) = 0x3c391b4000
mmap(0x3c391ba000, 16992, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x3c391ba000
close(3) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff377285000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff377283000
arch_prctl(ARCH_SET_FS, 0x7ff377283740) = 0
mprotect(0x609000, 4096, PROT_READ) = 0
mprotect(0x3c391b4000, 16384, PROT_READ) = 0
mprotect(0x3c38c1f000, 4096, PROT_READ) = 0
munmap(0x7ff377286000, 245801) = 0
brk(0) = 0x11bb000
brk(0x11dc000) = 0x11dc000
brk(0) = 0x11dc000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=106070960, ...}) = 0
mmap(NULL, 106070960, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ff370d5a000
close(3) = 0
rmdir("a") = 0
close(1) = 0
close(2) = 0
exit_group(0) = ?
+++ exited with 0 +++
[15:40:55][/tmp]$ touch a
[15:41:16][/tmp]$ strace rm a
execve("/usr/bin/rm", ["rm", "a"], [/* 78 vars */]) = 0
brk(0) = 0xfa8000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3b2388a000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=245801, ...}) = 0
mmap(NULL, 245801, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f3b2384d000
close(3) = 0
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p\36\3428<\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2100672, ...}) = 0
mmap(0x3c38e00000, 3924576, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x3c38e00000
mprotect(0x3c38fb4000, 2097152, PROT_NONE) = 0
mmap(0x3c391b4000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b4000) = 0x3c391b4000
mmap(0x3c391ba000, 16992, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x3c391ba000
close(3) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3b2384c000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3b2384a000
arch_prctl(ARCH_SET_FS, 0x7f3b2384a740) = 0
mprotect(0x60d000, 4096, PROT_READ) = 0
mprotect(0x3c391b4000, 16384, PROT_READ) = 0
mprotect(0x3c38c1f000, 4096, PROT_READ) = 0
munmap(0x7f3b2384d000, 245801) = 0
brk(0) = 0xfa8000
brk(0xfc9000) = 0xfc9000
brk(0) = 0xfc9000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=106070960, ...}) = 0
mmap(NULL, 106070960, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f3b1d321000
close(3) = 0
ioctl(0, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
newfstatat(AT_FDCWD, "a", {st_mode=S_IFREG|0664, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
geteuid() = 1000
newfstatat(AT_FDCWD, "a", {st_mode=S_IFREG|0664, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
faccessat(AT_FDCWD, "a", W_OK) = 0
unlinkat(AT_FDCWD, "a", 0) = 0
lseek(0, 0, SEEK_CUR) = -1 ESPIPE (Illegal seek)
close(0) = 0
close(1) = 0
close(2) = 0
exit_group(0) = ?
+++ exited with 0 +++
Dlaczego istnieją oddzielne wezwania systemowe do usunięcia katalogu i plików? Dlaczego te dwie operacje byłyby semantycznie różne?
linux
directory
rm
system-calls
d33tah
źródło
źródło
Odpowiedzi:
Katalogi są wyjątkowe w tym sensie, że w katalogu można mieć odniesienia do kilku plików i katalogów, więc jeśli usuniesz katalog nadrzędny, wszystkie te pliki utracą punkt odniesienia, z którego można uzyskać do nich dostęp, podobnie jak w procesie. W takich przypadkach
rmdir()
stosuj inne kontrole, które różnią się odunlink()
:Jeśli katalog nie jest pusty. Jeśli katalog nie jest pusty, nie można go usunąć, dopóki zawartość nie zostanie
unlink
usunięta.Jeśli katalog jest w użyciu. Jeśli proces straci swój bieżący katalog, może to prowadzić do problemów i nieokreślonych zachowań. Lepiej im zapobiegać.
W przypadku
unlink()
tych kontroli nie istnieje. W rzeczywistości możesz usunąć nazwę pliku,unlink()
a proces, który nadal używa / odwołuje się do niego, może go modyfikować bez problemów. Plik istnieje, dopóki nie istnieje deskryptor pliku, po prostu niedostępny dla nowego procesu (chyba że wiesz, gdzie szukać). Jest to część magii tęczowych dłoni w systemach plików * NIX.Teraz jest coś,
unlinkat()
co zachowuje się jak oba,unlink()
lubrmdir(2)
zależy od ścieżki, której się spodziewasz.źródło
rm -rf "$PWD"
działa i usuwa bieżący katalog. Myślę, że powódrmdir()
jest prawdopodobnie historyczny (początkowo katalogi zostały odłączone (), a rmdir (polecenie) odłączał dir /., Dir / .. i dir, a kiedy to zostało przeniesione do jądra, musiało to być nowy syscall robi wszystkie 3 przynajmniej przez okres przejściowy lub coś takiego)rmdir(dir)
nie działa, jeślidir
jest używana. Nie dotyczy to przynajmniej Linuksa, gdziermdir(getcwd())
działa dobrze (pod warunkiem, że bieżący katalog jest pusty).EBUSY
ścieżka jest obecnie używana przez system lub jakiś proces, który uniemożliwia jego usunięcie . W systemie Linux oznacza to, że ścieżka jest obecnie używana jako punkt podłączenia lub jest katalogiem głównym procesu wywołującego.mkdir test; sudo strace -e chroot,rmdir perl -e 'chroot("test"); rmdir("test")'
pokazuje, że zarówno chroot, jak i rmdir odniosły sukces.