[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[FDclone-users:00330] Re: copying from/to a linked file
- Subject: [FDclone-users:00330] Re: copying from/to a linked file
- From: Takashi SHIRAI <shirai@unixusers.net>
- Date: Thu, 19 Aug 2004 23:03:13 +0900
しらいです。
In Message-Id <86r7q3eoiw.knu@iDaemons.org>
"Akinori MUSHA" <knu@iDaemons.org>さんwrites:
> ファイルのコピーにおいてコピー元とコピー先がリンク(ハード or
> シンボリック)によって実体を同じくする場合、 FDclone でコピーを
> 強行(上書き)するとファイルが破壊されてしまいます。
実体が同じなので自分自身に上書きしようとして中身を消してし
まう訳ですか。確かにまずいですね。rename(2) だと統合して一つ
の実態になるのでファイル移動だと問題なさそうですけど。
> *BSD や GNU の cp(1) では stat して st_dev と st_ino が一致
> していたらその旨を表示してコピーを避けるようになっていますが、
> FDclone でも同様の処理にできないでしょうか。
でも、これって同名ファイルが存在して敢えて「上書き」を選ん
だ場合の処理ですよね?その場合のユーザの意図を重視するなら、
求められる動作は「削除して上書き」ではないでしょうか?
とは言え、この二つの操作を atomic に行なう system call は
存在しないので、unlink() & creat() だと critical section が
現れてしまいますね。
となると、実体が一致したら unlink() -> open(E_EXCL) という
処理が妥当なところではないでしょうか。
という訳でこんな感じではどうでしょう?
---- Cut Here ----
diff -u ../old/FD-2.06/file.c ./file.c
--- ../old/FD-2.06/file.c Tue Aug 10 00:00:00 2004
+++ ./file.c Thu Aug 19 23:05:51 2004
@@ -612,11 +612,9 @@
char *src, *dest;
struct stat *stp1, *stp2;
{
-#if MSDOS
struct stat st;
-#endif
char buf[BUFSIZ];
- int i, fd1, fd2, duperrno;
+ int i, fd1, fd2, flags, mode, duperrno;
#if MSDOS
if (!stp2 && Xlstat(dest, &st) >= 0) stp2 = &st;
@@ -628,17 +626,25 @@
buf[i] = '\0';
return(Xsymlink(buf, dest));
}
- if ((fd1 = Xopen(src, O_BINARY | O_RDONLY, stp1 -> st_mode)) < 0)
- return(-1);
+
+ flags = (O_BINARY | O_RDONLY);
+ mode = stp1 -> st_mode;
+ if ((fd1 = Xopen(src, flags, mode)) < 0) return(-1);
+
+ flags = (O_BINARY | O_WRONLY | O_CREAT | O_TRUNC);
#if MSDOS
- fd2 = Xopen(dest,
- O_BINARY | O_WRONLY | O_CREAT | O_TRUNC,
- stp1 -> st_mode | S_IWRITE);
+ mode |= S_IWRITE;
#else
- fd2 = Xopen(dest,
- O_BINARY | O_WRONLY | O_CREAT | O_TRUNC, stp1 -> st_mode);
+ if (Xstat(dest, &st) >= 0
+ && st.st_dev == stp1 -> st_dev && st.st_ino == stp1 -> st_ino) {
+ if (Xunlink(dest) < 0) {
+ Xclose(fd1);
+ return(-1);
+ }
+ flags |= O_EXCL;
+ }
#endif
- if (fd2 < 0) {
+ if ((fd2 = Xopen(dest, flags, mode)) < 0) {
Xclose(fd1);
return(-1);
}
---- Cut Here ----
しらい たかし