1
/*********************************************************
2
* Copyright (C) 2008 VMware, Inc. All rights reserved.
4
* The contents of this file are subject to the terms of the Common
5
* Development and Distribution License (the "License") version 1.0
6
* and no later version. You may not use this file except in
7
* compliance with the License.
9
* You can obtain a copy of the License at
10
* http://www.opensource.org/licenses/cddl1.php
12
* See the License for the specific language governing permissions
13
* and limitations under the License.
15
*********************************************************/
20
* Escape and unescape illegal filenames for different platforms.
25
# include "driver-config.h"
26
# include <linux/string.h>
27
#elif defined(__FreeBSD__)
29
# include <sys/libkern.h>
30
# define strchr(s,c) index(s,c)
34
# define memmove(s1,s2,n) bcopy(s2,s1,n)
35
#elif defined(__APPLE__) && defined(KERNEL)
45
#include "hgfsEscape.h"
50
#define UNREFERENCED_PARAMETER(P) (P)
52
/* These characters are illegal in Windows file names. */
53
const char* HGFS_ILLEGAL_CHARS = "/\\*?:\"<>|";
54
const char* HGFS_SUBSTITUTE_CHARS = "!@#$^&(){}";
55
/* Last character of a file name in Windows can be neither dot nor space. */
56
const char* HGFS_ILLEGAL_LAST_CHARS = ". ";
58
/* http://msdn.microsoft.com/en-us/library/aa365247.aspx */
59
char *HgfsReservedNames[] = {"CON", "PRN", "AUX", "NUL"};
60
char *HgfsReservedNamesWithNumber[] = {"COM", "LPT"};
62
#define HGFS_RESERVED_NAME_CHARS_LENGTH 3
63
#define HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH (HGFS_RESERVED_NAME_CHARS_LENGTH + 1)
64
/* Check for special escaping cases - reserved names and illegal last characters. */
65
#define IS_SPECIAL_CASE_ESCAPE(b,o,l) HgfsIsSpecialCaseEscape(b,o,l)
66
/* Process Windows reserved names. */
67
#define PROCESS_RESERVED_NAME(b,s,p,o,c) \
68
if (!HgfsProcessReservedName(b,s,p,o,c)) \
72
/* Process Windows reserved names. */
73
#define PROCESS_LAST_CHARACTER(b,s,p,c) \
74
if (!HgfsProcessLastCharacter(b,s,p,c)) \
81
#define UNREFERENCED_PARAMETER(P)
82
/* There is no special escape sequences on other than Windows platforms. */
83
#define IS_SPECIAL_CASE_ESCAPE(b,o,l) FALSE
84
/* There is no reserved names on other then Windows platforms. */
85
#define PROCESS_RESERVED_NAME(b,s,p,o,c)
86
/* There is no special processing for the last character on non-Windows platforms. */
87
#define PROCESS_LAST_CHARACTER(b,s,p,c)
89
#if defined(__APPLE__)
90
/* These characters are illegal in MAC OS file names. */
91
const char* HGFS_ILLEGAL_CHARS = "/:";
92
const char* HGFS_SUBSTITUTE_CHARS = "!&";
94
/* These characters are illegal in Linux file names. */
95
const char* HGFS_ILLEGAL_CHARS = "/";
96
const char* HGFS_SUBSTITUTE_CHARS = "!";
101
#define HGFS_ESCAPE_CHAR '%'
102
#define HGFS_ESCAPE_SUBSTITUE_CHAR ']'
105
HGFS_ESCAPE_ILLEGAL_CHARACTER,
106
HGFS_ESCAPE_RESERVED_NAME,
107
HGFS_ESCAPE_ILLEGAL_LAST_CHARACTER,
108
HGFS_ESCAPE_ESCAPE_SEQUENCE,
113
typedef Bool (*HgfsEnumCallback)(char const *bufIn,
115
HgfsEscapeReason reason,
119
* The structure is used by HgfsAddEscapeCharacter to keep context information between
121
* All offsets defined in this structure are in characters, not bytes
124
uint32 processedOffset; // Offset of the first unprocessed input character
125
uint32 outputBufferLength; // Number of characters in the output buffer
126
uint32 outputOffset; // Number of characters that are already in the output
127
char *outputBuffer; // Pointer to the output buffer
130
static void HgfsEscapeUndoComponent(char *bufIn, uint32 *totalLength);
131
static int HgfsEscapeGetComponentSize(char const *bufIn, uint32 sizeIn);
132
static int HgfsEscapeDoComponent(char const *bufIn, uint32 sizeIn, uint32 sizeBufOut,
136
*-----------------------------------------------------------------------------
138
* HgfsAddEscapeCharacter --
140
* Callback function that is called by HgfsEnumerate to insert an escape sequence
141
* into the input name.
144
* TRUE if successful, FALSE if there is an error like the output buffer is
148
* Updates the output buffer pointer (stored in the context variable).
150
*-----------------------------------------------------------------------------
154
HgfsAddEscapeCharacter(char const * bufIn, // IN: input name
155
uint32 offset, // IN: offset that requires escaping
156
HgfsEscapeReason reason, // IN: reason for esaping
157
void *context) // IN/OUT: convertion context
159
HgfsEscapeContext *escapeContext = (HgfsEscapeContext *)context;
160
uint32 charactersToCopy;
165
ASSERT(offset >= escapeContext->processedOffset); // Scanning forward
166
charactersToCopy = offset - escapeContext->processedOffset;
168
if (escapeContext->outputOffset + charactersToCopy >
169
escapeContext->outputBufferLength) {
173
memcpy(escapeContext->outputBuffer + escapeContext->outputOffset,
174
bufIn + escapeContext->processedOffset, charactersToCopy * sizeof *bufIn);
175
escapeContext->outputOffset += charactersToCopy;
176
escapeContext->processedOffset += charactersToCopy;
178
outputSpace = escapeContext->outputBufferLength - escapeContext->outputOffset;
181
case HGFS_ESCAPE_ILLEGAL_CHARACTER:
182
if (outputSpace < 2) {
185
illegal = strchr(HGFS_ILLEGAL_CHARS, bufIn[escapeContext->processedOffset]);
186
escapeContext->processedOffset++; // Skip illegal input character
187
ASSERT(illegal != NULL);
188
escapeContext->outputBuffer[escapeContext->outputOffset] =
189
HGFS_SUBSTITUTE_CHARS[illegal - HGFS_ILLEGAL_CHARS];
190
escapeContext->outputOffset++;
191
escapeContext->outputBuffer[escapeContext->outputOffset] = HGFS_ESCAPE_CHAR;
192
escapeContext->outputOffset++;
195
case HGFS_ESCAPE_RESERVED_NAME:
196
if (outputSpace < 1) {
199
escapeContext->outputBuffer[escapeContext->outputOffset] = HGFS_ESCAPE_CHAR;
200
escapeContext->outputOffset++;
203
case HGFS_ESCAPE_ILLEGAL_LAST_CHARACTER:
204
if (outputSpace < 1) {
207
escapeContext->outputBuffer[escapeContext->outputOffset] = HGFS_ESCAPE_CHAR;
208
escapeContext->outputOffset++;
211
case HGFS_ESCAPE_ESCAPE_SEQUENCE:
212
if (outputSpace < 2) {
215
escapeContext->processedOffset++; // Skip input esape character
216
escapeContext->outputBuffer[escapeContext->outputOffset] = HGFS_ESCAPE_SUBSTITUE_CHAR;
217
escapeContext->outputOffset++;
218
escapeContext->outputBuffer[escapeContext->outputOffset] = HGFS_ESCAPE_CHAR;
219
escapeContext->outputOffset++;
222
case HGFS_ESCAPE_COMPLETE:
223
if (outputSpace < 1) {
226
escapeContext->outputBuffer[escapeContext->outputOffset] = '\0';
238
*-----------------------------------------------------------------------------
240
* HgfsCountEscapeChars --
242
* Callback function that is called by HgfsEnumerate to count additional characters
243
* that need to be inserted in the input name.
246
* TRUE since it never fails.
251
*-----------------------------------------------------------------------------
255
HgfsCountEscapeChars(char const *bufIn, // IN: input name
256
uint32 offset, // IN: offset where escape is needed
257
HgfsEscapeReason reason, // IN: reason for escaping
258
void *context) // IN/OUT: context info
260
UNREFERENCED_PARAMETER(bufIn);
261
UNREFERENCED_PARAMETER(offset);
262
if (reason != HGFS_ESCAPE_COMPLETE) {
263
uint32 *counter = (uint32*)context;
272
*-----------------------------------------------------------------------------
274
* HgfsLetterToUpper --
276
* Converts lowercase English letters to uppercase.
277
* If the symbol is not a lowercase English letter returns the original character.
280
* Converted character.
285
*-----------------------------------------------------------------------------
289
HgfsLetterToUpper(char letter)
291
if (letter >= 'a' && letter <= 'z') {
292
return letter - ('a' - 'A');
299
*-----------------------------------------------------------------------------
301
* HgfsIsEqualPrefix --
303
* Verifies if the string prefix is equal to the given prefix.
304
* It assumes that the prefix includes only uppercase English letters or numbers
305
* and it does not have any international characters.
306
* The string must be either NULL terminated or not shorter then the prefix.
309
* TRUE if the uppcased string starts with the given prefix. False otherwise.
314
*-----------------------------------------------------------------------------
318
HgfsIsEqualPrefix(char const *prefix, // IN: prefix to check
319
char const *string, // IN: input string
320
uint32 prefixLength) // IN: length of the prefix in characters
323
for (i = 0; i < prefixLength; i++) {
324
ASSERT(prefix[i] > 0 && (prefix[i] < 'a' || prefix[i] > 'z' ));
325
if (prefix[i] != HgfsLetterToUpper(string[i])) {
334
*-----------------------------------------------------------------------------
336
* HgfsIsReservedPrefix --
338
* Verifies if the name's prefix is one of the reserved names.
341
* TRUE if the name's prefix is one of the reserved names.
346
*-----------------------------------------------------------------------------
350
HgfsIsReservedPrefix(char const *bufIn) // IN: input name
353
for (i = 0; i < ARRAYSIZE(HgfsReservedNames); i++) {
354
if (HgfsIsEqualPrefix(HgfsReservedNames[i], bufIn,
355
HGFS_RESERVED_NAME_CHARS_LENGTH)) {
364
*-----------------------------------------------------------------------------
366
* HgfsIsReservedPrefixWithNumber --
368
* Verifies if the name's prefix is one of the reserved names with number:
372
* TRUE if the name's prefix is one of the reserved names with number.
377
*-----------------------------------------------------------------------------
381
HgfsIsReservedPrefixWithNumber(char const *bufIn) // IN: input name
384
for (i = 0; i < ARRAYSIZE(HgfsReservedNamesWithNumber); i++) {
385
if (HgfsIsEqualPrefix(HgfsReservedNamesWithNumber[i], bufIn,
386
HGFS_RESERVED_NAME_CHARS_LENGTH) &&
387
bufIn[HGFS_RESERVED_NAME_CHARS_LENGTH] >= '1' &&
388
bufIn[HGFS_RESERVED_NAME_CHARS_LENGTH] <= '9') {
397
*-----------------------------------------------------------------------------
399
* HgfsIsSpecialCaseEscape --
401
* Verifies if the escape character is a part of special case escape sequence
402
* that exists only in Windows - escaped reserved name or escaped illegal last
406
* TRUE if the name's prefix is one of the reserved names with number.
411
*-----------------------------------------------------------------------------
415
HgfsIsSpecialCaseEscape(char const *bufIn, // IN: input name
416
uint32 offset, // IN: offset of the escape character
417
uint32 length) // IN: length of the name in characters
419
if (offset + 1 == length &&
420
strchr(HGFS_ILLEGAL_LAST_CHARS, bufIn[offset - 1]) != NULL) {
423
if (offset == HGFS_RESERVED_NAME_CHARS_LENGTH &&
424
(length == HGFS_RESERVED_NAME_CHARS_LENGTH + 1 || bufIn[offset+1] == '.')) {
425
return HgfsIsReservedPrefix(bufIn);
427
if (offset == HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH &&
428
(length == HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH + 1 ||
429
bufIn[offset+1] == '.')) {
430
return HgfsIsReservedPrefixWithNumber(bufIn);
437
*-----------------------------------------------------------------------------
439
* HgfsProcessReservedName --
441
* Verifies if the name is one of reserved Windows file names.
442
* If it is a reserved name invokes callback that performs required
446
* TRUE if no processing is required of if processing succeeded,
447
* FALSE if processing failed.
452
*-----------------------------------------------------------------------------
456
HgfsProcessReservedName(char const *bufIn, // IN: Unescaped input buffer
457
uint32 sizeIn, // IN: Length of the input
458
HgfsEnumCallback processEscape, // IN: Callack that is invoked
459
// if input is reserved name
460
uint32 *offset, // OUT: New offset in the input
461
void *context) // IN/OUT: Context for callback
463
/* Look reserved names: CON, PRN, AUX, NUL. */
464
if (sizeIn >= HGFS_RESERVED_NAME_CHARS_LENGTH && HgfsIsReservedPrefix(bufIn)) {
465
if (HGFS_RESERVED_NAME_CHARS_LENGTH == sizeIn ||
466
bufIn[HGFS_RESERVED_NAME_CHARS_LENGTH] == '.') {
467
if (!processEscape(bufIn, HGFS_RESERVED_NAME_CHARS_LENGTH,
468
HGFS_ESCAPE_RESERVED_NAME, context)) {
471
*offset = HGFS_RESERVED_NAME_CHARS_LENGTH;
475
/* Look reserved names with numbers: COM1-9 and LPT1-9. */
476
if (sizeIn >= HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH &&
477
HgfsIsReservedPrefixWithNumber(bufIn)) {
478
if (HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH == sizeIn ||
479
bufIn[HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH] == '.') {
480
if (!processEscape(bufIn, HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH,
481
HGFS_ESCAPE_RESERVED_NAME, context)) {
484
*offset = HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH;
492
*-----------------------------------------------------------------------------
494
* HgfsProcessLastCharacter --
496
* Verifies if the trailing character in the name is a valid last character.
497
* In Windows it is illegal to have a file name that ends with dot ('.') or
498
* space (' '). The only exception is "." and ".." directory names.
499
* If the last character is invalid the function invokes a callback to process it.
502
* TRUE if no processing is required of if processing succeeded,
503
* FALSE if processing failed.
508
*-----------------------------------------------------------------------------
512
HgfsProcessLastCharacter(char const *bufIn, // IN: Unescaped input buffer
513
uint32 sizeIn, // IN: Length of the input
514
HgfsEnumCallback processEscape, // IN: Callack that is invoked
515
// when escaping is needed
516
void *context) // IN/OUT: Callback context
519
/* If the filename is '.' or '..' we shouldn't escape it. */
520
if ((sizeIn == 1 && bufIn[0] == '.') ||
521
(sizeIn == 2 && bufIn[0] == '.' && bufIn[1] == '.')) {
525
/* Invoke the callback if the last character is illegal. */
526
if (strchr(HGFS_ILLEGAL_LAST_CHARS, bufIn[sizeIn - 1]) != NULL) {
527
if (!processEscape(bufIn, sizeIn, HGFS_ESCAPE_ILLEGAL_LAST_CHARACTER, context)) {
538
*-----------------------------------------------------------------------------
540
* HgfsIsEscapeSequence --
542
* Verifies if input buffer has an escape sequence at the position
546
* TRUE if there is an escape sequence at the position defined by offset.
551
*-----------------------------------------------------------------------------
555
HgfsIsEscapeSequence(char const *bufIn, // IN: input name
556
uint32 offset, // IN: offset of the escape character
557
uint32 length) // IN: length of the name in characters
559
if (bufIn[offset] == HGFS_ESCAPE_CHAR && offset > 0) {
561
if (bufIn[offset - 1] == HGFS_ESCAPE_SUBSTITUE_CHAR) {
564
substitute = strchr(HGFS_SUBSTITUTE_CHARS, bufIn[offset - 1]);
565
if (substitute != NULL) {
568
return IS_SPECIAL_CASE_ESCAPE(bufIn,offset,length);
575
*-----------------------------------------------------------------------------
577
* HgfsEscapeEnumerate --
579
* The function scans the input buffer and calls processEscape callback for every
580
* place in the input buffer which require escaping.
582
* Callback does the required processing. There are two different callbacks -
583
* one counts extra symbols that are needed for escaping and another produces
584
* escaped output name based on input name.
586
* 1. The first function calculates number of extra characters. It just increments
587
* a counter which is passed to it in context variable every time it is called
588
* for the reason different from "complete processing" assuming that
589
* exactly one extra character is required to escape any invalid input.
591
* 2. The second function produces output name by copying everything from input
592
* name into the output name up to the place which require escaping and
593
* then inserts appropriate escape sequence into the output. It keeps track of its
594
* progress and keeps pointer to the output buffer in the context variable.
595
* HgfsEscapeEnumerate calls calback function one more time at the end of the
596
* input buffer to let callback finish processing of the input (for example copy
597
* the rest of the name after the last escape sequence from input buffer to
601
* TRUE if the input has been processed successfully by the callback, false otherwise.
606
*-----------------------------------------------------------------------------
610
HgfsEscapeEnumerate(char const *bufIn, // IN: Buffer with unescaped input
611
uint32 sizeIn, // IN: Number of input *characters*
612
HgfsEnumCallback processEscape, // IN: Callack that is invoked every
613
// time escaping is required
614
void *context) // IN/OUT: Context for processEscape
616
/* First look for invalid characters in the input name. */
617
uint32 i, offset = 0;
622
ASSERT(processEscape);
624
PROCESS_RESERVED_NAME(bufIn, sizeIn, processEscape, &offset, context);
626
for (i = offset; i < sizeIn; i++) {
627
if (strchr(HGFS_ILLEGAL_CHARS, bufIn[i]) != NULL) {
628
if (!processEscape(bufIn, i, HGFS_ESCAPE_ILLEGAL_CHARACTER, context)) {
631
} else if (HgfsIsEscapeSequence(bufIn, i, sizeIn)) {
632
if (!processEscape(bufIn, i, HGFS_ESCAPE_ESCAPE_SEQUENCE, context)) {
638
PROCESS_LAST_CHARACTER(bufIn, sizeIn, processEscape, context);
640
if (!processEscape(bufIn, sizeIn, HGFS_ESCAPE_COMPLETE, context)) {
649
*-----------------------------------------------------------------------------
653
* Escape any characters that are not legal in a windows filename.
654
* Escape reserved file names that can't be used in Windows.
655
* We also of course have to escape the escape character, which is "%",
656
* when it is part of a character sequence that would require unescaping
658
* sizeBufOut must account for the NUL terminator.
661
* On success, the size (excluding the NUL terminator) of the
662
* escaped, NUL terminated buffer.
663
* On failure (bufOut not big enough to hold result), negative value.
668
*-----------------------------------------------------------------------------
672
HgfsEscape_Do(char const *bufIn, // IN: Buffer with unescaped input
673
uint32 sizeIn, // IN: Size of input buffer
674
uint32 sizeBufOut, // IN: Size of output buffer
675
char *bufOut) // OUT: Buffer for escaped output
677
const char *currentComponent = bufIn;
678
uint32 sizeLeft = sizeBufOut;
679
char *outPointer = bufOut;
680
const char *end = bufIn + sizeIn;
683
if (bufIn[sizeIn - 1] == '\0') {
685
* In some cases a NUL terminated string is passed to HgfsEscape_Do
686
* so it make sense to support such input even if CPName_GetComponent
687
* does not. Detect this case and make the input compliant with
688
* CPName_GetComponent by removing terminating NUL.
694
* Absolute symbolic link name starts with the '\0'. HgfsEscapeDo needs to work
695
* with such names. Leading NULL symbols should be skipped here since
696
* CPName_GetComponent does not support such names.
698
while (*currentComponent == '\0' && currentComponent - bufIn < sizeIn) {
701
*outPointer++ = '\0';
703
while (currentComponent - bufIn < sizeIn) {
705
uint32 componentSize = CPName_GetComponent(currentComponent, end, &next);
707
escapedLength = HgfsEscapeDoComponent(currentComponent, componentSize,
708
sizeLeft, outPointer);
709
if (escapedLength < 0) {
710
return escapedLength;
712
currentComponent = next;
713
sizeLeft -= escapedLength + 1;
714
outPointer += escapedLength + 1;
716
return (int) (outPointer - bufOut) - 1; // Do not count the last NUL terminator
720
*-----------------------------------------------------------------------------
722
* HgfsEscape_GetSize --
724
* Calculates required size in bytes for the buffer that is needed to hold escaped
725
* cross platform path name. Returns 0 if no escaping is required.
728
* On success, the size (excluding the NUL terminator) of the
729
* escaped, NUL terminated buffer.
730
* Returns 0 if the name is a valid Windows file name.
735
*-----------------------------------------------------------------------------
739
HgfsEscape_GetSize(char const *bufIn, // IN: Buffer with unescaped input
740
uint32 sizeIn) // IN: Size of the input buffer
743
const char *currentComponent = bufIn;
744
const char *end = bufIn + sizeIn;
747
if (sizeIn == 0) { // No need toescape empty name.
750
if (bufIn[sizeIn - 1] == '\0') {
752
* In some cases a NUL terminated string is passed to HgfsEscape_GeSize
753
* so it make sense to support such input even if CPName_GetComponent
754
* does not. Detect this case and make the input compliant with
755
* CPName_GetComponent by removing terminating NUL.
760
/* Skip leading NULs to keep CPName_GetComponent happy. */
761
while (*currentComponent == '\0' && currentComponent - bufIn < sizeIn) {
764
while (currentComponent - bufIn < sizeIn) {
765
uint32 componentSize = CPName_GetComponent(currentComponent, end, &next);
766
result += HgfsEscapeGetComponentSize(currentComponent, componentSize);
767
currentComponent = next;
769
return (result == 0) ? 0 : result + sizeIn;
774
*-----------------------------------------------------------------------------
778
* Unescape a buffer that was escaped using HgfsEscapeBuffer.
780
* The unescaping is done in place in the input buffer, and
784
* The size (excluding the NUL terminator) of the unescaped, NUL
790
*-----------------------------------------------------------------------------
794
HgfsEscape_Undo(char *bufIn, // IN: Characters to be unescaped
795
uint32 sizeIn) // IN: Number of characters in bufIn
797
uint32 componentSize = strlen(bufIn) + 1;
798
uint32 unprocessedSize = sizeIn + 1;
800
char *currentComponent = bufIn;
801
while (currentComponent != NULL) {
802
HgfsEscapeUndoComponent(currentComponent, &unprocessedSize);
803
componentSize = strlen(currentComponent) + 1; // Unescaped size
804
result += componentSize;
805
if (unprocessedSize > 1) {
806
currentComponent = currentComponent + componentSize;
807
componentSize = strlen(currentComponent) + 1; // Size of the next component
809
currentComponent = NULL;
817
*-----------------------------------------------------------------------------
819
* HgfsEscapeUndoComponent --
821
* Unescape a buffer that was escaped using HgfsEscapeBuffer.
823
* The unescaping is done in place in the input buffer, and
832
*-----------------------------------------------------------------------------
836
HgfsEscapeUndoComponent(char *bufIn, // IN: Characters to be unescaped
837
uint32 *unprocessedLength) // IN: Unprocessed characters
841
size_t sizeIn = strlen(bufIn);
842
char* curOutBuffer = bufIn;
846
escapePointer = strchr(curOutBuffer, HGFS_ESCAPE_CHAR);
847
while (escapePointer != NULL) {
848
offset = escapePointer - bufIn;
849
if (HgfsIsEscapeSequence(bufIn, offset, sizeIn)) {
850
char* substitute = strchr(HGFS_SUBSTITUTE_CHARS, bufIn[offset - 1]);
851
if (substitute != NULL) {
852
bufIn[offset - 1] = HGFS_ILLEGAL_CHARS[substitute - HGFS_SUBSTITUTE_CHARS];
853
} else if (bufIn[offset - 1] == HGFS_ESCAPE_SUBSTITUE_CHAR) {
854
bufIn[offset - 1] = HGFS_ESCAPE_CHAR;
856
memmove(escapePointer, escapePointer + 1, (*unprocessedLength) - offset - 1);
857
(*unprocessedLength)--;
860
escapePointer = strchr(escapePointer, HGFS_ESCAPE_CHAR);
862
escapePointer = NULL;
865
escapePointer = strchr(escapePointer + 1, HGFS_ESCAPE_CHAR);
868
ASSERT((*unprocessedLength) > sizeIn);
869
(*unprocessedLength) -= sizeIn + 1;
874
*-----------------------------------------------------------------------------
876
* HgfsEscapeDoComponent --
878
* Escape any characters that are not legal in a windows filename.
879
* Escape reserved file names that can't be used in Windows.
880
* We also of course have to escape the escape character, which is "%",
881
* when it is part of a character sequence that would require unescaping
883
* sizeBufOut must account for the NUL terminator.
886
* On success, the size (excluding the NUL terminator) of the
887
* escaped, NUL terminated buffer.
888
* On failure (bufOut not big enough to hold result), negative value.
893
*-----------------------------------------------------------------------------
897
HgfsEscapeDoComponent(char const *bufIn, // IN: Buffer with unescaped input
898
uint32 sizeIn, // IN: Size of input buffer
899
uint32 sizeBufOut, // IN: Size of output buffer
900
char *bufOut) // OUT: Buffer for escaped output
902
HgfsEscapeContext conversionContext;
903
conversionContext.processedOffset = 0;
904
conversionContext.outputBufferLength = sizeBufOut / sizeof *bufOut;
905
conversionContext.outputOffset = 0;
906
conversionContext.outputBuffer = bufOut;
908
if (!HgfsEscapeEnumerate(bufIn, sizeIn, HgfsAddEscapeCharacter, &conversionContext)) {
911
return conversionContext.outputOffset * sizeof *bufOut;
916
*-----------------------------------------------------------------------------
918
* HgfsEscapeGetComponentSize --
920
* Calculates number of addtitional characters that are needed to escape
921
* name for one NUL terminated component of the path.
924
* Number of additional escape characters needed to escape the name.
925
* Returns 0 if no escaping is required.
930
*-----------------------------------------------------------------------------
934
HgfsEscapeGetComponentSize(char const *bufIn, // IN: Buffer with unescaped input
935
uint32 sizeIn) // IN: Size of the in input buffer
938
HgfsEscapeEnumerate(bufIn, sizeIn, HgfsCountEscapeChars, &result);