Understanding Lua's os.tmpname() on Windows - c

I'm trying to use Lua's os.tmpname() on Windows (which uses tmpnam() under the hood), and I'm a bit puzzled by the filenames it is returning.
> print(os.tmpname())
\s3e8.
If I feed it directly to Lua like io.open(os.tmpname(), "w"), it will attempt to create the file in the root directory of the current drive. This seems pretty inappropriate, since we often don't have the permission to do that.
But according to this thread:
https://mingw-users.narkive.com/L7VR1gxX/temporary-file-woes
This is apparently supposed to be a path relative to the current directory. They mentioned this snippet from a Microsoft documentation:
Note than when a file name is prepended with a back slash and no path
information, such as \fname21, this indicates that the name is valid
for the current working directory.
But I can no longer find the documentation they mentioned in the thread.
I googled around, trying to find the latest documentation and found this:
https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/tempnam-wtempnam-tmpnam-wtmpnam?view=msvc-160
This is the generation rules mentioned in the documentation above:
_tempnam will generate a unique file name for a directory chosen by the following rules:
If the TMP environment variable is defined and set to a valid
directory name, unique file names will be generated for the directory
specified by TMP.
If the TMP environment variable is not defined or if it is set to the
name of a directory that does not exist, _tempnam will use the dir
parameter as the path for which it will generate unique names.
If the TMP environment variable is not defined or if it is set to the
name of a directory that does not exist, and if dir is either NULL or
set to the name of a directory that does not exist, _tempnam will use
the current working directory to generate unique names. Currently, if
both TMP and dir specify names of directories that do not exist, the
_tempnam function call will fail.
I do have the TMP environment variable defined, but Lua always generates the kind of paths I mentioned at the top.
So really, I have two questions:
Is this actually supposed to be a relative path?
If so why does it always generate a relative path, instead of using the standard TMP variables?
I'm testing this with Lua 5.2 from LuaBinaries and the Lua statically built into shinchiro's mpv builds.

According to this thread on lua-users.org you can try passing null.
well i solved it using tmpname(NULL,NULL)... it considers the
temporary directory of the system.
when i use tmpnam() on windows on a non-writable root, the filename
generated (\something) is not writable...
i guess it's an implementation bug
Also note the Lua 5.2 Reference Manual
When possible, you may prefer to use io.tmpfile, which automatically removes the file when the program ends.

Related

How to make my Linux C program accessible from bash

Say I made and compiled a small program in C to count the bytes of a file, called filebyte. To run it I would use ./filebyte
Now I want to make it universal on bash, like for example to run a php file, I would use bash command php file.php, same way I would like to run my program, filebyte filename.
How do I do this?
Thanks!
I often create a bin/ directory in my home directory, for small custom applications.
You then need to add that directory to your PATH, which is a list of colon-separated paths that your shell searches for executables when you type a name on thr command line.
This is usually accomplished by putting this in your ~/.bashrc file:
PATH="$PATH:~/bin"
Check the environment variable PATH and put the executable in one of the directories listed. You can also put it in a custom directory and then append it to PATH. You can check it by executing printenv PATH
If you want it for your current active shell alone, do
export PATH=$PATH:</path/to/file>
For permanently making the file available add the above line to ~/.bashrc
Why add it in PATH variable, man bash says why,
PATH The search path for commands. It is a colon-separated list of
directories in which the shell looks for commands (see COMMAND
EXECUTION below). A zero-length (null) directory name in the
value of PATH indicates the current directory. A null directory
name may appear as two adjacent colons, or as an initial or
trailing colon. The default path is system-dependent, and is set
by the administrator who installs bash. A common value is
''/usr/gnu/bin:/usr/local/bin:/usr/ucb:/bin:/usr/bin''.

Access labels of file through extended filename as directory

