From: SF/projects/mingw n. l. <min...@li...> - 2012-10-23 12:52:25
|
Bugs item #1048593, was opened at 2004-10-17 01:35 Message generated for change (Settings changed) made by earnie You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=102435&aid=1048593&group_id=2435 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. >Category: WSL (Windows System Libraries) Group: Feature requests >Status: Pending Resolution: None Priority: 5 Private: No Submitted By: boguslaw brandys (brandysb) >Assigned to: Earnie Boyd (earnie) Summary: tmpfile() replacement Initial Comment: MAX_TMP 32767 Bug report (Closed) for mingw-runtime no. 1047975 If tmpfile() limitation to 32767 temporary files in process and this is related to MSVC runtime please consider replacement for this function. This could be simple, fast and efficient like this : FILE * tmpfile(void) { char filename[MAX_PATH]; FILE *f; GetTempFileName(".","temp",0,filename); f = fopen(filename,"w+bTD"); return f; } Works very well. Best Regards Bogusław Brandys ---------------------------------------------------------------------- >Comment By: Earnie Boyd (earnie) Date: 2012-10-23 05:52 Message: I'll consider this for 4.1 or maybe 4.2. ---------------------------------------------------------------------- Comment By: boguslaw brandys (brandysb) Date: 2004-10-18 00:01 Message: Logged In: YES user_id=1092450 OK.Fixed in case when fopen fails. _rmtmp probably somewhere store FILE * pointers to delete them, it is useless when so many (>32767) files are generated becouse of memory required. In my opionion it is bad design also to use this function, but unfortunately it exists. Becouse I see no solution for _rmtmp() function instead maybe just add proposed new function as tmpfile2() - extended beyond TMP_MAX limit.What do you think ? FILE * tmpfile(void) { char temppath[MAX_PATH]; char filename[MAX_PATH]; FILE *f; int i; i = GetTempPath(MAX_PATH,temppath); if ((i==0) || (i > MAX_PATH)) return NULL; if (GetTempFileName(temppath,"tmp",0,filename)==0) return NULL; f = fopen(filename,"w+bTD"); if (f==NULL) unlink(filename); return f; } ---------------------------------------------------------------------- Comment By: Aaron W. LaFramboise (aaronwl) Date: 2004-10-17 15:04 Message: Logged In: YES user_id=1040098 Sorry, my test was broken. I was linking to the wrong runtime. :-( I can confirm that this works on Windows XP with all msvcrt versions from 4.20 to 7.0. I think this version is free of multithreading issues. I am still concerned, though, about the possibility of fopen() failing. The two reasons I can think of that this might happen would be hitting the limit for maximum files, or changes to the filesystem (such as the administrator "cleaning" the temp directory). There are two problems for this case in the current impl: -The temp file is not removed. -The return value and errno will be nonsensical to the user. The two options of what to do in such a case are: -Retry. This would be similar to what mkstemp() implementations do. This wouldn't be the right thing if a max file limit had been hit, though. -Fail. errno should probably be saved and restored in this case so that it isn't set to something that doesn't make any sense. The problem with this approach is that returning 0 usually means that no future call will suceed, either, which wouldn't necessarily be true: the very next call would probably suceed. The C standard (or POSIX) doesn't define any sort of EAGAIN condition, so I don't think theres a way around this. Other than that, I wonder if tmpnam or MAX_TMP should be altered in some way also. Unfortunately, GetTempFileName isn't a great fit for tmpnam, because tmpnam isn't supposed to create the file. ---------------------------------------------------------------------- Comment By: boguslaw brandys (brandysb) Date: 2004-10-17 13:47 Message: Logged In: YES user_id=1092450 I have exaclty the same msvcrt 7.0.2600.2180 with Windows XP SP2 Home and no problem : temporary files are deleted on close or exit Could You describe how You test this ? I attached my test program source (updated) ---------------------------------------------------------------------- Comment By: Aaron W. LaFramboise (aaronwl) Date: 2004-10-17 13:26 Message: Logged In: YES user_id=1040098 According to a test I just ran, on Windows XP Pro SP2 with msvcrt 7.0.2600.2180, this function does not cause temporary files to be removed on fclose() or exit. Additionally, the MSVC 6.0 documentation I have does not mention the 'D' or 'T' flags to fopen. Possibly msvcrt.dll does not have support for these options; maybe only msvcr??.dll does. I also noticed that mingwrt does not appear to include _rmtmp() at all. It probably should, since this function has been supported in all msvcrt.dll versions I have access to (since at least 4.20.0.6164, Jun 96). ---------------------------------------------------------------------- Comment By: boguslaw brandys (brandysb) Date: 2004-10-17 12:47 Message: Logged In: YES user_id=1092450 Well I could not test it on some NT/XP Pro , but the modified function just creates temporary files in current user temp directory so no race conditions exists. I'm also quite sure that there is no gap between getting the temporary name and creating temporary file (like would be if tmpname will be used) becouse GetTempFileName is atomic and CREATE unique file then closing it.After that file exists and is opened by fclose with special flag which causes it to be delete on close/exit. Of course that is no prevent for malicious code to write into the file in time BEETWEN GetTempFileName and fopen, but this is hardly to avoid . ---------------------------------------------------------------------- Comment By: boguslaw brandys (brandysb) Date: 2004-10-17 12:39 Message: Logged In: YES user_id=1092450 Sorry, i dont understand why my response is goint the first on the list not under the other comments ;-( But, I must say that this function DOES properly close file when fclose is used or application is terminated (well sometimes do not on crash) This is why "D" option is used according to MSDN. If someone , preferably C runtime Guru could say if this is mt-safe would be better, but I quite sure that there is now (after add GetTempPath) better then existing tmfile() implementation in mingw runtime. ---------------------------------------------------------------------- Comment By: boguslaw brandys (brandysb) Date: 2004-10-17 12:32 Message: Logged In: YES user_id=1092450 Modified proposition: FILE * tmpfile(void) { char temppath[MAX_PATH]; char filename[MAX_PATH]; FILE *f; int i; i = GetTempPath(MAX_PATH,temppath); if ((i==0) || (i > MAX_PATH)) return NULL; if (GetTempFileName(temppath,"tmp",0,filename)==0) return NULL; f = fopen(filename,"w+bTD"); return f; } Regarding MSDN documentation tmpfile() VC++ implementation is far from complete. I didn't find any errno setting mentioned in http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt_tmpfile.asp - only NULL is returned in case of error. I'm not going to send a "ready to go" implementation (in that case I should then rather send a patch) but my example is really based on two functions , and I think that both are very known. I tested race conditions and seems no one exists even if the same prefix for temporary files is given . Someone could extend this function to set always unique prefix based on rand or time value but it seems not necessary becouse GetTempFileName is internally checking for file presence. If somebody could check permissions behaviour I would be glad also. i checked it only on read-only system and just return NULL (proper behaviour) Option T means _O_SHORTLIVED and could be removed in case of security (file is maintained fully in memory if available) Check also http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/gettempfilename.asp Regards Boguslaw Brandys ---------------------------------------------------------------------- Comment By: Aaron W. LaFramboise (aaronwl) Date: 2004-10-17 11:28 Message: Logged In: YES user_id=1040098 I'd say that "simple, fast, and efficient" is something of a myth in generic library code that must cope with diverse situations that its creator may not have foreseen. There are a few problems here: The return values for both functions need to be checked, as both of them can fail. Sometimes this can mean a security problem (some versions of mkstemp() will warn about this situation), but on Windows, as far as I know all versions that enforce user permissions also give each user a different temp dir. I could still see potiential for abuse coming from two programs running as the same user being manipulated in some way by an adversary. "." maybe should be GetTempPath(). I noticed that msvcrt tmpfile() just creates the files in c:\, which is a little odd. Some parts of the documentation imply that it might create files in the pwd. It seems best to use TEMP or TMP though, as GetTempPath() does. This implementation isn't actually standards-conforming, because it doesn't remove the files automatically on close or on program termination (the standard permits either). However, MSVC docs are more strict, stating that the file is removed on close. I beleive this can be accomplished by manipulating the iobuf directly to save the filename. _rmtmp() compatibility with the new tmpfile() would also need to be confirmed. msvc probably also is passing _O_TEMPORARY to _open(), which might cause it to pass FILE_ATTRIBUTE_TEMPORARY to CreateFile(). This is impossible to do through fopen(). The situation here needs to be investigated. Multithreading needs to be examined. This function will probably need to lock a mutex: the gap between fopen() and setting iobuf attributes might cause problems for certain functions, such as _rmtmp(). There might be other things. This is just what popped into my head. In any case, any replacing of a function needs to be thought about very carefully. ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=102435&aid=1048593&group_id=2435 |