1 /*
2 * Copyright 2018 Jonathan Dieter <jdieter@gmail.com>
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include <stdlib.h>
28 #include <stdint.h>
29 #include <stdbool.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <errno.h>
33 #include <zck.h>
34
35 #include "zck_private.h"
36
read_data(zckCtx * zck,char * data,size_t length)37 ssize_t read_data(zckCtx *zck, char *data, size_t length) {
38 VALIDATE_READ_INT(zck);
39
40 if(length == 0)
41 return 0;
42 if(data == NULL) {
43 set_error(zck, "Unable to read to NULL data pointer");
44 return -1;
45 }
46 ssize_t read_bytes = read(zck->fd, data, length);
47 if(read_bytes == -1) {
48 set_error(zck, "Error reading data: %s", strerror(errno));
49 return -1;
50 }
51 return read_bytes;
52 }
53
write_data(zckCtx * zck,int fd,const char * data,size_t length)54 int write_data(zckCtx *zck, int fd, const char *data, size_t length) {
55 VALIDATE_INT(zck);
56
57 if(length == 0)
58 return true;
59 if(data == NULL) {
60 set_error(zck, "Unable to write from NULL data pointer");
61 return false;
62 }
63 ssize_t write_bytes = write(fd, data, length);
64 if(write_bytes == -1) {
65 set_fatal_error(zck, "Error writing data: %s", strerror(errno));
66 return false;
67 } else if(write_bytes < length) {
68 // According to man page, if write is less than full amount, we should try again
69 length -= write_bytes;
70 write_bytes = write(fd, data+write_bytes, length);
71 if(write_bytes == -1) {
72 set_fatal_error(zck, "Error writing data: %s", strerror(errno));
73 return false;
74 } else if(write_bytes < length) {
75 set_fatal_error(zck, "Short write (after two attempts)");
76 return false;
77 }
78 }
79 return true;
80 }
81
seek_data(zckCtx * zck,off_t offset,int whence)82 int seek_data(zckCtx *zck, off_t offset, int whence) {
83 VALIDATE_INT(zck);
84
85 if(lseek(zck->fd, offset, whence) == -1) {
86 char *wh_str = NULL;
87
88 if(whence == SEEK_CUR) {
89 wh_str = "from current position";
90 } else if(whence == SEEK_END) {
91 wh_str = "from end of file";
92 } else if(whence == SEEK_SET) {
93 wh_str = "from beginning of file";
94 } else {
95 wh_str = "using unknown measurement";
96 }
97 set_error(zck, "Unable to seek to %lu %s: %s", offset, wh_str,
98 strerror(errno));
99 return false;
100 }
101 return true;
102 }
103
tell_data(zckCtx * zck)104 ssize_t tell_data(zckCtx *zck) {
105 ssize_t loc = lseek(zck->fd, 0, SEEK_CUR);
106 return loc;
107 }
108
chunks_from_temp(zckCtx * zck)109 int chunks_from_temp(zckCtx *zck) {
110 int read_count;
111
112 if(lseek(zck->temp_fd, 0, SEEK_SET) == -1)
113 return false;
114
115 char *data = zmalloc(BUF_SIZE);
116
117 while((read_count = read(zck->temp_fd, data, BUF_SIZE)) > 0) {
118 if(read_count == -1 || !write_data(zck, zck->fd, data, read_count)) {
119 free(data);
120 return false;
121 }
122 }
123 free(data);
124 return true;
125 }
126