Changeset 66708 in vbox
- Timestamp:
- Apr 27, 2017 10:01:52 PM (8 years ago)
- svn:sync-xref-src-repo-rev:
- 115107
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/filesystem/fatvfs.cpp
r66699 r66708 38 38 #include <iprt/err.h> 39 39 #include <iprt/mem.h> 40 #include <iprt/path.h> 40 41 #include <iprt/poll.h> 41 42 #include <iprt/rand.h> … … 71 72 */ 72 73 #define RTFSFAT_ROT_R1_U8(a_bValue) (((a_bValue) >> 1) | (uint8_t)((a_bValue) << 7)) 74 75 76 /** Maximum number of characters we will create in a long file name. */ 77 #define RTFSFAT_MAX_LFN_CHARS 255 73 78 74 79 … … 2344 2349 * @returns true if 8.3 formattable name, false if not. 2345 2350 * @param pszName8Dot3 Where to return the 8-dot-3 name when returning 2346 * @c true. Filled with zero on false. 12+1 bytes.2351 * @c true. Filled with zero on false. 8+3+1 bytes. 2347 2352 * @param pszName The filename to convert. 2348 2353 */ … … 2434 2439 * 2435 2440 * @returns IPRT status code. 2441 * @retval VERR_FILE_NOT_FOUND if not found. 2436 2442 * @param pThis The directory to search. 2437 2443 * @param pszEntry The entry to look for. … … 2451 2457 * Turn pszEntry into a 8.3 filename, if possible. 2452 2458 */ 2453 char szName8Dot3[ 12+1];2459 char szName8Dot3[8+3+1]; 2454 2460 bool fIs8Dot3Name = rtFsFatDir_StringTo8Dot3(szName8Dot3, pszEntry); 2455 2461 … … 2608 2614 2609 2615 /** 2616 * Checks if we need to generate a long name for @a pszEntry. 2617 * 2618 * @returns true if we need to, false if we don't. 2619 * @param pszEntry The UTF-8 directory entry entry name. 2620 * @param fIs8Dot3Name Whether we've managed to create a 8-dot-3 name. 2621 * @param pDirEntry The directory entry with the 8-dot-3 name when 2622 * fIs8Dot3Name is set. 2623 */ 2624 static bool rtFsFatDir_NeedLongName(const char *pszEntry, bool fIs8Dot3Name, PCFATDIRENTRY pDirEntry) 2625 { 2626 if (!fIs8Dot3Name) 2627 return true; 2628 2629 /** @todo check case here. */ 2630 RT_NOREF(pszEntry, pDirEntry); 2631 return false; 2632 } 2633 2634 2635 /** 2636 * Checks if the given long name is valid for a long file name or not. 2637 * 2638 * Encoding, length and character set limitations are checked. 2639 * 2640 * @returns IRPT status code. 2641 * @param pwszEntry The long filename. 2642 * @param cwc The length of the filename in UTF-16 chars. 2643 */ 2644 static int rtFsFatDir_ValidateLongName(PCRTUTF16 pwszEntry, size_t cwc) 2645 { 2646 if (cwc <= RTFSFAT_MAX_LFN_CHARS) 2647 { 2648 RT_NOREF(pwszEntry); 2649 /** @todo check for invalid characters. */ 2650 return VINF_SUCCESS; 2651 } 2652 return VERR_FILENAME_TOO_LONG; 2653 } 2654 2655 2656 static void rtFsFatDir_CopyShortName(char *pszDst, uint32_t cchDst, const char *pszSrc, size_t cchSrc, char chPad) 2657 { 2658 /* Copy from source. */ 2659 if (cchSrc > 0) 2660 { 2661 const char *pszSrcEnd = &pszSrc[cchSrc]; 2662 while (cchDst > 0 && pszSrc != pszSrcEnd) 2663 { 2664 RTUNICP uc; 2665 int rc = RTStrGetCpEx(&pszSrc, &uc); 2666 if (RT_SUCCESS(rc)) 2667 { 2668 if (uc < 128) 2669 { 2670 if (g_awchFatCp437Chars[uc] != uc) 2671 { 2672 if (uc) 2673 { 2674 uc = RTUniCpToUpper(uc); 2675 if (g_awchFatCp437Chars[uc] != uc) 2676 uc = '_'; 2677 } 2678 else 2679 break; 2680 } 2681 } 2682 else 2683 uc = '_'; 2684 } 2685 else 2686 uc = '_'; 2687 2688 *pszDst++ = (char)uc; 2689 cchDst--; 2690 } 2691 } 2692 2693 /* Pad the remaining space. */ 2694 while (cchDst-- > 0) 2695 *pszDst++ = chPad; 2696 } 2697 2698 2699 /** 2700 * Generates a short filename. 2701 * 2702 * @returns IPRT status code. 2703 * @param pThis The directory. 2704 * @param pszEntry The long name (UTF-8). 2705 * @param pDirEntry Where to put the short name. 2706 */ 2707 static int rtFsFatDir_GenerateShortName(PRTFSFATDIR pThis, const char *pszEntry, PFATDIRENTRY pDirEntry) 2708 { 2709 FATDIRENTRY DirEntryIgn; 2710 bool fLongIgn; 2711 uint32_t offEntryInDirIgn; 2712 2713 /* Do some input parsing. */ 2714 const char *pszExt = RTPathSuffix(pszEntry); 2715 size_t const cchBasename = pszExt ? pszExt - pszEntry : strlen(pszEntry); 2716 size_t const cchExt = pszExt ? strlen(++pszExt) : 0; 2717 2718 /* Fill in the extension first. It stays the same. */ 2719 char szShortName[8+3+1]; 2720 rtFsFatDir_CopyShortName(&szShortName[8], 3, pszExt, cchExt, ' '); 2721 szShortName[8+3] = '\0'; 2722 2723 /* 2724 * First try single digit 1..9. 2725 */ 2726 rtFsFatDir_CopyShortName(szShortName, 6, pszEntry, cchBasename, '_'); 2727 szShortName[6] = '~'; 2728 for (uint32_t iLastDigit = 1; iLastDigit < 10; iLastDigit++) 2729 { 2730 szShortName[7] = iLastDigit + '0'; 2731 int rc = rtFsFatDir_FindEntry(pThis, szShortName, &offEntryInDirIgn, &fLongIgn, &DirEntryIgn); 2732 if (rc == VERR_FILE_NOT_FOUND) 2733 { 2734 memcpy(pDirEntry->achName, szShortName, sizeof(pDirEntry->achName)); 2735 return VINF_SUCCESS; 2736 } 2737 if (RT_FAILURE(rc)) 2738 return rc; 2739 } 2740 2741 /* 2742 * First try two digits 10..99. 2743 */ 2744 szShortName[5] = '~'; 2745 for (uint32_t iFirstDigit = 1; iFirstDigit < 10; iFirstDigit++) 2746 for (uint32_t iLastDigit = 0; iLastDigit < 10; iLastDigit++) 2747 { 2748 szShortName[6] = iFirstDigit + '0'; 2749 szShortName[7] = iLastDigit + '0'; 2750 int rc = rtFsFatDir_FindEntry(pThis, szShortName, &offEntryInDirIgn, &fLongIgn, &DirEntryIgn); 2751 if (rc == VERR_FILE_NOT_FOUND) 2752 { 2753 memcpy(pDirEntry->achName, szShortName, sizeof(pDirEntry->achName)); 2754 return VINF_SUCCESS; 2755 } 2756 if (RT_FAILURE(rc)) 2757 return rc; 2758 } 2759 2760 /* 2761 * Okay, do random numbers then. 2762 */ 2763 szShortName[2] = '~'; 2764 for (uint32_t i = 0; i < 8192; i++) 2765 { 2766 char szHex[68]; 2767 ssize_t cchHex = RTStrFormatU32(szHex, sizeof(szHex), RTRandU32(), 16, 5, 0, RTSTR_F_CAPITAL | RTSTR_F_WIDTH); 2768 AssertReturn(cchHex >= 5, VERR_NET_NOT_UNIQUE_NAME); 2769 szShortName[7] = szHex[cchHex]; 2770 szShortName[6] = szHex[cchHex - 1]; 2771 szShortName[5] = szHex[cchHex - 2]; 2772 szShortName[4] = szHex[cchHex - 3]; 2773 szShortName[3] = szHex[cchHex - 4]; 2774 int rc = rtFsFatDir_FindEntry(pThis, szShortName, &offEntryInDirIgn, &fLongIgn, &DirEntryIgn); 2775 if (rc == VERR_FILE_NOT_FOUND) 2776 { 2777 memcpy(pDirEntry->achName, szShortName, sizeof(pDirEntry->achName)); 2778 return VINF_SUCCESS; 2779 } 2780 if (RT_FAILURE(rc)) 2781 return rc; 2782 } 2783 2784 return VERR_NET_NOT_UNIQUE_NAME; 2785 } 2786 2787 2788 /** 2610 2789 * Considers whether we need to create a long name or not. 2611 2790 * … … 2626 2805 { 2627 2806 RT_NOREF(pThis, pDirEntry, paSlots, pszEntry); 2628 if (fIs8Dot3Name) 2807 2808 /* 2809 * If we don't need to create a long name, return immediately. 2810 */ 2811 if (!rtFsFatDir_NeedLongName(pszEntry, fIs8Dot3Name, pDirEntry)) 2629 2812 { 2630 2813 *pcSlots = 0; 2631 2814 return VINF_SUCCESS; 2632 2815 } 2816 2817 /* 2818 * Convert the name to UTF-16 and figure it's length (this validates the 2819 * input encoding). Then do long name validation (length, charset limitation). 2820 */ 2821 RTUTF16 wszEntry[FATDIRNAMESLOT_MAX_SLOTS * FATDIRNAMESLOT_CHARS_PER_SLOT + 4]; 2822 PRTUTF16 pwszEntry = wszEntry; 2823 size_t cwcEntry; 2824 int rc = RTStrToUtf16Ex(pszEntry, RTSTR_MAX, &pwszEntry, RT_ELEMENTS(wszEntry), &cwcEntry); 2825 if (RT_SUCCESS(rc)) 2826 rc = rtFsFatDir_ValidateLongName(pwszEntry, cwcEntry); 2827 if (RT_SUCCESS(rc)) 2828 { 2829 /* 2830 * Generate a short name if we need to. 2831 */ 2832 if (!fIs8Dot3Name) 2833 rc = rtFsFatDir_GenerateShortName(pThis, pszEntry, pDirEntry); 2834 if (RT_SUCCESS(rc)) 2835 { 2836 /* 2837 * Fill in the long name slots. First we pad the wszEntry with 0xffff 2838 * until it is a multiple of of the slot count. That way we can copy 2839 * the name straight into the entry without constaints. 2840 */ 2841 memset(&wszEntry[cwcEntry + 1], 0xff, 2842 RT_MIN(sizeof(wszEntry) - (cwcEntry + 1) * sizeof(RTUTF16), FATDIRNAMESLOT_CHARS_PER_SLOT)); 2843 2844 uint8_t const bChecksum = rtFsFatDir_CalcChecksum(pDirEntry); 2845 size_t const cSlots = (cwcEntry + FATDIRNAMESLOT_CHARS_PER_SLOT - 1) / FATDIRNAMESLOT_CHARS_PER_SLOT; 2846 size_t iSlot = cSlots; 2847 PCRTUTF16 pwszSrc = wszEntry; 2848 while (iSlot-- > 0) 2849 { 2850 memcpy(paSlots[iSlot].awcName0, pwszSrc, sizeof(paSlots[iSlot].awcName0)); 2851 pwszSrc += RT_ELEMENTS(paSlots[iSlot].awcName0); 2852 memcpy(paSlots[iSlot].awcName1, pwszSrc, sizeof(paSlots[iSlot].awcName1)); 2853 pwszSrc += RT_ELEMENTS(paSlots[iSlot].awcName1); 2854 memcpy(paSlots[iSlot].awcName2, pwszSrc, sizeof(paSlots[iSlot].awcName2)); 2855 pwszSrc += RT_ELEMENTS(paSlots[iSlot].awcName2); 2856 2857 paSlots[iSlot].idSlot = (uint8_t)(cSlots - iSlot); 2858 paSlots[iSlot].fAttrib = FAT_ATTR_NAME_SLOT; 2859 paSlots[iSlot].fZero = 0; 2860 paSlots[iSlot].idxZero = 0; 2861 paSlots[iSlot].bChecksum = bChecksum; 2862 } 2863 paSlots[0].idSlot |= FATDIRNAMESLOT_FIRST_SLOT_FLAG; 2864 *pcSlots = (uint32_t)cSlots; 2865 return VINF_SUCCESS; 2866 } 2867 } 2633 2868 *pcSlots = UINT32_MAX; 2634 return VERR_INVALID_NAME;2869 return rc; 2635 2870 } 2636 2871 … … 2880 3115 uint32_t cSlots = UINT32_MAX; 2881 3116 FATDIRNAMESLOT aSlots[FATDIRNAMESLOT_MAX_SLOTS]; 3117 AssertCompile(RTFSFAT_MAX_LFN_CHARS < RT_ELEMENTS(aSlots) * FATDIRNAMESLOT_CHARS_PER_SLOT); 2882 3118 int rc = rtFsFatDir_MaybeCreateLongNameAndShortAlias(pThis, pszEntry, fIs8Dot3Name, pDirEntry, aSlots, &cSlots); 2883 3119 if (RT_SUCCESS(rc))
Note:
See TracChangeset
for help on using the changeset viewer.