State-Changed-From-To: open-analyzed State-Changed-By: Manu State-Changed-When: Mon Aug 18 20:00:44 PDT 2003 State-Changed-Why: Dear Darren, I've been aware of the issue for a while but did not change the current implementation as I was afraid to break existing code. This is why I've introduced in class FILE `file_path_exists' which will only test for existence of a symlink file as it was requested by some of our users. I guess we could add `is_symbolic_link' in FILE so that instead of calling update from UNIX_FILE_INFO it calls update_with_no_symlink_resolution link instead. This one will only query using `lstat' when available. What do you think about that? From: Darren Hiebert To: ISE Customer Support Cc: Subject: Re: EiffelBase/3513 Date: Tue, 19 Aug 2003 08:36:54 -0500 (CDT) > I've been aware of the issue for a while but did not change the current > implementation as I was afraid to break existing code. This is why I've > introduced in class FILE `file_path_exists' which will only test for > existence of a symlink file as it was requested by some of our users. Of course, any existing code is already broken, since `is_symlink' always returns false. `file_path_exists' is of no value is this context because it does not answer the question of whether or not the path is a symbolic link. I realize that because the file status is read only during `update', that file_stat() calls stat() immediately following lstat() (thus losing any information about the symbolic link status), and that all queries are merely redirected queries to the underlying status structure, `is_symlink' cannot possibly work. My suggestion would be to make the change below, which add a new run-time call similar to file_stat() that does only lstat(), and then have `update' make this call before file_stat() and save the symlink status. --- /sstb/home/hiebertd/Eiffel/PorterPackage-5.3.0620/C/run-time/file.c 2002-03-14 17:01:11.000000000 -0600 +++ /tmp/file.c 2003-08-19 08:32:05.159875600 -0500 @@ -912,6 +912,36 @@ #endif } +rt_public void file_lstat (char *path, struct stat *buf) + /* Path name */ + /* Structure to fill in */ +{ + /* This is an encapsulation of the lstat() system call. The routine either + * succeeds and returns or fails and raises the appropriate exception. + */ + + int status; /* System call status */ + + for (;;) { + errno = 0; /* Reset error condition */ +#ifdef HAS_LSTAT + status = lstat(path, buf); +#else + status = stat(path, buf); /* Get file statistics */ +#endif + if (status == -1) { /* An error occurred */ + if (errno == EINTR) /* Interrupted by signal */ + continue; /* Re-issue system call */ + else + esys(); /* Raise exception */ + } + break; + } +#if defined EIF_VMS && defined _VMS_V6_SOURCE + buf->st_uid &= 0x0000FFFF ; /* VMS: mask out group id */ +#endif +} + rt_public EIF_INTEGER file_info (struct stat *buf, int op) { /* Perform the field dereferencing from the appropriate stat structure, --- /usr/local/Eiffel5/library/base/kernel/classic/unix_file_info.e 2002-03-14 17:28:16.000000000 -0600 +++ /tmp/unix_file_info.e 2003-08-19 08:29:51.063183000 -0500 @@ -138,11 +138,8 @@ Result := file_info ($buffered_file_info, 12) /= 0 end - is_symlink: BOOLEAN is + is_symlink: BOOLEAN -- Is file a symbolic link? - do - Result := file_info ($buffered_file_info, 18) /= 0 - end is_fifo: BOOLEAN is -- Is file a named pipe? @@ -252,6 +249,8 @@ ext_name: ANY do ext_name := f_name.to_c + file_lstat ($ext_name, $buffered_file_info) + is_symlink := file_info ($buffered_file_info, 18) /= 0 file_stat ($ext_name, $buffered_file_info) -- Do not duplicate the file name. That way, if the file is -- renamed, the name here will change accordingly and access() @@ -273,6 +272,12 @@ "C (char *, struct stat *) | %"eif_file.h%"" end + file_lstat (name, stat_buf: POINTER) is + -- Get information from link `name' into `stat_buf' + external + "C (char *, struct stat *) | %"eif_file.h%"" + end + file_access (f_name: ANY; which: INTEGER): BOOLEAN is -- Perform access test `which' on `f_name' using real ID. external > I guess we could add `is_symbolic_link' in FILE so that instead of calling > update from UNIX_FILE_INFO it calls update_with_no_symlink_resolution > link instead. This one will only query using `lstat' when available. > > What do you think about that? This is another possibility. But this approach still leaves `is_symlink' broken. Why leave a routine known to be broken? It just serves as a trap for others. -- Darren Hiebert Phone: 256-971-2977 Northrop Grumman Corporation