|
@@ -0,0 +1,142 @@
|
|
|
+#include <assert.h>
|
|
|
+#include <errno.h>
|
|
|
+#include <fcntl.h>
|
|
|
+#include <stdbool.h>
|
|
|
+#include <stdio.h>
|
|
|
+#include <string.h>
|
|
|
+#include <sys/stat.h>
|
|
|
+#include <sys/types.h>
|
|
|
+#include <unistd.h>
|
|
|
+
|
|
|
+#define STR_HELPER(x) #x
|
|
|
+#define STR(x) STR_HELPER(x)
|
|
|
+
|
|
|
+#define BUF_LENGTH 4096
|
|
|
+#define HOLE_LENGTH 8192
|
|
|
+
|
|
|
+#define TEST_DIR "tmp"
|
|
|
+#define TEST_FILE "__testfile__"
|
|
|
+
|
|
|
+ssize_t rw_file(int fd, char* buf, size_t bytes, bool write_flag) {
|
|
|
+ ssize_t rv = 0;
|
|
|
+ ssize_t ret;
|
|
|
+
|
|
|
+ while (bytes > rv) {
|
|
|
+ if (write_flag)
|
|
|
+ ret = write(fd, buf + rv, bytes - rv);
|
|
|
+ else
|
|
|
+ ret = read(fd, buf + rv, bytes - rv);
|
|
|
+
|
|
|
+ if (ret > 0) {
|
|
|
+ rv += ret;
|
|
|
+ } else {
|
|
|
+ if (ret < 0 && (errno == EAGAIN || errno == EINTR)) {
|
|
|
+ continue;
|
|
|
+ } else {
|
|
|
+ fprintf(stderr, "%s failed:%s\n", write_flag ? "write" : "read", strerror(errno));
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return rv;
|
|
|
+}
|
|
|
+
|
|
|
+int main(int argc, const char** argv) {
|
|
|
+ char buf[BUF_LENGTH];
|
|
|
+ ssize_t bytes;
|
|
|
+ int fd = 0;
|
|
|
+ int rv = 0;
|
|
|
+
|
|
|
+ memset(buf, 0, BUF_LENGTH);
|
|
|
+
|
|
|
+ /* setup the test directory and file */
|
|
|
+ rv = mkdir(TEST_DIR, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
|
|
+ if (rv < 0 && errno != EEXIST) {
|
|
|
+ perror("mkdir failed");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ rv = unlink(TEST_DIR"/"TEST_FILE);
|
|
|
+ if (rv < 0 && errno != ENOENT) {
|
|
|
+ perror("unlink failed");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ fd = open(TEST_DIR"/"TEST_FILE, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
|
|
|
+ if (fd < 0) {
|
|
|
+ perror("open failed");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* test file size: write a file of type != FILEBUF_MAP */
|
|
|
+ bytes = rw_file(fd, buf, BUF_LENGTH, true);
|
|
|
+ if (bytes != BUF_LENGTH) {
|
|
|
+ perror("writing " STR(BUF_LENGTH) " bytes to test file failed");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ rv = lseek(fd, 0, SEEK_SET);
|
|
|
+ if (rv < 0) {
|
|
|
+ perror("lseek to beginning of file failed");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ bytes = rw_file(fd, buf, 1, true);
|
|
|
+ if (bytes != 1) {
|
|
|
+ perror("writing one byte to test file failed");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ rv = lseek(fd, HOLE_LENGTH, SEEK_SET);
|
|
|
+ if (rv < 0) {
|
|
|
+ perror("lseek to " STR(HOLE_LENGTH) " offset failed");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ bytes = rw_file(fd, buf, BUF_LENGTH, true);
|
|
|
+ if (bytes != BUF_LENGTH) {
|
|
|
+ perror("writing " STR(BUF_LENGTH) " bytes to test file failed");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ rv = close(fd);
|
|
|
+ if (rv < 0) {
|
|
|
+ perror("close failed");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ fd = open(TEST_DIR"/"TEST_FILE, O_RDONLY);
|
|
|
+ if (fd < 0) {
|
|
|
+ perror("open failed");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* reopen file: file size should be HOLE_LENGTH + BUF_LENGTH */
|
|
|
+ rv = lseek(fd, HOLE_LENGTH, SEEK_SET);
|
|
|
+ if (rv < 0) {
|
|
|
+ perror("lseek to " STR(HOLE_LENGTH) " offset failed");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ bytes = rw_file(fd, buf, BUF_LENGTH, false);
|
|
|
+ if (bytes != BUF_LENGTH) {
|
|
|
+ perror("reading " STR(BUF_LENGTH) " bytes from test file failed");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ rv = close(fd);
|
|
|
+ if (rv < 0) {
|
|
|
+ perror("close failed");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ rv = unlink(TEST_DIR"/"TEST_FILE);
|
|
|
+ if (rv < 0) {
|
|
|
+ perror("unlink failed");
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ printf("test completed successfully\n");
|
|
|
+ return 0;
|
|
|
+}
|