Apakah ada cara yang lebih baik daripada sekadar mencoba membuka file?
int exists(const char *fname)
{
FILE *file;
if ((file = fopen(fname, "r")))
{
fclose(file);
return 1;
}
return 0;
}
c
filesystems
cross-platform
Dave Marshall
sumber
sumber
fopen()
/fclose()
adalah bahwa Anda mungkin tidak dapat membuka file untuk dibaca meskipun sudah ada. Misalnya,/dev/kmem
ada, tetapi sebagian besar proses tidak dapat membukanya bahkan untuk membaca./etc/shadow
adalah file lain seperti itu. Tentu saja, keduanyastat()
danaccess()
bergantung pada dapat mengakses direktori yang berisi file; semua taruhan dibatalkan jika Anda tidak bisa melakukan itu (tidak ada izin eksekusi pada direktori yang berisi file).if (file = fopen(fname, "r"))
akan memberi peringatan. Gunakan tanda kurung di sekitar pernyataan di dalam pernyataan ifif ((file = fopen(fname, "r")))
Jawaban:
Cari
access()
fungsinya, ditemukan diunistd.h
. Anda dapat mengganti fungsi Anda denganAnda juga dapat menggunakan
R_OK
,,W_OK
danX_OK
sebagai penggantiF_OK
untuk memeriksa izin baca, menulis izin, dan mengeksekusi izin (masing-masing) daripada keberadaan, dan Anda dapat ATAU salah satu dari mereka bersama-sama (yaitu memeriksa baik membaca dan menulis menggunakan izinR_OK|W_OK
)Pembaruan : Perhatikan bahwa pada Windows, Anda tidak dapat menggunakan
W_OK
untuk menguji izin menulis dengan andal, karena fungsi akses tidak memperhitungkan DACL.access( fname, W_OK )
dapat mengembalikan 0 (berhasil) karena file tidak memiliki set atribut read-only, tetapi Anda masih mungkin tidak memiliki izin untuk menulis ke file.sumber
access()
memecahkan kode saya. Saya pindah dari DevC ++ ke CodeBlocks dan berhenti bekerja. Jadi, itu tidak sempurna; +1 lebih banyak ke @Leffler.access()
boleh digunakan untuk memeriksa keberadaan file), tetapi dalam program SUID atau SGID, bahkan itu bisa saja salah. Jika file yang diuji berada dalam direktori yang UID atau GID nyata tidak dapat mengakses,access()
mungkin tidak melaporkan file seperti itu ketika memang ada. Esoteris dan mustahil? Iya.Gunakan
stat
seperti ini:dan menyebutnya seperti ini:
sumber
access()
juga ada masalah, dan ada opsi untuk digunakan untuk membuataccess()
danstat()
bekerja dengan file besar (lebih besar dari 2 GB).stat
menderita kerentanan TOCTOU yang samaaccess
? (Tidak jelas bagi saya bahwa akan lebih baik.)stat()
danaccess()
menderita kerentanan TOCTOU (demikian jugalstat()
, tetapifstat()
aman). Itu tergantung apa yang akan Anda lakukan berdasarkan ada atau tidaknya file. Menggunakan opsi yang tepat untukopen()
biasanya merupakan cara terbaik untuk mengatasi masalah, tetapi bisa rumit merumuskan pilihan yang tepat. Lihat juga diskusi tentang EAFP (Lebih Mudah Meminta Pengampunan daripada Izin) dan LBYL (Look Before You Leap) - lihat LBYL vs EAFP di Jawa , misalnya.Biasanya ketika Anda ingin memeriksa apakah ada file, itu karena Anda ingin membuat file itu jika tidak. Jawaban Graeme Perrow baik jika Anda tidak ingin membuat file itu, tetapi rentan terhadap kondisi balapan jika Anda melakukannya: proses lain dapat membuat file di antara Anda memeriksa apakah ada, dan Anda benar-benar membukanya untuk menulisnya . (Jangan tertawa ... ini bisa berimplikasi keamanan yang buruk jika file yang dibuat adalah symlink!)
Jika Anda ingin memeriksa keberadaan dan membuat file jika tidak ada, secara atomis sehingga tidak ada kondisi ras, maka gunakan ini:
sumber
open(2)
(di Linux; halaman manual OS Anda mungkin bervariasi), tetapi itu agak jelek dan mungkin tidak tahan terhadap penyerang jahat.FILE*
, Anda harus menggunakan metode posixfdopen(fd,"flags")
untuk menghasilkanFILE*
Iya. Gunakan
stat()
. Lihat halaman manual untukstat(2)
.stat()
akan gagal jika file tidak ada, jika tidak kemungkinan besar berhasil. Jika memang ada, tetapi Anda tidak memiliki akses baca ke direktori di mana ia ada, itu juga akan gagal, tetapi dalam hal itu metode apa pun akan gagal (bagaimana Anda bisa memeriksa konten direktori yang mungkin tidak Anda lihat sesuai dengan hak akses? Cukup, Anda tidak bisa).Oh, seperti orang lain sebutkan, Anda juga bisa menggunakannya
access()
. Namun saya lebih sukastat()
, seolah-olah file itu ada akan segera memberi saya banyak informasi berguna (kapan terakhir diperbarui, seberapa besar itu, pemilik dan / atau grup yang memiliki file, izin akses, dan sebagainya).sumber
access()
periksa izin akses file dari suatu file dan ini disimpan di dalam inode untuk file itu dan tidak dalam entri direktori (setidaknya untuk semua sistem file yang memiliki struktur seperti inode) . Jadiaccess()
harus mengakses inode dengan cara yang sama persis dengan yangstat()
mengaksesnya. Jadi apa yang Anda katakan hanya berlaku jika Anda tidak memeriksa izin! Dan sebenarnya pada beberapa sistemaccess()
bahkan diimplementasikan di atasstat()
(misalnya glibc pada GNU Hurd melakukannya seperti itu), jadi tidak ada jaminan di tempat pertama.sumber
(fopen_s(file, "sample.txt", "r"))
karenafopen()
dianggap sudah usang (atau nonaktifkan kesalahan yang sudah usang, tetapi itu tidak disarankan).fopen()
adalah standar C, tidak ke mana-mana. Ini hanya "usang" oleh Microsoft. Jangan gunakanfopen_s()
kecuali Anda menginginkan kode khusus platform, non-portabel.Dari bantuan Visual C ++, saya cenderung untuk ikut
Juga perlu diperhatikan nilai mode :
_access(const char *path,
int mode
)
00: Hanya ada
02: Izin menulis
04: Baca izin
06: Baca dan tulis izin
Karena Anda
fopen
bisa gagal dalam situasi di mana file itu ada tetapi tidak dapat dibuka seperti yang diminta.Sunting: Baca saja pos Mecki.
stat()
memang terlihat seperti cara yang lebih rapi untuk pergi. Ho hum.sumber
Anda dapat menggunakan fungsi realpath ().
sumber
Saya pikir fungsi access () , yang ditemukan di
unistd.h
adalah pilihan yang baik untukLinux
(Anda dapat menggunakan stat juga).Anda dapat menggunakannya seperti ini:
Dan Anda mendapatkan Output berikut:
sumber