2010-01-11 31 views
8

Tôi có một chương trình chấp nhận hai tên tệp làm đối số: nó đọc tệp đầu tiên để tạo tệp thứ hai. Làm cách nào để đảm bảo rằng chương trình sẽ không ghi đè tệp đầu tiên?Cách kiểm tra xem hai tên tệp có trỏ đến cùng một tệp vật lý hay không

Hạn chế:

  • Phương pháp phải tiếp tục làm việc khi sự hỗ trợ hệ thống tập tin (mềm hoặc cứng) liên kết
  • quyền tập tin được cố định và nó chỉ được yêu cầu rằng các tập tin đầu tiên là có thể đọc được và tập tin thứ hai có khả năng ghi
  • Nó tốt nên nền tảng trung lập (mặc dù Linux là mục tiêu chính)
+8

Trong triết lý UNIX và Linux, một chương trình như vậy được gọi là bộ lọc. Nó thường đọc từ đầu vào tiêu chuẩn (STDIN) và ghi vào đầu ra tiêu chuẩn (STDOUT). Điều này giúp giảm bớt các chương trình như vậy vì nó ngăn chặn trách nhiệm của việc xác minh đó cho người gọi. Chương trình của bạn có thể tập trung vào thực hiện công việc của mình. –

Trả lời

12

Trên linux, mở cả hai tệp và sử dụng fstat để kiểm tra xem st_ino (chỉnh sửa :) và st_dev có giống nhau hay không. open sẽ theo các liên kết tượng trưng. Không sử dụng trực tiếp stat để ngăn điều kiện cuộc đua.

+4

Điều kiện chủng tộc có nghĩa là trạng thái tệp có thể thay đổi giữa chỉ số (2) và mở (2). Bạn làm stat, và sau đó một số người dùng unlinks tập tin bạn vừa nói và liên kết tập tin thứ hai của bạn với một trong những bạn sắp mở (2). Chỉ cần làm rõ. –

+7

Cũng đảm bảo trường 'st_dev' khớp với nhau. Không có gì ngăn cản các tệp khác nhau trên hai tập khác nhau có cùng số inode. –

3

Nếu có thể, mở file đầu tiên read-only, (O_RDONLY) trong LINUX. Sau đó, nếu bạn cố gắng mở lại nó để viết nó, bạn sẽ gặp lỗi.

+0

Bạn sẽ nhận được các kết quả sai nếu tệp thứ hai đã được mở chỉ đọc bởi một tiến trình khác. Tôi thậm chí không chắc chắn các giải pháp phổ quát là có thể (bạn phải nghỉ mát cho các tính năng hệ thống tập tin cụ thể như nhận được ID tập tin). – Costique

9

Đặt cược tốt nhất là không sử dụng tên tệp làm danh tính. Thay vào đó, khi bạn mở tệp để đọc, hãy khóa nó, sử dụng bất kỳ cơ chế nào mà hệ điều hành của bạn hỗ trợ. Khi bạn sau đó cũng mở tệp để ghi, cũng khóa tệp đó - nếu khóa không thành công, hãy báo cáo lỗi.

+0

Không phải là rất meta, nhưng logic meta tốt đẹp sẽ hoạt động trên hầu hết các nền tảng, – dmckee

0

Bạn có thể sử dụng stat để nhận trạng thái tệp và kiểm tra xem các số inode có giống nhau hay không.

-1

Có thể bạn có thể sử dụng hàm system() để gọi một số lệnh shell?

Trong bash, bạn chỉ cần gọi:

stat -c %i filename 

này cho biết số inode của một tập tin. Bạn có thể so sánh hai tệp theo cách này và nếu các inode của chúng giống hệt nhau, điều đó có nghĩa chúng là các liên kết cứng. Cuộc gọi sau:

stat -c %N filename 

sẽ hiển thị tên tệp và nếu đó là liên kết tượng trưng, ​​nó cũng sẽ in tên tệp liên kết. Nó chỉ in ra một tên, ngay cả khi tệp trỏ đến có liên kết cứng, vì vậy việc kiểm tra liên kết tượng trưng sẽ yêu cầu so sánh số inode cho tệp thứ 2 và tệp liên kết tượng trưng liên kết để đảm bảo.

Bạn có thể chuyển hướng đầu ra của stat sang tệp văn bản và sau đó phân tích cú pháp tệp trong chương trình của bạn.

+1

Không phải của tôi downvote, nhưng hiếm khi có một điểm trong shelling ra để chạy một lệnh để chuyển đổi dữ liệu vào văn bản và sau đó phân tích cú pháp văn bản. Trên các hệ thống unix, phần SEE ALSO của trang man sẽ cho bạn biết chức năng mà các tiện ích dòng lệnh đang gọi để đạt được công việc của họ. Trong trường hợp này 'man 1 stat' cho tôi biết về' lstat (2) 'và' stat (2) 'chia sẻ một trang con người với' fstat (2) ', vì vậy bạn có thể nhận được câu trả lời tối ưu khá dễ dàng. – dmckee

+0

Nói chung, tôi gọi hệ thống() là một điều xấu (tm). Chỉ cần đề xuất một khả năng, mặc dù tôi nhận ra nó là tối ưu. – mingos

Các vấn đề liên quan