diff options
author | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2006-10-14 02:23:43 +0000 |
---|---|---|
committer | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2006-10-14 02:23:43 +0000 |
commit | 9e617927e057d79ceb2ac4869b18b1e84567dc68 (patch) | |
tree | 37b7584ae40b99edb5583fbc4392b62ffdadf278 /libbb/read.c | |
parent | 6147e0907e5b5e3a07a4c8976097a585faaa3895 (diff) | |
download | busybox-w32-9e617927e057d79ceb2ac4869b18b1e84567dc68.tar.gz busybox-w32-9e617927e057d79ceb2ac4869b18b1e84567dc68.tar.bz2 busybox-w32-9e617927e057d79ceb2ac4869b18b1e84567dc68.zip |
add open_read_close() and similar stuff
git-svn-id: svn://busybox.net/trunk/busybox@16377 69ca8d6d-28ef-0310-b511-8ec308f3f277
Diffstat (limited to 'libbb/read.c')
-rw-r--r-- | libbb/read.c | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/libbb/read.c b/libbb/read.c new file mode 100644 index 000000000..1c2945f45 --- /dev/null +++ b/libbb/read.c | |||
@@ -0,0 +1,133 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * Utility routines. | ||
4 | * | ||
5 | * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> | ||
6 | * | ||
7 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | ||
8 | */ | ||
9 | |||
10 | #include "libbb.h" | ||
11 | |||
12 | ssize_t safe_read(int fd, void *buf, size_t count) | ||
13 | { | ||
14 | ssize_t n; | ||
15 | |||
16 | do { | ||
17 | n = read(fd, buf, count); | ||
18 | } while (n < 0 && errno == EINTR); | ||
19 | |||
20 | return n; | ||
21 | } | ||
22 | |||
23 | /* | ||
24 | * Read all of the supplied buffer from a file. | ||
25 | * This does multiple reads as necessary. | ||
26 | * Returns the amount read, or -1 on an error. | ||
27 | * A short read is returned on an end of file. | ||
28 | */ | ||
29 | ssize_t full_read(int fd, void *buf, size_t len) | ||
30 | { | ||
31 | ssize_t cc; | ||
32 | ssize_t total; | ||
33 | |||
34 | total = 0; | ||
35 | |||
36 | while (len) { | ||
37 | cc = safe_read(fd, buf, len); | ||
38 | |||
39 | if (cc < 0) | ||
40 | return cc; /* read() returns -1 on failure. */ | ||
41 | |||
42 | if (cc == 0) | ||
43 | break; | ||
44 | |||
45 | buf = ((char *)buf) + cc; | ||
46 | total += cc; | ||
47 | len -= cc; | ||
48 | } | ||
49 | |||
50 | return total; | ||
51 | } | ||
52 | |||
53 | // Die with an error message if we can't read the entire buffer. | ||
54 | void xread(int fd, void *buf, size_t count) | ||
55 | { | ||
56 | if (count) { | ||
57 | ssize_t size = full_read(fd, buf, count); | ||
58 | if (size != count) | ||
59 | bb_error_msg_and_die("short read"); | ||
60 | } | ||
61 | } | ||
62 | |||
63 | // Die with an error message if we can't read one character. | ||
64 | unsigned char xread_char(int fd) | ||
65 | { | ||
66 | char tmp; | ||
67 | |||
68 | xread(fd, &tmp, 1); | ||
69 | |||
70 | return tmp; | ||
71 | } | ||
72 | |||
73 | // Read one line a-la fgets. Works only on seekable streams | ||
74 | char *reads(int fd, char *buffer, size_t size) | ||
75 | { | ||
76 | char *p; | ||
77 | |||
78 | if (size < 2) | ||
79 | return NULL; | ||
80 | size = full_read(fd, buffer, size-1); | ||
81 | if ((ssize_t)size <= 0) | ||
82 | return NULL; | ||
83 | |||
84 | buffer[size] = '\0'; | ||
85 | p = strchr(buffer, '\n'); | ||
86 | if (p) { | ||
87 | off_t offset; | ||
88 | *p++ = '\0'; | ||
89 | offset = (p-buffer) - size; | ||
90 | // set fd position the right after the \n | ||
91 | if (offset && lseek(fd, offset, SEEK_CUR) == (off_t)-1) | ||
92 | return NULL; | ||
93 | } | ||
94 | return buffer; | ||
95 | } | ||
96 | |||
97 | ssize_t read_close(int fd, void *buf, size_t size) | ||
98 | { | ||
99 | int e; | ||
100 | size = full_read(fd, buf, size); | ||
101 | e = errno; | ||
102 | close(fd); | ||
103 | errno = e; | ||
104 | return size; | ||
105 | } | ||
106 | |||
107 | ssize_t open_read_close(const char *filename, void *buf, size_t size) | ||
108 | { | ||
109 | int fd = open(filename, O_RDONLY); | ||
110 | if (fd < 0) | ||
111 | return fd; | ||
112 | return read_close(fd, buf, size); | ||
113 | } | ||
114 | |||
115 | void *xmalloc_open_read_close(const char *filename, size_t *sizep) | ||
116 | { | ||
117 | char *buf; | ||
118 | size_t size = sizep ? *sizep : INT_MAX; | ||
119 | int fd = xopen(filename, O_RDONLY); | ||
120 | off_t len = xlseek(fd, 0, SEEK_END); | ||
121 | xlseek(fd, 0, SEEK_SET); | ||
122 | |||
123 | if (len > size) | ||
124 | bb_error_msg_and_die("file '%s' is too big", filename); | ||
125 | size = len; | ||
126 | buf = xmalloc(size+1); | ||
127 | size = read_close(fd, buf, size); | ||
128 | if ((ssize_t)size < 0) | ||
129 | bb_perror_msg_and_die("'%s'", filename); | ||
130 | buf[size] = '\0'; | ||
131 | if (sizep) *sizep = size; | ||
132 | return buf; | ||
133 | } | ||