VirtualBox

Changeset 90010 in vbox for trunk/src/VBox/Devices/Audio


Ignore:
Timestamp:
Jul 4, 2021 7:37:45 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
145499
Message:

Audio/AudioHlp: Deal with sharing violations when audio debug is enabled for AC'97 on windows by retrying 15 times with a letter added to the filename. Cleanedup the AudioHlpFileNameGet code. bugref:9890

Location:
trunk/src/VBox/Devices/Audio
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/AudioHlp.cpp

    r89447 r90010  
    235235
    236236/**
    237  * Sanitizes the file name component so that unsupported characters
    238  * will be replaced by an underscore ("_").
    239  *
    240  * @returns VBox status code.
    241  * @param   pszPath             Path to sanitize.
    242  * @param   cbPath              Size (in bytes) of path to sanitize.
    243  */
    244 int AudioHlpFileNameSanitize(char *pszPath, size_t cbPath)
    245 {
    246     RT_NOREF(cbPath);
    247     int rc = VINF_SUCCESS;
    248 #ifdef RT_OS_WINDOWS
    249     /* Filter out characters not allowed on Windows platforms, put in by
    250        RTTimeSpecToString(). */
    251     /** @todo Use something like RTPathSanitize() if available later some time. */
    252     static RTUNICP const s_uszValidRangePairs[] =
    253     {
    254         ' ', ' ',
    255         '(', ')',
    256         '-', '.',
    257         '0', '9',
    258         'A', 'Z',
    259         'a', 'z',
    260         '_', '_',
    261         0xa0, 0xd7af,
    262         '\0'
    263     };
    264     ssize_t cReplaced = RTStrPurgeComplementSet(pszPath, s_uszValidRangePairs, '_' /* Replacement */);
    265     if (cReplaced < 0)
    266         rc = VERR_INVALID_UTF8_ENCODING;
    267 #else
    268     RT_NOREF(pszPath);
    269 #endif
    270     return rc;
    271 }
    272 
    273 /**
    274237 * Constructs an unique file name, based on the given path and the audio file type.
    275238 *
    276239 * @returns VBox status code.
    277  * @param   pszFile             Where to store the constructed file name.
    278  * @param   cchFile             Size (in characters) of the file name buffer.
    279  * @param   pszPath             Base path to use.
    280  *                              If NULL or empty, the system's temporary directory will be used.
    281  * @param   pszName             A name for better identifying the file.
    282  * @param   uInstance           Device / driver instance which is using this file.
    283  * @param   enmType             Audio file type to construct file name for.
    284  * @param   fFlags              File naming flags, AUDIOHLPFILENAME_FLAGS_XXX.
    285  */
    286 int AudioHlpFileNameGet(char *pszFile, size_t cchFile, const char *pszPath, const char *pszName,
     240 * @param   pszDst      Where to store the constructed file name.
     241 * @param   cbDst       Size of the destination buffer (bytes; incl terminator).
     242 * @param   pszPath     Base path to use.  If NULL or empty, the user's
     243 *                      temporary directory will be used.
     244 * @param   pszName     A name for better identifying the file.
     245 * @param   uInstance   Device / driver instance which is using this file.
     246 * @param   enmType     Audio file type to construct file name for.
     247 * @param   fFlags      File naming flags, AUDIOHLPFILENAME_FLAGS_XXX.
     248 * @param   chTweak     Retry tweak character.
     249 */
     250static int audioHlpConstructPathWorker(char *pszDst, size_t cbDst, const char *pszPath, const char *pszName,
     251                                       uint32_t uInstance, AUDIOHLPFILETYPE enmType, uint32_t fFlags, char chTweak)
     252{
     253    /*
     254     * Validate input.
     255     */
     256    AssertPtrNullReturn(pszPath, VERR_INVALID_POINTER);
     257    AssertPtrReturn(pszName, VERR_INVALID_POINTER);
     258    AssertReturn(!(fFlags & ~AUDIOHLPFILENAME_FLAGS_VALID_MASK), VERR_INVALID_FLAGS);
     259
     260    /* Validate the type and translate it into a suffix. */
     261    const char *pszSuffix = NULL;
     262    switch (enmType)
     263    {
     264        case AUDIOHLPFILETYPE_RAW: pszSuffix = ".pcm"; break;
     265        case AUDIOHLPFILETYPE_WAV: pszSuffix = ".wav"; break;
     266        case AUDIOHLPFILETYPE_INVALID:
     267        case AUDIOHLPFILETYPE_32BIT_HACK:
     268            break; /* no default */
     269    }
     270    AssertMsgReturn(pszSuffix, ("enmType=%d\n", enmType), VERR_INVALID_PARAMETER);
     271
     272    /*
     273     * The directory.  Make sure it exists and ends with a path separator.
     274     */
     275    int rc;
     276    if (!pszPath || !*pszPath)
     277        rc = RTPathTemp(pszDst, cbDst);
     278    else
     279    {
     280        AssertPtrReturn(pszDst, VERR_INVALID_POINTER);
     281        rc = RTStrCopy(pszDst, cbDst, pszPath);
     282    }
     283    AssertRCReturn(rc, rc);
     284
     285    if (!RTDirExists(pszDst))
     286    {
     287        rc = RTDirCreateFullPath(pszDst, RTFS_UNIX_IRWXU);
     288        AssertRCReturn(rc, rc);
     289    }
     290
     291    size_t offDst = RTPathEnsureTrailingSeparator(pszDst, cbDst);
     292    AssertReturn(offDst > 0, VERR_BUFFER_OVERFLOW);
     293    Assert(offDst < cbDst);
     294
     295    /*
     296     * The filename.
     297     */
     298    /* Start with a ISO timestamp w/ colons replaced by dashes if requested. */
     299    if (fFlags & AUDIOHLPFILENAME_FLAGS_TS)
     300    {
     301        RTTIMESPEC NowTimeSpec;
     302        RTTIME     NowUtc;
     303        AssertReturn(RTTimeToString(RTTimeExplode(&NowUtc, RTTimeNow(&NowTimeSpec)), &pszDst[offDst], cbDst - offDst),
     304                     VERR_BUFFER_OVERFLOW);
     305
     306        /* Change the two colons in the time part to dashes.  */
     307        char *pchColon = &pszDst[offDst];
     308        while ((pchColon = strchr(pchColon, ':')) != NULL)
     309            *pchColon++ = '-';
     310
     311        offDst += strlen(&pszDst[offDst]);
     312        Assert(pszDst[offDst - 1] == 'Z');
     313
     314        /* Append a dash to separate the timestamp from the name. */
     315        AssertReturn(offDst + 2 <= cbDst, VERR_BUFFER_OVERFLOW);
     316        pszDst[offDst++] = '-';
     317        pszDst[offDst]   = '\0';
     318    }
     319
     320    /* Append the filename, instance, retry-tweak and suffix. */
     321    ssize_t cchTail;
     322    if (chTweak == '\0')
     323        cchTail = RTStrPrintf2(&pszDst[offDst], cbDst - offDst, "%s-%u%s", pszName, uInstance, pszSuffix);
     324    else
     325        cchTail = RTStrPrintf2(&pszDst[offDst], cbDst - offDst, "%s-%u%c%s", pszName, uInstance, chTweak, pszSuffix);
     326    AssertReturn(cchTail > 0, VERR_BUFFER_OVERFLOW);
     327
     328    return VINF_SUCCESS;
     329}
     330
     331/**
     332 * Constructs an unique file name, based on the given path and the audio file type.
     333 *
     334 * @returns VBox status code.
     335 * @param   pszDst      Where to store the constructed file name.
     336 * @param   cbDst       Size of the destination buffer (bytes; incl terminator).
     337 * @param   pszPath     Base path to use.  If NULL or empty, the user's
     338 *                      temporary directory will be used.
     339 * @param   pszName     A name for better identifying the file.
     340 * @param   uInstance   Device / driver instance which is using this file.
     341 * @param   enmType     Audio file type to construct file name for.
     342 * @param   fFlags      File naming flags, AUDIOHLPFILENAME_FLAGS_XXX.
     343 */
     344int AudioHlpFileNameGet(char *pszDst, size_t cbDst, const char *pszPath, const char *pszName,
    287345                        uint32_t uInstance, AUDIOHLPFILETYPE enmType, uint32_t fFlags)
    288346{
    289     AssertPtrReturn(pszFile, VERR_INVALID_POINTER);
    290     AssertReturn(cchFile,    VERR_INVALID_PARAMETER);
    291     /* pszPath can be NULL. */
    292     AssertPtrReturn(pszName, VERR_INVALID_POINTER);
    293     /** @todo Validate fFlags. */
    294 
    295     int rc;
    296 
    297     char *pszPathTmp = NULL;
    298 
    299     do
    300     {
    301         if (   pszPath == NULL
    302             || !strlen(pszPath))
    303         {
    304             char szTemp[RTPATH_MAX];
    305             rc = RTPathTemp(szTemp, sizeof(szTemp));
    306             if (RT_SUCCESS(rc))
    307             {
    308                 pszPathTmp = RTStrDup(szTemp);
    309             }
    310             else
    311                 break;
    312         }
    313         else
    314             pszPathTmp = RTStrDup(pszPath);
    315 
    316         AssertPtrBreakStmt(pszPathTmp, rc = VERR_NO_MEMORY);
    317 
    318         char szFilePath[RTPATH_MAX];
    319         rc = RTStrCopy(szFilePath, sizeof(szFilePath), pszPathTmp);
    320         AssertRCBreak(rc);
    321 
    322         /* Create it when necessary. */
    323         if (!RTDirExists(szFilePath))
    324         {
    325             rc = RTDirCreateFullPath(szFilePath, RTFS_UNIX_IRWXU);
    326             if (RT_FAILURE(rc))
    327                 break;
    328         }
    329 
    330         char szFileName[RTPATH_MAX];
    331         szFileName[0] = '\0';
    332 
    333         if (fFlags & AUDIOHLPFILENAME_FLAGS_TS)
    334         {
    335             RTTIMESPEC time;
    336             if (!RTTimeSpecToString(RTTimeNow(&time), szFileName, sizeof(szFileName)))
    337             {
    338                 rc = VERR_BUFFER_OVERFLOW;
    339                 break;
    340             }
    341 
    342             rc = AudioHlpFileNameSanitize(szFileName, sizeof(szFileName));
    343             if (RT_FAILURE(rc))
    344                 break;
    345 
    346             rc = RTStrCat(szFileName, sizeof(szFileName), "-");
    347             if (RT_FAILURE(rc))
    348                 break;
    349         }
    350 
    351         rc = RTStrCat(szFileName, sizeof(szFileName), pszName);
    352         if (RT_FAILURE(rc))
    353             break;
    354 
    355         rc = RTStrCat(szFileName, sizeof(szFileName), "-");
    356         if (RT_FAILURE(rc))
    357             break;
    358 
    359         char szInst[16];
    360         RTStrPrintf2(szInst, sizeof(szInst), "%RU32", uInstance);
    361         rc = RTStrCat(szFileName, sizeof(szFileName), szInst);
    362         if (RT_FAILURE(rc))
    363             break;
    364 
    365         switch (enmType)
    366         {
    367             case AUDIOHLPFILETYPE_RAW:
    368                 rc = RTStrCat(szFileName, sizeof(szFileName), ".pcm");
    369                 break;
    370 
    371             case AUDIOHLPFILETYPE_WAV:
    372                 rc = RTStrCat(szFileName, sizeof(szFileName), ".wav");
    373                 break;
    374 
    375             default:
    376                 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
    377                 break;
    378         }
    379 
    380         if (RT_FAILURE(rc))
    381             break;
    382 
    383         rc = RTPathAppend(szFilePath, sizeof(szFilePath), szFileName);
    384         if (RT_FAILURE(rc))
    385             break;
    386 
    387         rc = RTStrCopy(pszFile, cchFile, szFilePath);
    388 
    389     } while (0);
    390 
    391     RTStrFree(pszPathTmp);
    392 
    393     LogFlowFuncLeaveRC(rc);
    394     return rc;
     347    return audioHlpConstructPathWorker(pszDst, cbDst, pszPath, pszName, uInstance, enmType, fFlags, '\0');
    395348}
    396349
     
    564517                                PCPDMAUDIOPCMPROPS pProps, uint64_t fOpen)
    565518{
    566     char szFile[RTPATH_MAX];
    567     int rc = AudioHlpFileNameGet(szFile, sizeof(szFile), pszDir, pszName, iInstance, enmType, fFilename);
    568     if (RT_SUCCESS(rc))
    569     {
     519    *ppFile = NULL;
     520
     521    for (uint32_t iTry = 0; ; iTry++)
     522    {
     523        char szFile[RTPATH_MAX];
     524        int rc = audioHlpConstructPathWorker(szFile, sizeof(szFile), pszDir, pszName, iInstance, enmType, fFilename,
     525                                             iTry == 0 ? '\0' : iTry + 'a');
     526        AssertRCReturn(rc, rc);
     527
    570528        PAUDIOHLPFILE pFile = NULL;
    571529        rc = AudioHlpFileCreate(enmType, szFile, fCreate, &pFile);
     530        AssertRCReturn(rc, rc);
     531
     532        rc = AudioHlpFileOpen(pFile, fOpen, pProps);
    572533        if (RT_SUCCESS(rc))
    573534        {
    574             rc = AudioHlpFileOpen(pFile, fOpen, pProps);
    575             if (RT_SUCCESS(rc))
    576             {
    577                 *ppFile = pFile;
    578                 return rc;
    579             }
    580             AudioHlpFileDestroy(pFile);
     535            *ppFile = pFile;
     536            return rc;
    581537        }
    582     }
    583     *ppFile = NULL;
    584     return rc;
     538        AudioHlpFileDestroy(pFile);
     539
     540        AssertReturn(iTry < 16, rc);
     541    }
    585542}
    586543
  • trunk/src/VBox/Devices/Audio/AudioHlp.h

    r89342 r90010  
    6767    /** The customary invalid zero value. */
    6868    AUDIOHLPFILETYPE_INVALID = 0,
    69     /** Unknown type, do not use. */
    70     AUDIOHLPFILETYPE_UNKNOWN,
    7169    /** Raw (PCM) file. */
    7270    AUDIOHLPFILETYPE_RAW,
     
    7977/** @name Audio file (name) helper methods.
    8078 * @{ */
    81 int     AudioHlpFileNameSanitize(char *pszPath, size_t cbPath);
    8279int     AudioHlpFileNameGet(char *pszFile, size_t cchFile, const char *pszPath, const char *pszName,
    8380                            uint32_t uInstance, AUDIOHLPFILETYPE enmType, uint32_t fFlags);
     
    8986#define AUDIOHLPFILENAME_FLAGS_NONE         UINT32_C(0)
    9087/** Adds an ISO timestamp to the file name. */
    91 #define AUDIOHLPFILENAME_FLAGS_TS           RT_BIT(0)
     88#define AUDIOHLPFILENAME_FLAGS_TS           RT_BIT_32(0)
     89/** Valid flag mask. */
     90#define AUDIOHLPFILENAME_FLAGS_VALID_MASK   AUDIOHLPFILENAME_FLAGS_TS
    9291/** @} */
    9392
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette