Line | Count | Source |
1 | | /* This file is part of GDBM, the GNU data base manager. |
2 | | Copyright (C) 2011-2025 Free Software Foundation, Inc. |
3 | | |
4 | | GDBM is free software; you can redistribute it and/or modify |
5 | | it under the terms of the GNU General Public License as published by |
6 | | the Free Software Foundation; either version 3, or (at your option) |
7 | | any later version. |
8 | | |
9 | | GDBM is distributed in the hope that it will be useful, |
10 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | | GNU General Public License for more details. |
13 | | |
14 | | You should have received a copy of the GNU General Public License |
15 | | along with GDBM. If not, see <http://www.gnu.org/licenses/>. */ |
16 | | |
17 | | #include "autoconf.h" |
18 | | #include "gdbmdefs.h" |
19 | | |
20 | | /* Read exactly SIZE bytes of data into BUFFER. Return value is 0 on |
21 | | success, and -1 on error. In the latter case, gdbm_errno is set to |
22 | | GDBM_FILE_EOF, if not enough data is available, and to |
23 | | GDBM_FILE_READ_ERROR, if a read error occurs. */ |
24 | | int |
25 | | _gdbm_full_read (GDBM_FILE dbf, void *buffer, size_t size) |
26 | 4.07M | { |
27 | 4.07M | char *ptr = buffer; |
28 | 5.19M | while (size) |
29 | 1.25M | { |
30 | 1.25M | ssize_t rdbytes = gdbm_file_read (dbf, ptr, size); |
31 | 1.25M | if (rdbytes == -1) |
32 | 270 | { |
33 | 270 | if (errno == EINTR) |
34 | 0 | continue; |
35 | 270 | if (gdbm_last_errno (dbf) == GDBM_NO_ERROR) |
36 | 270 | GDBM_SET_ERRNO (dbf, GDBM_FILE_READ_ERROR, FALSE); |
37 | 270 | return -1; |
38 | 270 | } |
39 | 1.25M | if (rdbytes == 0) |
40 | 145k | { |
41 | 145k | GDBM_SET_ERRNO (dbf, GDBM_FILE_EOF, FALSE); |
42 | 145k | return -1; |
43 | 145k | } |
44 | 1.11M | ptr += rdbytes; |
45 | 1.11M | size -= rdbytes; |
46 | 1.11M | } |
47 | 3.93M | return 0; |
48 | 4.07M | } |
49 | | |
50 | | /* Write exactly SIZE bytes of data from BUFFER to DBF. Return 0 on |
51 | | success, and -1 (setting gdbm_errno to GDBM_FILE_READ_ERROR) on error. */ |
52 | | int |
53 | | _gdbm_full_write (GDBM_FILE dbf, void *buffer, size_t size) |
54 | 800k | { |
55 | 800k | char *ptr = buffer; |
56 | | |
57 | | /* Invalidate file_size */ |
58 | 800k | dbf->file_size = -1; |
59 | 1.41M | while (size) |
60 | 612k | { |
61 | 612k | ssize_t wrbytes = gdbm_file_write (dbf, ptr, size); |
62 | 612k | if (wrbytes == -1) |
63 | 0 | { |
64 | 0 | if (errno == EINTR) |
65 | 0 | continue; |
66 | 0 | if (gdbm_last_errno (dbf) == GDBM_NO_ERROR) |
67 | 0 | GDBM_SET_ERRNO (dbf, GDBM_FILE_WRITE_ERROR, TRUE); |
68 | 0 | return -1; |
69 | 0 | } |
70 | 612k | if (wrbytes == 0) |
71 | 0 | { |
72 | 0 | errno = ENOSPC; |
73 | 0 | GDBM_SET_ERRNO (dbf, GDBM_FILE_WRITE_ERROR, TRUE); |
74 | 0 | return -1; |
75 | 0 | } |
76 | 612k | ptr += wrbytes; |
77 | 612k | size -= wrbytes; |
78 | 612k | } |
79 | 800k | return 0; |
80 | 800k | } |
81 | | |
82 | | /* Grow the disk file of DBF to SIZE bytes in length. Fill the |
83 | | newly allocated space with zeros. */ |
84 | | int |
85 | | _gdbm_file_extend (GDBM_FILE dbf, off_t size) |
86 | 212k | { |
87 | 212k | size_t page_size = sysconf (_SC_PAGESIZE); |
88 | 212k | char *buf; |
89 | 212k | off_t file_end; |
90 | | |
91 | 212k | file_end = lseek (dbf->desc, 0, SEEK_END); |
92 | 212k | if (!file_end) |
93 | 0 | { |
94 | 0 | GDBM_SET_ERRNO (dbf, GDBM_FILE_SEEK_ERROR, FALSE); |
95 | 0 | return -1; |
96 | 0 | } |
97 | 212k | size -= file_end; |
98 | 212k | if (size > 0) |
99 | 104k | { |
100 | 104k | if (size < page_size) |
101 | 19.3k | page_size = size; |
102 | 104k | buf = calloc (1, page_size); |
103 | 104k | if (!buf) |
104 | 0 | { |
105 | 0 | GDBM_SET_ERRNO (dbf, GDBM_MALLOC_ERROR, FALSE); |
106 | 0 | return -1; |
107 | 0 | } |
108 | | |
109 | | /* Invalidate file_size */ |
110 | 104k | dbf->file_size = -1; |
111 | | |
112 | 2.39M | while (size) |
113 | 2.28M | { |
114 | 2.28M | ssize_t n = write (dbf->desc, buf, |
115 | 2.28M | size < page_size ? size : page_size); |
116 | 2.28M | if (n <= 0) |
117 | 0 | { |
118 | 0 | GDBM_SET_ERRNO (dbf, GDBM_FILE_WRITE_ERROR, TRUE); |
119 | 0 | break; |
120 | 0 | } |
121 | 2.28M | size -= n; |
122 | 2.28M | } |
123 | 104k | free (buf); |
124 | 104k | if (size) |
125 | 0 | return -1; |
126 | 104k | } |
127 | 212k | return 0; |
128 | 212k | } |
129 | | |