… | |
… | |
1706 | dirp = FindFirstFile (path, &entp); |
1706 | dirp = FindFirstFile (path, &entp); |
1707 | free (path); |
1707 | free (path); |
1708 | |
1708 | |
1709 | if (dirp == INVALID_HANDLE_VALUE) |
1709 | if (dirp == INVALID_HANDLE_VALUE) |
1710 | { |
1710 | { |
1711 | dirp = 0; |
|
|
1712 | |
|
|
1713 | /* should steal _dosmaperr */ |
1711 | /* should steal _dosmaperr */ |
1714 | switch (GetLastError ()) |
1712 | switch (GetLastError ()) |
1715 | { |
1713 | { |
1716 | case ERROR_FILE_NOT_FOUND: |
1714 | case ERROR_FILE_NOT_FOUND: |
1717 | req->result = 0; |
1715 | req->result = 0; |
1718 | break; |
1716 | break; |
1719 | |
1717 | |
1720 | case ERROR_INVALID_NAME: |
1718 | case ERROR_INVALID_NAME: |
1721 | case ERROR_PATH_NOT_FOUND: |
1719 | case ERROR_PATH_NOT_FOUND: |
1722 | case ERROR_NO_MORE_FILES: |
1720 | case ERROR_NO_MORE_FILES: |
1723 | errno = ENOENT; |
1721 | errno = ENOENT; |
1724 | break; |
1722 | break; |
1725 | |
1723 | |
1726 | case ERROR_NOT_ENOUGH_MEMORY: |
1724 | case ERROR_NOT_ENOUGH_MEMORY: |
1727 | errno = ENOMEM; |
1725 | errno = ENOMEM; |
1728 | break; |
1726 | break; |
1729 | |
1727 | |
1730 | default: |
1728 | default: |
1731 | errno = EINVAL; |
1729 | errno = EINVAL; |
1732 | break; |
1730 | break; |
1733 | } |
1731 | } |
|
|
1732 | |
|
|
1733 | return; |
1734 | } |
1734 | } |
1735 | } |
1735 | } |
1736 | #else |
1736 | #else |
1737 | dirp = opendir (req->ptr1); |
1737 | dirp = opendir (req->ptr1); |
|
|
1738 | |
|
|
1739 | if (!dirp) |
|
|
1740 | return; |
1738 | #endif |
1741 | #endif |
1739 | |
1742 | |
1740 | if (req->flags & EIO_FLAG_PTR1_FREE) |
1743 | if (req->flags & EIO_FLAG_PTR1_FREE) |
1741 | free (req->ptr1); |
1744 | free (req->ptr1); |
1742 | |
1745 | |
1743 | req->flags |= EIO_FLAG_PTR1_FREE | EIO_FLAG_PTR2_FREE; |
1746 | req->flags |= EIO_FLAG_PTR1_FREE | EIO_FLAG_PTR2_FREE; |
1744 | req->ptr1 = dents = flags ? malloc (dentalloc * sizeof (eio_dirent)) : 0; |
1747 | req->ptr1 = dents = flags ? malloc (dentalloc * sizeof (eio_dirent)) : 0; |
1745 | req->ptr2 = names = malloc (namesalloc); |
1748 | req->ptr2 = names = malloc (namesalloc); |
1746 | |
1749 | |
1747 | if (dirp && names && (!flags || dents)) |
1750 | if (!names || (flags && !dents)) |
|
|
1751 | return; |
|
|
1752 | |
1748 | for (;;) |
1753 | for (;;) |
1749 | { |
1754 | { |
1750 | int done; |
1755 | int done; |
1751 | |
1756 | |
1752 | #ifdef _WIN32 |
1757 | #ifdef _WIN32 |
1753 | done = !dirp; |
1758 | done = !dirp; |
1754 | #else |
1759 | #else |
1755 | errno = 0; |
1760 | errno = 0; |
1756 | entp = readdir (dirp); |
1761 | entp = readdir (dirp); |
1757 | done = !entp; |
1762 | done = !entp; |
1758 | #endif |
1763 | #endif |
1759 | |
1764 | |
1760 | if (done) |
1765 | if (done) |
1761 | { |
1766 | { |
1762 | #ifndef _WIN32 |
1767 | #ifndef _WIN32 |
1763 | int old_errno = errno; |
1768 | int old_errno = errno; |
1764 | closedir (dirp); |
1769 | closedir (dirp); |
1765 | errno = old_errno; |
1770 | errno = old_errno; |
1766 | |
1771 | |
1767 | if (errno) |
1772 | if (errno) |
1768 | break; |
1773 | break; |
1769 | #endif |
1774 | #endif |
1770 | |
1775 | |
1771 | /* sort etc. */ |
1776 | /* sort etc. */ |
1772 | req->int1 = flags; |
1777 | req->int1 = flags; |
1773 | req->result = dentoffs; |
1778 | req->result = dentoffs; |
1774 | |
1779 | |
1775 | if (flags & EIO_READDIR_STAT_ORDER) |
1780 | if (flags & EIO_READDIR_STAT_ORDER) |
1776 | eio_dent_sort (dents, dentoffs, flags & EIO_READDIR_DIRS_FIRST ? 7 : 0, inode_bits); |
1781 | eio_dent_sort (dents, dentoffs, flags & EIO_READDIR_DIRS_FIRST ? 7 : 0, inode_bits); |
1777 | else if (flags & EIO_READDIR_DIRS_FIRST) |
1782 | else if (flags & EIO_READDIR_DIRS_FIRST) |
1778 | if (flags & EIO_READDIR_FOUND_UNKNOWN) |
1783 | if (flags & EIO_READDIR_FOUND_UNKNOWN) |
1779 | eio_dent_sort (dents, dentoffs, 7, inode_bits); /* sort by score and inode */ |
1784 | eio_dent_sort (dents, dentoffs, 7, inode_bits); /* sort by score and inode */ |
1780 | else |
1785 | else |
|
|
1786 | { |
|
|
1787 | /* in this case, all is known, and we just put dirs first and sort them */ |
|
|
1788 | eio_dirent *oth = dents + dentoffs; |
|
|
1789 | eio_dirent *dir = dents; |
|
|
1790 | |
|
|
1791 | /* now partition dirs to the front, and non-dirs to the back */ |
|
|
1792 | /* by walking from both sides and swapping if necessary */ |
|
|
1793 | while (oth > dir) |
|
|
1794 | { |
|
|
1795 | if (dir->type == EIO_DT_DIR) |
|
|
1796 | ++dir; |
|
|
1797 | else if ((--oth)->type == EIO_DT_DIR) |
|
|
1798 | { |
|
|
1799 | eio_dirent tmp = *dir; *dir = *oth; *oth = tmp; |
|
|
1800 | |
|
|
1801 | ++dir; |
|
|
1802 | } |
|
|
1803 | } |
|
|
1804 | |
|
|
1805 | /* now sort the dirs only (dirs all have the same score) */ |
|
|
1806 | eio_dent_sort (dents, dir - dents, 0, inode_bits); |
|
|
1807 | } |
|
|
1808 | |
|
|
1809 | break; |
|
|
1810 | } |
|
|
1811 | |
|
|
1812 | /* now add the entry to our list(s) */ |
|
|
1813 | name = D_NAME (entp); |
|
|
1814 | |
|
|
1815 | /* skip . and .. entries */ |
|
|
1816 | if (name [0] != '.' || (name [1] && (name [1] != '.' || name [2]))) |
|
|
1817 | { |
|
|
1818 | int len = D_NAMLEN (entp) + 1; |
|
|
1819 | |
|
|
1820 | while (ecb_expect_false (namesoffs + len > namesalloc)) |
|
|
1821 | { |
|
|
1822 | namesalloc *= 2; |
|
|
1823 | req->ptr2 = names = realloc (names, namesalloc); |
|
|
1824 | |
|
|
1825 | if (!names) |
|
|
1826 | break; |
|
|
1827 | } |
|
|
1828 | |
|
|
1829 | memcpy (names + namesoffs, name, len); |
|
|
1830 | |
|
|
1831 | if (dents) |
|
|
1832 | { |
|
|
1833 | struct eio_dirent *ent; |
|
|
1834 | |
|
|
1835 | if (ecb_expect_false (dentoffs == dentalloc)) |
1781 | { |
1836 | { |
1782 | /* in this case, all is known, and we just put dirs first and sort them */ |
1837 | dentalloc *= 2; |
|
|
1838 | req->ptr1 = dents = realloc (dents, dentalloc * sizeof (eio_dirent)); |
|
|
1839 | |
|
|
1840 | if (!dents) |
|
|
1841 | break; |
|
|
1842 | } |
|
|
1843 | |
1783 | eio_dirent *oth = dents + dentoffs; |
1844 | ent = dents + dentoffs; |
1784 | eio_dirent *dir = dents; |
|
|
1785 | |
1845 | |
1786 | /* now partition dirs to the front, and non-dirs to the back */ |
1846 | ent->nameofs = namesoffs; /* rather dirtily we store the offset in the pointer */ |
1787 | /* by walking from both sides and swapping if necessary */ |
1847 | ent->namelen = len - 1; |
1788 | while (oth > dir) |
1848 | ent->inode = D_INO (entp); |
|
|
1849 | |
|
|
1850 | inode_bits |= ent->inode; |
|
|
1851 | |
|
|
1852 | switch (D_TYPE (entp)) |
|
|
1853 | { |
|
|
1854 | default: |
|
|
1855 | ent->type = EIO_DT_UNKNOWN; |
|
|
1856 | flags |= EIO_READDIR_FOUND_UNKNOWN; |
|
|
1857 | break; |
|
|
1858 | |
|
|
1859 | #ifdef DT_FIFO |
|
|
1860 | case DT_FIFO: ent->type = EIO_DT_FIFO; break; |
|
|
1861 | #endif |
|
|
1862 | #ifdef DT_CHR |
|
|
1863 | case DT_CHR: ent->type = EIO_DT_CHR; break; |
|
|
1864 | #endif |
|
|
1865 | #ifdef DT_MPC |
|
|
1866 | case DT_MPC: ent->type = EIO_DT_MPC; break; |
|
|
1867 | #endif |
|
|
1868 | #ifdef DT_DIR |
|
|
1869 | case DT_DIR: ent->type = EIO_DT_DIR; break; |
|
|
1870 | #endif |
|
|
1871 | #ifdef DT_NAM |
|
|
1872 | case DT_NAM: ent->type = EIO_DT_NAM; break; |
|
|
1873 | #endif |
|
|
1874 | #ifdef DT_BLK |
|
|
1875 | case DT_BLK: ent->type = EIO_DT_BLK; break; |
|
|
1876 | #endif |
|
|
1877 | #ifdef DT_MPB |
|
|
1878 | case DT_MPB: ent->type = EIO_DT_MPB; break; |
|
|
1879 | #endif |
|
|
1880 | #ifdef DT_REG |
|
|
1881 | case DT_REG: ent->type = EIO_DT_REG; break; |
|
|
1882 | #endif |
|
|
1883 | #ifdef DT_NWK |
|
|
1884 | case DT_NWK: ent->type = EIO_DT_NWK; break; |
|
|
1885 | #endif |
|
|
1886 | #ifdef DT_CMP |
|
|
1887 | case DT_CMP: ent->type = EIO_DT_CMP; break; |
|
|
1888 | #endif |
|
|
1889 | #ifdef DT_LNK |
|
|
1890 | case DT_LNK: ent->type = EIO_DT_LNK; break; |
|
|
1891 | #endif |
|
|
1892 | #ifdef DT_SOCK |
|
|
1893 | case DT_SOCK: ent->type = EIO_DT_SOCK; break; |
|
|
1894 | #endif |
|
|
1895 | #ifdef DT_DOOR |
|
|
1896 | case DT_DOOR: ent->type = EIO_DT_DOOR; break; |
|
|
1897 | #endif |
|
|
1898 | #ifdef DT_WHT |
|
|
1899 | case DT_WHT: ent->type = EIO_DT_WHT; break; |
|
|
1900 | #endif |
|
|
1901 | } |
|
|
1902 | |
|
|
1903 | ent->score = 7; |
|
|
1904 | |
|
|
1905 | if (flags & EIO_READDIR_DIRS_FIRST) |
|
|
1906 | { |
|
|
1907 | if (ent->type == EIO_DT_UNKNOWN) |
1789 | { |
1908 | { |
1790 | if (dir->type == EIO_DT_DIR) |
1909 | if (*name == '.') /* leading dots are likely directories, and, in any case, rare */ |
1791 | ++dir; |
1910 | ent->score = 1; |
1792 | else if ((--oth)->type == EIO_DT_DIR) |
1911 | else if (!strchr (name, '.')) /* absense of dots indicate likely dirs */ |
1793 | { |
1912 | ent->score = len <= 2 ? 4 - len : len <= 4 ? 4 : len <= 7 ? 5 : 6; /* shorter == more likely dir, but avoid too many classes */ |
1794 | eio_dirent tmp = *dir; *dir = *oth; *oth = tmp; |
|
|
1795 | |
|
|
1796 | ++dir; |
|
|
1797 | } |
|
|
1798 | } |
1913 | } |
1799 | |
1914 | else if (ent->type == EIO_DT_DIR) |
1800 | /* now sort the dirs only (dirs all have the same score) */ |
1915 | ent->score = 0; |
1801 | eio_dent_sort (dents, dir - dents, 0, inode_bits); |
|
|
1802 | } |
1916 | } |
1803 | |
|
|
1804 | break; |
|
|
1805 | } |
|
|
1806 | |
|
|
1807 | /* now add the entry to our list(s) */ |
|
|
1808 | name = D_NAME (entp); |
|
|
1809 | |
|
|
1810 | /* skip . and .. entries */ |
|
|
1811 | if (name [0] != '.' || (name [1] && (name [1] != '.' || name [2]))) |
|
|
1812 | { |
|
|
1813 | int len = D_NAMLEN (entp) + 1; |
|
|
1814 | |
|
|
1815 | while (ecb_expect_false (namesoffs + len > namesalloc)) |
|
|
1816 | { |
|
|
1817 | namesalloc *= 2; |
|
|
1818 | req->ptr2 = names = realloc (names, namesalloc); |
|
|
1819 | |
|
|
1820 | if (!names) |
|
|
1821 | break; |
|
|
1822 | } |
1917 | } |
1823 | |
1918 | |
1824 | memcpy (names + namesoffs, name, len); |
|
|
1825 | |
|
|
1826 | if (dents) |
|
|
1827 | { |
|
|
1828 | struct eio_dirent *ent; |
|
|
1829 | |
|
|
1830 | if (ecb_expect_false (dentoffs == dentalloc)) |
|
|
1831 | { |
|
|
1832 | dentalloc *= 2; |
|
|
1833 | req->ptr1 = dents = realloc (dents, dentalloc * sizeof (eio_dirent)); |
|
|
1834 | |
|
|
1835 | if (!dents) |
|
|
1836 | break; |
|
|
1837 | } |
|
|
1838 | |
|
|
1839 | ent = dents + dentoffs; |
|
|
1840 | |
|
|
1841 | ent->nameofs = namesoffs; /* rather dirtily we store the offset in the pointer */ |
|
|
1842 | ent->namelen = len - 1; |
|
|
1843 | ent->inode = D_INO (entp); |
|
|
1844 | |
|
|
1845 | inode_bits |= ent->inode; |
|
|
1846 | |
|
|
1847 | switch (D_TYPE (entp)) |
|
|
1848 | { |
|
|
1849 | default: |
|
|
1850 | ent->type = EIO_DT_UNKNOWN; |
|
|
1851 | flags |= EIO_READDIR_FOUND_UNKNOWN; |
|
|
1852 | break; |
|
|
1853 | |
|
|
1854 | #ifdef DT_FIFO |
|
|
1855 | case DT_FIFO: ent->type = EIO_DT_FIFO; break; |
|
|
1856 | #endif |
|
|
1857 | #ifdef DT_CHR |
|
|
1858 | case DT_CHR: ent->type = EIO_DT_CHR; break; |
|
|
1859 | #endif |
|
|
1860 | #ifdef DT_MPC |
|
|
1861 | case DT_MPC: ent->type = EIO_DT_MPC; break; |
|
|
1862 | #endif |
|
|
1863 | #ifdef DT_DIR |
|
|
1864 | case DT_DIR: ent->type = EIO_DT_DIR; break; |
|
|
1865 | #endif |
|
|
1866 | #ifdef DT_NAM |
|
|
1867 | case DT_NAM: ent->type = EIO_DT_NAM; break; |
|
|
1868 | #endif |
|
|
1869 | #ifdef DT_BLK |
|
|
1870 | case DT_BLK: ent->type = EIO_DT_BLK; break; |
|
|
1871 | #endif |
|
|
1872 | #ifdef DT_MPB |
|
|
1873 | case DT_MPB: ent->type = EIO_DT_MPB; break; |
|
|
1874 | #endif |
|
|
1875 | #ifdef DT_REG |
|
|
1876 | case DT_REG: ent->type = EIO_DT_REG; break; |
|
|
1877 | #endif |
|
|
1878 | #ifdef DT_NWK |
|
|
1879 | case DT_NWK: ent->type = EIO_DT_NWK; break; |
|
|
1880 | #endif |
|
|
1881 | #ifdef DT_CMP |
|
|
1882 | case DT_CMP: ent->type = EIO_DT_CMP; break; |
|
|
1883 | #endif |
|
|
1884 | #ifdef DT_LNK |
|
|
1885 | case DT_LNK: ent->type = EIO_DT_LNK; break; |
|
|
1886 | #endif |
|
|
1887 | #ifdef DT_SOCK |
|
|
1888 | case DT_SOCK: ent->type = EIO_DT_SOCK; break; |
|
|
1889 | #endif |
|
|
1890 | #ifdef DT_DOOR |
|
|
1891 | case DT_DOOR: ent->type = EIO_DT_DOOR; break; |
|
|
1892 | #endif |
|
|
1893 | #ifdef DT_WHT |
|
|
1894 | case DT_WHT: ent->type = EIO_DT_WHT; break; |
|
|
1895 | #endif |
|
|
1896 | } |
|
|
1897 | |
|
|
1898 | ent->score = 7; |
|
|
1899 | |
|
|
1900 | if (flags & EIO_READDIR_DIRS_FIRST) |
|
|
1901 | { |
|
|
1902 | if (ent->type == EIO_DT_UNKNOWN) |
|
|
1903 | { |
|
|
1904 | if (*name == '.') /* leading dots are likely directories, and, in any case, rare */ |
|
|
1905 | ent->score = 1; |
|
|
1906 | else if (!strchr (name, '.')) /* absense of dots indicate likely dirs */ |
|
|
1907 | ent->score = len <= 2 ? 4 - len : len <= 4 ? 4 : len <= 7 ? 5 : 6; /* shorter == more likely dir, but avoid too many classes */ |
|
|
1908 | } |
|
|
1909 | else if (ent->type == EIO_DT_DIR) |
|
|
1910 | ent->score = 0; |
|
|
1911 | } |
|
|
1912 | } |
|
|
1913 | |
|
|
1914 | namesoffs += len; |
1919 | namesoffs += len; |
1915 | ++dentoffs; |
1920 | ++dentoffs; |
1916 | } |
1921 | } |
1917 | |
1922 | |
1918 | if (EIO_CANCELLED (req)) |
1923 | if (EIO_CANCELLED (req)) |
1919 | { |
1924 | { |
1920 | errno = ECANCELED; |
1925 | errno = ECANCELED; |
1921 | break; |
1926 | break; |
1922 | } |
1927 | } |
1923 | |
1928 | |
1924 | #ifdef _WIN32 |
1929 | #ifdef _WIN32 |
1925 | if (!FindNextFile (dirp, &entp)) |
1930 | if (!FindNextFile (dirp, &entp)) |
1926 | { |
1931 | { |
1927 | FindClose (dirp); |
1932 | FindClose (dirp); |
1928 | dirp = 0; |
1933 | dirp = 0; |
1929 | } |
1934 | } |
1930 | #endif |
1935 | #endif |
1931 | } |
1936 | } |
1932 | } |
1937 | } |
1933 | |
1938 | |
1934 | /*****************************************************************************/ |
1939 | /*****************************************************************************/ |
1935 | |
1940 | |
1936 | #define ALLOC(len) \ |
1941 | #define ALLOC(len) \ |