Pārlūkot izejas kodu

Another iteration with unix files -- observed problems outside virtualbox

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@6959 8c9fc860-2736-0410-a75d-ab315db34111
felixf 8 gadi atpakaļ
vecāks
revīzija
b1715f082c
1 mainītis faili ar 41 papildinājumiem un 30 dzēšanām
  1. 41 30
      source/Generic.Unix.UnixFiles.Mod

+ 41 - 30
source/Generic.Unix.UnixFiles.Mod

@@ -13,6 +13,7 @@ CONST
 	Open = 0;  Create = 1;  Closed = 2;	(* file states *)
 	
 	NoKey = -1;
+	CreateFlags = Unix.rdwr + Unix.creat + Unix.trunc;
 	
 	TraceCollection = 0;
 	TraceSearch=1;
@@ -388,12 +389,14 @@ TYPE
 					END;
 					key := 0;
 				END Delete0;
-
-				PROCEDURE Rename0*( old, new: ARRAY OF CHAR;  f: Files.File;  VAR res: LONGINT );
+				
+				(* return remaining old file, if any *)
+				PROCEDURE TryRename*( old, new: ARRAY OF CHAR;  f: Files.File;  VAR res: LONGINT ): LONGINT;
 				CONST Bufsize = 4096;
-				VAR fdold, fdnew, n, r: LONGINT;  ostat, nstat: Unix.Status;
+				VAR fdold, fdnew, fo, n, r: LONGINT;  ostat, nstat: Unix.Status;
 					buf: ARRAY Bufsize OF CHAR;
 				BEGIN {EXCLUSIVE}
+					fo := NoDesc;
 					r:= Unix.stat( ADDRESSOF( old ), ostat );
 
 					IF r >= 0 THEN
@@ -402,20 +405,19 @@ TYPE
 							 r := Unix.unlink( ADDRESSOF( new ) )  (* work around stale nfs handles *);
 						END;
 						r := Unix.rename( ADDRESSOF( old ), ADDRESSOF( new ) );
-						IF r < 0 THEN
+						IF r < 0 THEN (* could not rename, try copy *)
 							res := Unix.errno( );
 							IF (res = Unix.EXDEV) OR (res = Unix.ETXTBSY) THEN  (* cross device link, move the file / file busy frequently happens in VirtualBox *)
-
 								fdold := Unix.open( ADDRESSOF( old ), Unix.rdonly, {} );
+								fo := fdold;
 								IF fdold < 0 THEN    
 									res := Unix.errno( );  
-									RETURN
+									RETURN NoDesc;
 								END;
 								fdnew := Unix.open( ADDRESSOF( new ), Unix.rdwr + Unix.creat + Unix.trunc, Unix.rwrwr );
 								IF fdnew < 0 THEN    
 									res := Unix.errno( );  
-
-									RETURN
+									RETURN NoDesc;
 								END;
 								n := Unix.read( fdold, ADDRESSOF( buf ), Bufsize );
 								WHILE n > 0 DO
@@ -424,23 +426,29 @@ TYPE
 										res := Unix.errno();  
 										r := Unix.close( fdold );  
 										r := Unix.close( fdnew );
-										RETURN
+										RETURN NoDesc;
 									END;
 									n := Unix.read( fdold, ADDRESSOF( buf ), Bufsize )
 								END;
-								r := Unix.unlink( ADDRESSOF( old ) );  								
+								r := Unix.unlink( ADDRESSOF( old ) );
 								r := Unix.close( fdold );
-								r := Unix.unlink( ADDRESSOF( old ) );  (* for virtual box to work *)
 								r := Unix.close( fdnew );  
 								res := Files.Ok
 							ELSE
-								RETURN  (* res is Unix.rename return code *)
+								RETURN NoDesc (* res is Unix.rename return code *)
 							END
 						END;
 						res := Files.Ok
 					ELSE  
 						res := Unix.errno();
-					END
+					END;
+					RETURN fo;
+				END TryRename;
+
+				PROCEDURE Rename0*( old, new: ARRAY OF CHAR;  f: Files.File;  VAR res: LONGINT );
+				VAR of: LONGINT;
+				BEGIN
+					of := TryRename(old, new, f, res);
 				END Rename0;
 				
 
@@ -547,7 +555,7 @@ TYPE
 	
 	File* = OBJECT (Files.File)
 			VAR
-				fd, fdTemp: LONGINT;
+				fd: LONGINT;
 				workName, registerName: Filename;
 				tempFile: BOOLEAN;
 				dev: Unix.DevT;
@@ -560,20 +568,21 @@ TYPE
 
 				PROCEDURE & Init( fs: Files.FileSystem );
 				BEGIN
-					SELF.fs := fs;  flags := {};  fdTemp := 0;
+					SELF.fs := fs;  flags := {};
 				END Init;
 
-				
 				PROCEDURE CreateUnixFile;
-				CONST 
-					CreateFlags = Unix.rdwr + Unix.creat + Unix.trunc;
 				VAR 
 					stat: Unix.Status;  done: BOOLEAN;  r: LONGINT;
 				BEGIN
 					IF state = Create THEN  
 						GetTempName( registerName, workName );  tempFile := TRUE
-					ELSIF state = Closed THEN  
-						workName := registerName;  registerName := "";  tempFile := FALSE;
+					ELSIF state = Closed THEN
+						IF registerName # "" THEN
+							workName := registerName;  registerName := "";  tempFile := FALSE;
+						ELSE
+							RETURN;
+						END;
 					END;
 					r := Unix.unlink( ADDRESSOF( workName ) );
 					(*unlink first to avoid stale NFS handles and to avoid reuse of inodes*)
@@ -587,7 +596,6 @@ TYPE
 						fd := Unix.open( ADDRESSOF( workName ), CreateFlags, Unix.rwrwr );
 						done := fd >= 0
 					END;
-					IF tempFile THEN fdTemp:= fd END;
 					IF done THEN
 						(*IF fd >= FileTabSize THEN  
 							r := Unix.close( fd );  
@@ -807,24 +815,27 @@ TYPE
 
 
 				PROCEDURE Register0*( VAR res: LONGINT );
+				VAR fo: LONGINT;
 				BEGIN {EXCLUSIVE}
 					IF (state = Create) & (registerName # "") THEN  
 						state := Closed (* shortcut renaming *)   ;
 					END;
-
+					
 					FlushBuffers;
+					
 					IF registerName # "" THEN
-						fs.Rename0( workName, registerName, SELF, res );
+						fo := unixFS.TryRename( workName, registerName, SELF, res );
 						IF res # Files.Ok THEN  
 							Halt( SELF, FALSE, "UnixFiles.File.Register: rename failed" )  
 						END;
-						
-						IF tempFile & (fdTemp # 0) THEN
-							res := Unix.close(fdTemp); 
-							res := Unix.unlink( ADDRESSOF( workName ) ); 
-							fdTemp := 0;
+
+						IF fo # NoDesc THEN 
+							TRACE(fo, fd); 
+							res := Unix.close(fo); 
+							res := Unix.unlink(ADDRESSOF(workName));  (* VirtualBox ! Can only delete file when closed. *)
+							fd := Unix.open( ADDRESSOF( registerName ), CreateFlags, Unix.rwrwr );
 						END;
-						
+
 						workName := registerName;  registerName := "";  tempFile := FALSE;
 					END;
 					(*collection.Register(SELF);*)
@@ -861,7 +872,7 @@ TYPE
 							fd := NoDesc;
 						END;
 					END;
-					DEC( openfiles );  state := Closed
+					DEC( openfiles );  state := Closed;
 				END Finalize;
 				
 				PROCEDURE Close;