I want to list all labels of a specific file in ClearCase. Based on the last approach in the accepted answer at (how to find all the labels for a given file in clearcase) I want to use a combination of cd and dir. I only use dynamic views and as we have thousand of versions I guess this approach is much faster than a slow cleartool query (ClearCase is slow as hell here). For info I work on Windows only.
Here is the mentioned approach:
cd m:/myView/path/to/addon.xml##
# list all files, not directories: the files are the labels
dir /B /A-D
Unfortunately the approach does not work for every file. The strange thing is that the label files do not appear in the directory even if there are labels on the checked-in file. The label files exist only in the branch folders.
The stranger thing is that the following works: copy filename##\labelname targetfile. And even a copy labelname targetname works from within the directory "filename##". I don't get it. Why doesn't dir show these files? I tried all attributes (like hidden files) and so on.
Is this a bug in MVFS or am I missing something? As I said it works for many files but not for all. But I don't know what is different with those files. Maybe the file extension/type? But should this matter?
I don't get it. Why doesn't dir show these files?
Because dir is a Windows command which will list Windows filesystem files, not MVFS (Multi-Version FileSystem) ones, used by a dynamic view.
I don't know what is different with those files. Maybe the file extension/type?
Everything after the ## is a version-extended pathname (see man page), emulated as a Windows file by the MVFS dynamic view.
But should this matter?
If you are using Windows commands (and not cleartool queries), it should not, as those extended paths are supposed to be directly visible by Windows.
They are accessible (copy filename##\labelname targetfile), but should be also visible (listed by a Windows filesystem-based dir command)
In particular, for Version labels in extended namespace:
Version labels appear in the extended namespace as hard links (UNIX and Linux) or as additional files (Windows).
On Windows, if version \main\4 of an element is labeled RLS_1, the extended namespace directory corresponding to the element's main branch lists both 4 and RLS_1:
Z:\myvob\src> dir sort.c##\main
2006-11-10T17:34 1846 4
...
2006-11-10T17:34 1846 RLS_1
If the label type was created with the once-per-element restriction, on Windows, an entry for the labeled version appears in the element's top-level directory:
Z:\myvob\src> dir sort.c## 2006-11-10T17:34 1846 RLS_1
Don't forget also that a pathnames can involve multiple elements:
After a path name crosses over into the extended namespace with ##, you must specify a version for each succeeding element in the path name.
For example:
To automatically select versions for elements proj and src: cross over to extended namespace at directory element include, specifying a version of include and a version of sort.h:
Windows:
\proj_vob\src##\RLS_1\include\RLS_1\sort.h\RLS_1
The OP adds in the comment:
The problem was the once-per-element restriction. This is the default setting in our environment but someone used the once-per-branch setting in his VOB. So the label files could not be created at the top-level directory.
The once-per-element restriction is the mklbtype default.
A mklbtype -pbranch command creates a label type that can be used once on each branch of an element.

Cross-platform directory path validation in C (Linux and Windows)

I have a C function that accepts directory path as a string. The function creates a directory at the given path.
int create_directory(const char *path) {
// given path may be absolute or relative
// step 1:-need to validate the given path(cross platform for both Linux and windows)
// what are the criteria for path validation?
// step 2:- check permission about user accessibility ,means can not create directory, if path is like /usr/bin or /root).but in root login then we create.
So what are the criteria for validation?
// step 3:-if directory, subdirectory already exist at the path, then return?
// step 4:-if not exists then create directory ;
}
basically I have problem in step 1 and step 2. I am not able to identify what the exact criteria for path validation are.
The best way to check the validity of a path given to you is to try the operation with it. The OS will give you an error code (errno or GetLastError() or something) and you can use that to determine why it wasn't possible.
I would let the underlying OS perform the validation.
Create the directory and then check the error code.
Linux uses the "/" to separate between directories in a given path while windows uses "\" plus almost all the windows paths begin with C:\\ or (D:\\ it doesn't matter the most important is the :) so you can just use a strchr() to look for those signs or you can just use perror() which is much easier (you'll have to include <errno.h>)

Creating a unique temporary directory from pure C in windows

I'd like to create a unique temporary directory in Windows from some C
code (not C++ or C#). I want to do this so that I can put some temp
files in the directory, and then delete them all easily when I'm done
(by removing the directory recursively).
I'm essentially looking for an equivalent of the linux
mkdtemp
function. There is a C# answer here, and responses on this
question
suggest using Boost. But since I'm using C, those solutions don't work
for me.
The best I've been able to come up with so far is to use
GetTempFileName
followed by CreateDirectory,
but the problem there is that if I ask
GetTempFileName
to create a unique file name, it will also create the file (which I
don't want, since I want to make a directory instead).
Relatedly, there's
GetTempPath,
which returns the location of the user's temp folder from environment
variables - but since I want to create my own directory that I can
safely delete later, I still need to create a directory inside any
path it would return.
It looks like if I want a unique directory to be created, I'll have to
create a temp file, get the name, delete it, and then create a
directory with the same name - which sounds very messy.
Any other ideas?
You can use what GetTempPath returns concatenated with a Guid to ensure uniqueness of the directory. You can create a Guid using UuidCreate or CoCreateGuid Function.
To delete recursively the directory, there is an example here in pure C: How to remove directory recursively? based on FindFirstFile, FindNextFile, DeleteFile and RemoveDirectory.
There is also SHFileOperation but it's more heavyweight and is based on the Windows Shell functions, and the Shell DLLs are not always wanted, especially if you're writing server code.
Use GetTempPath then CreateDirectory with a random name under it, optionally retrying if CreateDirectory fails due to it already existing. But if your name generation is good enough, the likelihood of a collision with an existing name is much smaller than the likelihood of a blackhat guessing your password or even your private key, so you might as well ignore it.
Use _tempnam tmpnam_s to create a filename that doesn't exist yet, and then use CreateDirectory to create the directory. There's technically a race condition if you do this, in that another process could potentially create a file or directory with that name in the time in between when you generate the filename and when you create the directory, but the odds of that are rather unlikely. To protect against that, you can loop until you succeed.
For recursively removing a directory tree, you can use SHFileOperation. Alternatively, you can do the directory traversal yourself with FindFirstFile/FindNextFile, DeleteFile, and RemoveDirectory.
If you want to remove the directory automatically upon exiting, register a function using atexit. This will only work for normal program termination (i.e. via the exit function or via returning from main/WinMain). This will not work for abnormal program termination (e.g. via abort, an access violation, someone else calling TerminateProcess, etc.).

What's the relative order with which Windows search for executable files in PATH?

If I have a.com, a.cmd, a.bat, and a.exe files in my %PATH%, which one would Windows pick if I invoke just the command a? Is this officially spec-ed somewhere by Microsoft?
I just wanted to wrap my gvim.exe executable with -n, but my gvim.bat doesn't appear to get run neither from the command line, nor from the Run dialog.
See the command search sequence on Microsoft Docs
The PATH and PATHEXT environmental variables each provide an element of the search sequence: PATH is the ordered list of directories "where" to look, and PATHEXT is the ordered list of file extensions ("what") to look for (in case the extension isn't explicitly provided on the command line). Prior to using the PATH however, the current directory is searched.
The PATHEXT variable defaults to ".COM;.EXE;.BAT;.CMD"
Summarized from the Microsoft Technet link provided by mjv:
Windows will step through the directories in PATH from left to right (normal list order).
In each of these, it attempts to locate a file with each PATHEXT also left to right, before continuing to the next PATH entry.
The first file it finds wins.
So, in your case, you need to change PATHEXT so that .BAT comes before .EXE (or it will always find .exe first and not the .bat you most likely want to override it, if in the same directory) and also put the path of your 'override' gvim.bat earlier (earliest?) in the PATH listing than anywhere it could find gvim.* (because it tries every PATHEXT in each before going on down PATH)
I believe it walks through %PATHEXT% and tries each of those

Resources