HgfsNameStatus HgfsServerPolicy_GetShareOptions(char const *nameIn, // IN: Share name size_t nameInLen, // IN: Share name length HgfsShareOptions *configOptions)// OUT: Config options { HgfsSharedFolder *share; char const *inEnd; char *next; int len; ASSERT(nameIn); ASSERT(configOptions); inEnd = nameIn + nameInLen; len = CPName_GetComponent(nameIn, inEnd, (char const **) &next); if (len < 0) { LOG(4, ("HgfsServerPolicy_GetShareOptions: get first component failed\n")); return HGFS_NAME_STATUS_FAILURE; } share = HgfsServerPolicyGetShare(&myState, nameIn, len); if (!share) { LOG(4, ("HgfsServerPolicy_GetShareOptions: No matching share name.\n")); return HGFS_NAME_STATUS_DOES_NOT_EXIST; } *configOptions = share->configOptions; return HGFS_NAME_STATUS_COMPLETE; }
int HgfsEscape_Do(char const *bufIn, // IN: Buffer with unescaped input uint32 sizeIn, // IN: Size of input buffer uint32 sizeBufOut, // IN: Size of output buffer char *bufOut) // OUT: Buffer for escaped output { const char *currentComponent = bufIn; uint32 sizeLeft = sizeBufOut; char *outPointer = bufOut; const char *end = bufIn + sizeIn; const char *next; ASSERT(sizeIn > 0); if (bufIn[sizeIn - 1] == '\0') { /* * In some cases a NUL terminated string is passed to HgfsEscape_Do * so it make sense to support such input even if CPName_GetComponent * does not. Detect this case and make the input compliant with * CPName_GetComponent by removing terminating NUL. */ end--; sizeIn--; } /* * Absolute symbolic link name starts with the '\0'. HgfsEscapeDo needs to work * with such names. Leading NULL symbols should be skipped here since * CPName_GetComponent does not support such names. */ while (*currentComponent == '\0' && currentComponent - bufIn < sizeIn) { currentComponent++; sizeLeft--; *outPointer++ = '\0'; } while (currentComponent - bufIn < sizeIn) { int escapedLength; int componentSize = CPName_GetComponent(currentComponent, end, &next); if (componentSize < 0) { return componentSize; } escapedLength = HgfsEscapeDoComponent(currentComponent, componentSize, sizeLeft, outPointer); if (escapedLength < 0) { return escapedLength; } currentComponent = next; sizeLeft -= escapedLength + 1; outPointer += escapedLength + 1; } return (int) (outPointer - bufOut) - 1; // Do not count the last NUL terminator }
HgfsNameStatus CPName_ConvertFromRoot(char const **bufIn, // IN/OUT: Input to convert size_t *inSize, // IN/OUT: Size of input size_t *outSize, // IN/OUT: Size of output buffer char **bufOut) // IN/OUT: Output buffer { char const *next; char *out; int len; ASSERT(bufIn); ASSERT(inSize); ASSERT(outSize); ASSERT(bufOut); out = *bufOut; /* * Get first component */ len = CPName_GetComponent(*bufIn, *bufIn + *inSize, &next); if (len < 0) { Log("%s: get first component failed\n", __FUNCTION__); return HGFS_NAME_STATUS_FAILURE; } /* Space for leading '/' plus NUL termination */ if (*outSize < len + 2) { return HGFS_NAME_STATUS_FAILURE; } /* Put a leading '/' in the output buffer either way */ *out++ = '/'; memcpy(out, *bufIn, len); out += len; /* NUL terminate */ *out = '\0'; *inSize -= next - *bufIn; *outSize -= out - *bufOut; *bufIn = next; *bufOut = out; return HGFS_NAME_STATUS_COMPLETE; }
int HgfsEscape_GetSize(char const *bufIn, // IN: Buffer with unescaped input uint32 sizeIn) // IN: Size of the input buffer { uint32 result = 0; const char *currentComponent = bufIn; const char *end = bufIn + sizeIn; const char *next; if (sizeIn == 0) { // No need toescape empty name. return 0; } if (bufIn[sizeIn - 1] == '\0') { /* * In some cases a NUL terminated string is passed to HgfsEscape_GeSize * so it make sense to support such input even if CPName_GetComponent * does not. Detect this case and make the input compliant with * CPName_GetComponent by removing terminating NUL. */ end--; sizeIn--; } /* Skip leading NULs to keep CPName_GetComponent happy. */ while (*currentComponent == '\0' && currentComponent - bufIn < sizeIn) { currentComponent++; } while (currentComponent - bufIn < sizeIn) { int componentSize = CPName_GetComponent(currentComponent, end, &next); if (componentSize < 0) { Log("%s: failed to calculate escapde name size - name is invalid\n", __FUNCTION__); return -1; } result += HgfsEscapeGetComponentSize(currentComponent, componentSize); currentComponent = next; } return (result == 0) ? 0 : result + sizeIn; }
int CPNameConvertFrom(char const **bufIn, // IN/OUT: Input to convert size_t *inSize, // IN/OUT: Size of input size_t *outSize, // IN/OUT: Size of output buffer char **bufOut, // IN/OUT: Output buffer char pathSep) // IN: Path separator character { char const *in; char const *inEnd; size_t myOutSize; char *out; Bool inPlaceConvertion = (*bufIn == *bufOut); ASSERT(bufIn); ASSERT(inSize); ASSERT(outSize); ASSERT(bufOut); in = *bufIn; if (inPlaceConvertion) { in++; // Skip place for the leading path separator. } inEnd = in + *inSize; myOutSize = *outSize; out = *bufOut; for (;;) { char const *next; int len; int newLen; len = CPName_GetComponent(in, inEnd, &next); if (len < 0) { Log("%s: error: get next component failed\n", __FUNCTION__); return len; } /* Bug 27926 - preventing escaping from shared folder. */ if ((len == 1 && *in == '.') || (len == 2 && in[0] == '.' && in[1] == '.')) { Log("%s: error: found dot/dotdot\n", __FUNCTION__); return -1; } if (len == 0) { /* No more component */ break; } newLen = ((int) myOutSize) - len - 1; if (newLen < 0) { Log("%s: error: not enough room\n", __FUNCTION__); return -1; } myOutSize = (size_t) newLen; *out++ = pathSep; if (!inPlaceConvertion) { memcpy(out, in, len); } out += len; in = next; } /* NUL terminate */ if (myOutSize < 1) { Log("%s: error: not enough room\n", __FUNCTION__); return -1; } *out = '\0'; /* Path name size should not require more than 4 bytes. */ ASSERT((in - *bufIn) <= 0xFFFFFFFF); /* Update pointers. */ *inSize -= (in - *bufIn); *outSize = myOutSize; *bufIn = in; *bufOut = out; return 0; }