/* * This function provides 64-bit offset padding that * is not supplied by GCC 1.X but is supplied by GCC 2.X. */ ssize_t _sys_pwrite(int fd, const void *buf, size_t nbyte, off_t offset) { return __pwrite(fd, buf, nbyte, 0, offset); }
/* * Erase and write function. * Param ofs: offset on flash_device. * Param data: data to write on flash. * Param rbuf: pointer to allocated buffer to copy readed data. * Param length: length of testing area */ static int erase_and_write(loff_t ofs, unsigned char *data, unsigned char *rbuf, loff_t length) { struct erase_info_user er; unsigned int i; int ret; er.start = ofs; er.length = meminfo.erasesize; ret = erase(fd, er.length, er.start); if (ret < 0) { perror("\nerase"); printf("Could't not erase flash at 0x%08x length 0x%08x.\n", er.start, er.length); return ret; } for (i = 0; i < meminfo.erasesize; i += meminfo.writesize) { /* Write data to given offset */ __pwrite(fd, data + i, meminfo.writesize, ofs + i, length); /* Read data from offset */ pread(fd, rbuf + i, meminfo.writesize, ofs + i); ret = ioctl(fd, ECCGETSTATS, &newstats); if (ret < 0) { perror("\nECCGETSTATS"); return ret; } if (newstats.corrected > oldstats.corrected) { printf("\n %d bit(s) ECC corrected at page 0x%08llx\n", newstats.corrected - oldstats.corrected, ofs + memregion.offset + i); init_progression_bar(length); show_progress(ofs + i); if ((newstats.corrected-oldstats.corrected) >= MAX_ECC_BITS) { /* Increment ECC stats that * are over MAX_ECC_BITS */ ecc_stats_over++; } else { /* Increment ECC stat value */ ecc_stats[(newstats.corrected - oldstats.corrected) - 1]++; } /* Set oldstats to newstats */ oldstats.corrected = newstats.corrected; } if (newstats.failed > oldstats.failed) { printf("\nECC failed at page 0x%08llx\n", ofs + memregion.offset + i); init_progression_bar(length); show_progress(ofs + i); oldstats.failed = newstats.failed; ecc_failed_cnt++; } } /* Compared written data with read data. * If data is not identical, display a detailed * debugging information. */ ret = memcmp(data, rbuf, meminfo.erasesize); if (ret < 0) { printf("\ncompare failed. seed %d\n", seed); for (i = 0; i < meminfo.erasesize; i++) { if (data[i] != rbuf[i]) printf("Byte 0x%x is %02x should be %02x\n", i, rbuf[i], data[i]); } return ret; } return 0; }
int posix_fallocate (int fd, __off_t offset, __off_t len) { struct stat64 st; if (offset < 0 || len < 0) return EINVAL; /* Perform overflow check. The outer cast relies on a GCC extension. */ if ((__off_t) ((uint64_t) offset + (uint64_t) len) < 0) return EFBIG; /* pwrite below will not do the right thing in O_APPEND mode. */ { int flags = __fcntl (fd, F_GETFL, 0); if (flags < 0 || (flags & O_APPEND) != 0) return EBADF; } /* We have to make sure that this is really a regular file. */ if (__fxstat64 (_STAT_VER, fd, &st) != 0) return EBADF; if (S_ISFIFO (st.st_mode)) return ESPIPE; if (! S_ISREG (st.st_mode)) return ENODEV; if (len == 0) { /* This is racy, but there is no good way to satisfy a zero-length allocation request. */ if (st.st_size < offset) { int ret = __ftruncate (fd, offset); if (ret != 0) ret = errno; return ret; } return 0; } /* Minimize data transfer for network file systems, by issuing single-byte write requests spaced by the file system block size. (Most local file systems have fallocate support, so this fallback code is not used there.) */ unsigned increment; { struct statfs64 f; if (__fstatfs64 (fd, &f) != 0) return errno; if (f.f_bsize == 0) increment = 512; else if (f.f_bsize < 4096) increment = f.f_bsize; else /* NFS does not propagate the block size of the underlying storage and may report a much larger value which would still leave holes after the loop below, so we cap the increment at 4096. */ increment = 4096; } /* Write a null byte to every block. This is racy; we currently lack a better option. Compare-and-swap against a file mapping might additional local races, but requires interposition of a signal handler to catch SIGBUS. */ for (offset += (len - 1) % increment; len > 0; offset += increment) { len -= increment; if (offset < st.st_size) { unsigned char c; ssize_t rsize = __pread (fd, &c, 1, offset); if (rsize < 0) return errno; /* If there is a non-zero byte, the block must have been allocated already. */ else if (rsize == 1 && c != 0) continue; } if (__pwrite (fd, "", 1, offset) != 1) return errno; } return 0; }