ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I'm tired of gcc complaining about my use of tempnam(), so I'd like to find an alternative. However, I need a function that returns a file name, not a file stream, and that doesn't open the file yet. I want to pass the file name to an external editor for input. Can anybody suggest a way of accomplishing this?
I currently have the editor command concatenated with the return from tempnam (), so it ends up something like "vim /tmp/strinXXXXXX", which I can later call with "system (editor_command)". It works just fine, exactly the way I want it to; I just want gcc to quit whining about the fact that tempnam is insecure. (Especially since if I call ':make' from within vim, it gives me the warning and then when I return to the editor it jumps to the line with the tempnam function, which is not where I was working.)
I suggest you stop using tempnam() as the compiler suggests; it has been deprecated (per POSIX.1-2008). Use mkstemp() instead. You can always close the file immediately after it is opened so that you can then use the filename with your preferred application (editor).
So, I have to generate a unique filename myself and make sure it doesn't already exist. How is that more secure than having tempnam do it, given that the security complaint about tempnam is that between the time the file name is generated and the time it is opened, the same name could be generated by another application?
Firstly, read the man page like I should have done first, mkstemp takes a template, the Xs are literally Xs, you don't have to make the unique name.
Quote:
The last six characters of template must be XXXXXX and these are replaced with a string that makes the filename unique... Since it will be modified, template must not be a string constant, but should be declared as a character array.
As for security:
Huh? Security is through users and fileystem permissions, not obfuscated/pseudorandom filenames, no?
If you make the tempfile first, you own it, right? Deny them writing to it before you put contents in it. Edit: seems most systems will create mkstemp tempfiles with 0600.
If they make it first, you can't write to it/can't change it's permissions (or you can because you and this malicious other app are running under the same account which is a user's problem, or they're root and you can't win anyway).
Edit: Again from mkstemp
Quote:
The file is opened with the open(2) O_EXCL flag, guaranteeing that when mkstemp() returns successfully we are the only user.
Also, encrypt contents if it's so important, and don't write the decryption key out, and trust that memory isn't being read?
As for security:
Huh? Security is through users and fileystem permissions, not obfuscated/pseudorandom filenames, no?
If you make the tempfile first, you own it, right? Deny them writing to it before you put contents in it. Edit: seems most systems will create mkstemp tempfiles with 0600.
If they make it first, you can't write to it/can't change it's permissions (or you can because you and this malicious other app are running under the same account which is a user's problem, or they're root and you can't win anyway).
Edit: Again from mkstemp
Also, encrypt contents if it's so important, and don't write the decryption key out, and trust that memory isn't being read?
Warning: Between the time the pathname is constructed and the file is created another process might have created a file with the same name using tmpnam, leading to a possible security hole. The implementation generates names which can hardly be predicted, but when opening the file you should use the O_EXCL flag. Using tmpfile or mkstemp is a safe way to avoid this problem.
If you make the tempfile first, you own it, right? Deny them writing to it before you put contents in it. Edit: seems most systems will create mkstemp tempfiles with 0600.
If they make it first, you can't write to it/can't change it's permissions
But if they put a link to one of your files first, and you don't pass O_EXCL to open, then you will write to your existing file.
I suggest you stop using tempnam() as the compiler suggests; it has been deprecated (per POSIX.1-2008). Use mkstemp() instead. You can always close the file immediately after it is opened so that you can then use the filename with your preferred application (editor).
So mkstemp returns an int. I was using fopen(), as prescribed in all the file I/O tutorials I've seen, later on to read from this temporary file, but it wants a FILE* struct. Do I now have to use something else?
Edit: Never mind, I got confused about which variable I had to pass where for what reason.
Last edited by benav; 08-14-2011 at 12:12 PM.
Reason: Brain not working.
It returns a file descriptor you can "convert" to FILE* using fdopen(). You could use something like this:
Code:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
/* Create a file with an unique name, beginning with the specified prefix.
*
* The file name will be dynamically allocated, and saved in the pointer
* pointed by nameptr. After you are done with the file, you should
* release the dynamically allocated name using free().
*
* If you supply NULL nameptr, the file will be immediately unlinked,
* and the dynamically allocated file name freed. Thus, the file will not
* have a name (except for a brief moment within this function).
* (In this case, the function is similar to tmpfile(), except that this
* function lets you specify the prefix or directory for the file.)
*
* If an error occurs, the function will return NULL with errno set.
*
* Example:
*
* FILE *filehandle;
* char *filename;
*
* filehandle = fopen_unique("/tmp/my-prefix.", &filename);
* if (!filehandle) {
*
* error, check errno [/I]for reason[/I]
*
* } else {
*
* work on the file
*
* fclose(filehandle);
* remove(filename);
* free(filename);
* }
*/
FILE *fopen_unique(char const *const prefix, char **nameptr)
{
size_t const n = (prefix) ? strlen(prefix) : 0;
char *name;
FILE *handle;
int descriptor, result, saved_errno;
if (n < (size_t)1) {
errno = EINVAL;
return NULL;
}
name = malloc(n + 7);
if (!name) {
errno = ENOMEM;
return NULL;
}
memcpy(name, prefix, n);
name[n+0] = 'X';
name[n+1] = 'X';
name[n+2] = 'X';
name[n+3] = 'X';
name[n+4] = 'X';
name[n+5] = 'X';
name[n+6] = 0;
do {
descriptor = mkstemp(name);
} while (descriptor == -1 && errno == EINTR);
if (descriptor == -1) {
saved_errno = errno;
free(name);
errno = saved_errno;
return NULL;
}
if (!nameptr) {
do {
result = unlink(name);
} while (result == -1 && errno == EINTR);
if (result == -1) {
saved_errno = errno;
close(descriptor);
free(name);
errno = saved_errno;
return NULL;
}
free(name);
name = NULL;
} else {
*nameptr = name;
}
do {
handle = fdopen(descriptor, "r+");
} while (handle == NULL && errno == EINTR);
if (!handle) {
saved_errno = errno;
if (name) {
unlink(name);
free(name);
}
close(descriptor);
errno = saved_errno;
return NULL;
}
return handle;
}
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.