FIO_fwriteSparse() : * @return : storedSkips, * argument for next call to FIO_fwriteSparse() or FIO_fwriteSparseEnd() */
| 1922 | * @return : storedSkips, |
| 1923 | * argument for next call to FIO_fwriteSparse() or FIO_fwriteSparseEnd() */ |
| 1924 | static unsigned |
| 1925 | FIO_fwriteSparse(FILE* file, |
| 1926 | const void* buffer, size_t bufferSize, |
| 1927 | const FIO_prefs_t* const prefs, |
| 1928 | unsigned storedSkips) |
| 1929 | { |
| 1930 | const size_t* const bufferT = (const size_t*)buffer; /* Buffer is supposed malloc'ed, hence aligned on size_t */ |
| 1931 | size_t bufferSizeT = bufferSize / sizeof(size_t); |
| 1932 | const size_t* const bufferTEnd = bufferT + bufferSizeT; |
| 1933 | const size_t* ptrT = bufferT; |
| 1934 | static const size_t segmentSizeT = (32 KB) / sizeof(size_t); /* check every 32 KB */ |
| 1935 | |
| 1936 | if (prefs->testMode) return 0; /* do not output anything in test mode */ |
| 1937 | |
| 1938 | if (!prefs->sparseFileSupport) { /* normal write */ |
| 1939 | size_t const sizeCheck = fwrite(buffer, 1, bufferSize, file); |
| 1940 | if (sizeCheck != bufferSize) |
| 1941 | EXM_THROW(70, "Write error : cannot write decoded block : %s", |
| 1942 | strerror(errno)); |
| 1943 | return 0; |
| 1944 | } |
| 1945 | |
| 1946 | /* avoid int overflow */ |
| 1947 | if (storedSkips > 1 GB) { |
| 1948 | if (LONG_SEEK(file, 1 GB, SEEK_CUR) != 0) |
| 1949 | EXM_THROW(91, "1 GB skip error (sparse file support)"); |
| 1950 | storedSkips -= 1 GB; |
| 1951 | } |
| 1952 | |
| 1953 | while (ptrT < bufferTEnd) { |
| 1954 | size_t nb0T; |
| 1955 | |
| 1956 | /* adjust last segment if < 32 KB */ |
| 1957 | size_t seg0SizeT = segmentSizeT; |
| 1958 | if (seg0SizeT > bufferSizeT) seg0SizeT = bufferSizeT; |
| 1959 | bufferSizeT -= seg0SizeT; |
| 1960 | |
| 1961 | /* count leading zeroes */ |
| 1962 | for (nb0T=0; (nb0T < seg0SizeT) && (ptrT[nb0T] == 0); nb0T++) ; |
| 1963 | storedSkips += (unsigned)(nb0T * sizeof(size_t)); |
| 1964 | |
| 1965 | if (nb0T != seg0SizeT) { /* not all 0s */ |
| 1966 | size_t const nbNon0ST = seg0SizeT - nb0T; |
| 1967 | /* skip leading zeros */ |
| 1968 | if (LONG_SEEK(file, storedSkips, SEEK_CUR) != 0) |
| 1969 | EXM_THROW(92, "Sparse skip error ; try --no-sparse"); |
| 1970 | storedSkips = 0; |
| 1971 | /* write the rest */ |
| 1972 | if (fwrite(ptrT + nb0T, sizeof(size_t), nbNon0ST, file) != nbNon0ST) |
| 1973 | EXM_THROW(93, "Write error : cannot write decoded block : %s", |
| 1974 | strerror(errno)); |
| 1975 | } |
| 1976 | ptrT += seg0SizeT; |
| 1977 | } |
| 1978 | |
| 1979 | { static size_t const maskT = sizeof(size_t)-1; |
| 1980 | if (bufferSize & maskT) { |
| 1981 | /* size not multiple of sizeof(size_t) : implies end of block */ |
no test coverage detected