2
0
Эх сурвалжийг харах

Support Files.Exists(fileName, VAR fullFilename, VAR flags) on the level of the file systems. Using enumerators made problems and was inappropriate for this low-level FS-related task.

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@7069 8c9fc860-2736-0410-a75d-ab315db34111
felixf 8 жил өмнө
parent
commit
e29617a016

+ 1 - 4
source/FSTools.Mod

@@ -1117,11 +1117,8 @@ END CloseFiles;
 
 (* returns if a file or directory exists. If yes, then fullname is set to filename *)
 PROCEDURE Exists*(CONST name: ARRAY OF CHAR; VAR fullName: ARRAY OF CHAR; VAR flags: SET): BOOLEAN;
-VAR enum: Files.Enumerator; fname, suffix: Files.FileName; time, date, size: LONGINT;
 BEGIN
-	NEW(enum);
-	enum.Open(name,{});
-	IF enum.HasMoreEntries() & enum.GetEntry(fullName, flags, time, date, size) THEN RETURN TRUE ELSE RETURN FALSE END;
+	RETURN Files.Exists(name, fullName, flags);
 END Exists;
 
 END FSTools.

+ 37 - 2
source/Files.Mod

@@ -316,6 +316,19 @@ TYPE
 		BEGIN	(* see note in Volume.Finalize *)
 			vol := NIL
 		END Finalize;
+		
+		(* default implementation using an enumerator *)
+		PROCEDURE Has*(CONST name: ARRAY OF CHAR; VAR fullName: ARRAY OF CHAR; VAR flags: SET): BOOLEAN;
+		VAR enum: Enumerator; time, date, size: LONGINT;
+		BEGIN
+			NEW(enum);
+			enum.Open(name,{});
+			IF enum.HasMoreEntries() & enum.GetEntry(fullName, flags, time, date, size) THEN 
+				RETURN TRUE 
+			ELSE 
+				RETURN FALSE 
+			END;
+		END Has;
 
 (* GC
 		PROCEDURE Purge*(f: File);	(* race! *)
@@ -1056,8 +1069,8 @@ END RemoveDirectory;
 PROCEDURE Enumerate(VAR mask: ARRAY OF CHAR; flags: SET; enum: Enumerator);
 VAR
 	fs: FileSystem; ft: FileSystemTable; i: LONGINT;
-	prefix: Prefix; fmask: FileName
-;BEGIN
+	prefix: Prefix; fmask: FileName;
+BEGIN
 	SplitName(mask, prefix, fmask);
 	IF prefix = "" THEN
 		GetList(ft);
@@ -1075,6 +1088,28 @@ VAR
 	END
 END Enumerate;
 
+PROCEDURE Exists*(CONST fileName: ARRAY OF CHAR; VAR fullName: ARRAY OF CHAR; VAR flags: SET): BOOLEAN;
+VAR
+	fs: FileSystem; ft: FileSystemTable; i: LONGINT;
+	prefix: Prefix;
+BEGIN
+	IF prefix = "" THEN
+		GetList(ft);
+		IF ft # NIL THEN
+				(* FIX: deadlock possible if fs containing anonymous file does not allow concurrent Enumerate and Write *)
+			FOR i := 0 TO LEN(ft^)-1 DO
+				IF ~(NeedsPrefix IN ft[i].flags) THEN
+					IF ft[i].Has(fileName, fullName, flags) THEN RETURN TRUE END;
+				END;
+			END
+		END
+	ELSE
+		fs := This(prefix);
+		RETURN fs.Has(fileName, fullName, flags);
+	END;
+	RETURN FALSE;
+END Exists;
+
 (* Find an open file. *)
 
 PROCEDURE FindOpenFile(enum: FileSearcher; fs: FileSystem; key: LONGINT): File;

+ 24 - 0
source/Unix.UnixFiles.Mod

@@ -113,6 +113,11 @@ TYPE
 			BEGIN
 				fs.RemoveDirectory0( name, force, key, res );
 			END RemoveDirectory0;
+			
+			PROCEDURE Has(CONST name: ARRAY OF CHAR; VAR fullName: ARRAY OF CHAR; VAR flags: SET): BOOLEAN;
+			BEGIN
+				RETURN fs.Has(name, fullName, flags);
+			END Has;
 
 	END AliasFileSystem;
 	
@@ -496,6 +501,25 @@ TYPE
 					END;
 					checkSet := NIL;
 				END Enumerate0;
+				
+				PROCEDURE Has(CONST name: ARRAY OF CHAR; VAR fullName: ARRAY OF CHAR; VAR flags: SET): BOOLEAN;
+				VAR r: LONGINT;stat: Unix.Status;
+				BEGIN
+					r := Unix.stat( ADDRESSOF( name ), stat );
+					TRACE(r);
+					IF r  # 0 THEN RETURN FALSE END;
+					flags := {};
+					IF IsDirectory( stat ) THEN
+						flags := {Files.ReadOnly, Files.Directory}
+					ELSE
+						r := Unix.access( ADDRESSOF( name ), Unix.W_OK ); 
+						IF r < 0 THEN  flags := {Files.ReadOnly}  END
+					END;
+					r := Unix.realpath(ADDRESSOF(name), ADDRESSOF(fullName));
+					TRACE(r,name,fullName);
+					IF (r = 0) THEN COPY(name, fullName) END; (* no success *)
+					RETURN TRUE;
+				END Has;
 
 	END UnixFileSystem;
 	

+ 22 - 1
source/Win32.WinFS.Mod

@@ -140,7 +140,7 @@ TYPE
 	VAR fs: WinFileSystem;
 		useprefix*: BOOLEAN;
 
-		PROCEDURE Prefix( VAR name, res: ARRAY OF CHAR );
+		PROCEDURE Prefix( CONST name: ARRAY OF CHAR; VAR res: ARRAY OF CHAR );
 		BEGIN
 			IF useprefix & (name # "") THEN Join( prefix, ":", name, res );  ELSE COPY( name, res );  END;
 		END Prefix;
@@ -197,6 +197,13 @@ TYPE
 		BEGIN
 			Prefix( name, fname );  fs.RemoveDirectory0( fname, force, key, res );
 		END RemoveDirectory0;
+		
+		PROCEDURE Has(CONST name: ARRAY OF CHAR; VAR fullName: ARRAY OF CHAR; VAR flags: SET): BOOLEAN;
+		VAR fname: FileName;
+		BEGIN
+			Prefix(name, fname );  RETURN fs.Has(fname, fullName, flags);
+		END Has;
+		
 
 	END AliasFileSystem;
 
@@ -406,6 +413,20 @@ TYPE
 			collection.Finalize();
 		END Finalize;
 
+		PROCEDURE Has*(CONST fileName: ARRAY OF CHAR; VAR fullName: ARRAY OF CHAR; VAR flags: SET): BOOLEAN;
+		VAR name: FileName;
+		BEGIN
+			COPY(fileName, name);
+			ConvertChar(name, Files.PathDelimiter, PathDelimiter );  
+			IF FindFile(fileName, fullName) THEN 
+				flags := FileFlags(Kernel32.GetFileAttributes(fullName));
+				ConvertChar(fullName, PathDelimiter,Files.PathDelimiter);  
+				RETURN TRUE
+			ELSE
+				RETURN FALSE
+			END;
+		END Has;
+
 	END WinFileSystem;
 
 	Buffer = POINTER TO RECORD