Re: How to pass filenames to system( ) ?
Re: How to pass filenames to system( ) ?
- Subject: Re: How to pass filenames to system( ) ?
- From: Quinn <email@hidden>
- Date: Wed, 3 Mar 2010 12:16:11 +0000
At 09:33 +0100 3/3/10, Patrick Stadelmann wrote:
What do I need to do ? Is there a function I need to call to escape
problematic characters in the filename ? Or a doc explaining how to
write such function ?
The simple answer here is... don't use system(). It's evil, for this
reason, and for others. There are high-level alternatives, like
NSTask, that don't run a shell and hence don't have this problem.
Even if you need to stick with low-level routines, you can pass wacky
paths to fork/exec and posix_spawn without any problems.
The above is especially true if your code is running with privileges.
You really don't want to use system() in privileged code.
If you have to use system(), you will run into various gotchas like
the one you described. You will have to parse each path and apply
quoting. AFAIK there's no C-language routine to do this, but it's
not too hard to do. I know I've written this code before, but I
wasn't able to unearth it, alas. The basic idea is:
1. go through every byte of the string
2. if the byte is a reasonable value, pass it through unquoted
3. otherwise quote the byte by prefixing it with slosh ('\')
The exact definition of reasonable is tricky but, to be on the safe
side, you can just say that the alphanumerics and underscore are
reasonable, and everything else is not.
Oh, cool, I finally managed to track down my code.
static char * CreateQuotedStringWithString(const char *str)
{
char * result;
size_t resultIndex;
size_t strIndex;
size_t strLength;
int pass;
char ch;
// The first pass calculates the result string length, the
// second pass actually populates the result string.
result = NULL;
strLength = strlen(str);
for (pass = 0; pass < 2; pass++) {
resultIndex = 0;
for (strIndex = 0; strIndex < strLength; strIndex++) {
ch = str[strIndex];
// I avoid isalpha and so on here because I don't
// trust them to work independent of localisation.
if ( ((ch >= '0') && (ch <= '9'))
|| ((ch >= 'A') && (ch <= 'Z'))
|| ((ch >= 'a') && (ch <= 'z'))
|| (ch == '_') ) {
if (result != NULL) {
result[resultIndex] = ch;
}
resultIndex += 1;
} else {
if (result != NULL) {
result[resultIndex] = '\\';
result[resultIndex + 1] = ch;
}
resultIndex += 2;
}
}
// At the end of the first pass, allocate the result
// string. At the end of the second pass, put in the
// null terminator.
if (pass == 0) {
result = malloc(resultIndex + 1);
assert(result != NULL);
} else {
result[resultIndex] = 0;
}
}
return result;
}
S+E
--
Quinn "The Eskimo!" <http://www.apple.com/developer/>
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Filesystem-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden