Reputation: 1518
I am trying to create a directory with log entries with mkstemp
. But, to my understanding I mustn't pass a string constant to mkstemp
. I allocate memory for the string and use snprintf
to format the output which I thought was going to work but mkstemp
returns a negative value setting errno to EINVAL.
However, in the linux manual for mkstemp
it clearly says:
EINVAL For mkstemp() and mkostemp(): The last six characters of template were not XXXXXX; now template is unchanged.
Furhtermore mkstemp
never modifies my dynamic string.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LOG_DIR "/tmp"
int main(int argc, char **argv) {
char *fname;
FILE *fp;
if(argc != 3) {
fprintf(stderr, "Usage: %s <msg> <severity>\n", argv[0]);
return 0;
}
int length = snprintf(NULL, 0, "%s/log_entry.XXXXXX", LOG_DIR); // snprintf returns the required length for my string
if(length < 0) {
perror("snprintf failed");
return 1;
}
fname = malloc(sizeof(char) * length); // allocate memory for fname based on the return value of snprintf
snprintf(fname, length, "%s/log_entry.XXXXXX", LOG_DIR); // send formatted output into fname
int fd = mkstemp(fname); // this returns -1 and errno is set to 22
if(fd < 0) {
perror("failed to create entry file");
return 1;
}
fp = fdopen(fd, "w");
if(fp == NULL) {
perror("failed to open entry file");
return 1;
}
fprintf(fp, "\"%s\" %d ",argv[1], atoi(argv[2]));
fflush(fp);
fclose(fp);
free(fname);
return 0;
}
This snippet spits out an error on both of my Linux machines however if I remove the dynamic allocated string and explicitly set fname
it works
char fname[] = "/tmp/log_entry.XXXXXX";
Upvotes: 0
Views: 655
Reputation: 25286
fname = malloc(sizeof(char) * length);
should be:
fname = malloc(sizeof(char) * (length + 1));
Now
snprintf(fname, length+1, "%s/log_entry.XXXXXX", LOG_DIR);
will create the filename. In your version, the filename did not end with 6 'X's which made mkstemp
fail.
Upvotes: 2
Reputation: 16607
fname = malloc(sizeof(char) * length);
You fill it completely , leave no space for '\0'
. :eave a space for null terminator -
fname = malloc(sizeof(char) *(length+1));
Then increase length in snprintf
also to length+1
.
Upvotes: 1