A tempdir I didn't want

Today I had a suprising using my rust program on a windows system I did not know before (and won't be able to use again and don't know a lot about..). I'm creating a temporary directory using the tempfile crate, using the following code:

tempfile::Builder::new().prefix("ZRS_").tempdir() 

This works fine all the time, but on this specific system I got the following directory: C:\Users\USER~1.NAM\AppData\Local\Temp\ZRS_W8JZVw (the letters of USER and NAM are different ones, but still ascii only. I changed them because the resemble the real user name). This wrought havoc, because of the tilde included - I'm putting this into a LaTex file, and LaTex is very finicky when it comes to non-alphabetic chars.

So, if anyone can answer any of the following questions, I'd be really grateful:

  1. Why is there a tilde? I kinda recognize something from DOS or older versions of windows, but this was on windows 10.
  2. Is there a way to avoid special chars in the path? I have found no fitting argument to any of the functions of tempfile, but I'd rather avoid anything except alphabetical chars and numbers. But I think tempfile only created ZRS_W8JZVw, which does fit the bill nicely...
  3. Is there a good strategy dealing with that? I'm pondering checking for the tilde, and if I find one I'd just try to create a tempdir in C:\ directly. Or is there a better way? I'm not even sure what can actually happen, so I might check for "only alphabetical and numbers" and then go for the alternative, just to be sure.

Thanks for any pointers!

It's because your username is longer than what fits into the ancient "8.3" filename format. This is a peculiarty of NTFS.

I'm no Windows user, but according to this, you can edit the value of the key HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisable8dot3NameCreation in the registry in order to avoid this old and annoying behavior.

Thanks a lot, but

I don't really have control over the systems my software is running on, and my users are very non-technical. I was kinda hoping for a solution I can implement directly in my code, like a tempfile function I did overlook or something...

Well, but if that is the reason I fell my workaround looks kinda solid, so maybe that's just what it takes. Thanks!

Short answer: Use canonicalize on the path you get.

Long answer:

Under the hood it's using GetTempPath2W which in turn gets whatever value is the TMP environment variable. It's possible the user changed it for some reason (maybe a side effect of some other software they ran). You can get back the long path using canonicalize.

Most morally correct answer: Use a library to properly escape paths for use in LaTex

3 Likes

canonicalize fails for network drives on windows. The syscall used by canonicalize is simply not implemented for network drives. If you use canonicalize you should probably add a fallback to using the non-canonicalized path if canonicalization failed.

1 Like

While that's good advice I'd note that using the non-canonicalized path was the issue in the first place. :wink:

(also, as an aside, the issue isn't "network drives" it's a specific third party driver, that's mostly used for a popular RAM disk).

2 Likes

Do you know of one? Neither google nor crates.io would help me out here.

That sounds pretty reasonable. Except, this returns UNC paths, which aren't usable with LaTeX as well. I guess I could chop of the starting \\?\, but I heard this is error prone (for reasons I did not understand).

Sorry, I don't know. Maybe there isn't one yet.

You could use dunce - Rust

2 Likes

Uhh that seems to be the final missing piece of the puzzle, thanks a lot!

Thanks for the correction!