xref: /aosp_15_r20/external/tpm2-tss/src/tss2-fapi/ifapi_io.c (revision 758e9fba6fc9adbf15340f70c73baee7b168b1c9)
1*758e9fbaSOystein Eftevaag /* SPDX-License-Identifier: BSD-2-Clause */
2*758e9fbaSOystein Eftevaag /*******************************************************************************
3*758e9fbaSOystein Eftevaag  * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
4*758e9fbaSOystein Eftevaag  * All rights reserved.
5*758e9fbaSOystein Eftevaag  *******************************************************************************/
6*758e9fbaSOystein Eftevaag 
7*758e9fbaSOystein Eftevaag #ifdef HAVE_CONFIG_H
8*758e9fbaSOystein Eftevaag #include <config.h>
9*758e9fbaSOystein Eftevaag #endif
10*758e9fbaSOystein Eftevaag 
11*758e9fbaSOystein Eftevaag #include <stdio.h>
12*758e9fbaSOystein Eftevaag #include <stdlib.h>
13*758e9fbaSOystein Eftevaag #include <unistd.h>
14*758e9fbaSOystein Eftevaag #include <sys/stat.h>
15*758e9fbaSOystein Eftevaag #include <fcntl.h>
16*758e9fbaSOystein Eftevaag #include <poll.h>
17*758e9fbaSOystein Eftevaag #include <errno.h>
18*758e9fbaSOystein Eftevaag #include <sys/types.h>
19*758e9fbaSOystein Eftevaag #include <dirent.h>
20*758e9fbaSOystein Eftevaag /* Need for some libc-versions */
21*758e9fbaSOystein Eftevaag #ifndef __FreeBSD__
22*758e9fbaSOystein Eftevaag #include <malloc.h>
23*758e9fbaSOystein Eftevaag #endif
24*758e9fbaSOystein Eftevaag 
25*758e9fbaSOystein Eftevaag #include "tss2_common.h"
26*758e9fbaSOystein Eftevaag #include "ifapi_io.h"
27*758e9fbaSOystein Eftevaag #include "ifapi_helpers.h"
28*758e9fbaSOystein Eftevaag #include "ifapi_macros.h"
29*758e9fbaSOystein Eftevaag #define LOGMODULE fapi
30*758e9fbaSOystein Eftevaag #include "util/log.h"
31*758e9fbaSOystein Eftevaag #include "util/aux_util.h"
32*758e9fbaSOystein Eftevaag 
33*758e9fbaSOystein Eftevaag /** Start reading a file's complete content into memory in an asynchronous way.
34*758e9fbaSOystein Eftevaag  *
35*758e9fbaSOystein Eftevaag  * @param[in,out] io The input/output context being used for file I/O.
36*758e9fbaSOystein Eftevaag  * @param[in] filename The name of the file to be read into memory.
37*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS: if the function call was a success.
38*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR: if an I/O error was encountered; such as the file was not found.
39*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated to hold the read data.
40*758e9fbaSOystein Eftevaag  */
41*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_io_read_async(struct IFAPI_IO * io,const char * filename)42*758e9fbaSOystein Eftevaag ifapi_io_read_async(
43*758e9fbaSOystein Eftevaag     struct IFAPI_IO *io,
44*758e9fbaSOystein Eftevaag     const char *filename)
45*758e9fbaSOystein Eftevaag {
46*758e9fbaSOystein Eftevaag     if (io->char_rbuffer) {
47*758e9fbaSOystein Eftevaag         LOG_ERROR("rbuffer still in use; maybe use of old API.");
48*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_IO_ERROR;
49*758e9fbaSOystein Eftevaag     }
50*758e9fbaSOystein Eftevaag 
51*758e9fbaSOystein Eftevaag     io->stream = fopen(filename, "rt");
52*758e9fbaSOystein Eftevaag     if (io->stream == NULL) {
53*758e9fbaSOystein Eftevaag         LOG_ERROR("File \"%s\" not found.", filename);
54*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_IO_ERROR;
55*758e9fbaSOystein Eftevaag     }
56*758e9fbaSOystein Eftevaag     /* Locking the file. Lock will be release upon close */
57*758e9fbaSOystein Eftevaag     if (lockf(fileno(io->stream), F_TLOCK, 0) == -1 && errno == EAGAIN) {
58*758e9fbaSOystein Eftevaag         LOG_ERROR("File %s currently locked.", filename);
59*758e9fbaSOystein Eftevaag         fclose(io->stream);
60*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_IO_ERROR;
61*758e9fbaSOystein Eftevaag     }
62*758e9fbaSOystein Eftevaag 
63*758e9fbaSOystein Eftevaag     fseek(io->stream, 0L, SEEK_END);
64*758e9fbaSOystein Eftevaag     long length = ftell(io->stream);
65*758e9fbaSOystein Eftevaag     fclose(io->stream);
66*758e9fbaSOystein Eftevaag 
67*758e9fbaSOystein Eftevaag     io->stream = fopen(filename, "rt");
68*758e9fbaSOystein Eftevaag     io->char_rbuffer = malloc (length + 1);
69*758e9fbaSOystein Eftevaag     if (io->char_rbuffer == NULL) {
70*758e9fbaSOystein Eftevaag         fclose(io->stream);
71*758e9fbaSOystein Eftevaag         io->stream = NULL;
72*758e9fbaSOystein Eftevaag         LOG_ERROR("Memory could not be allocated. %li bytes requested", length + 1);
73*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_MEMORY;
74*758e9fbaSOystein Eftevaag     }
75*758e9fbaSOystein Eftevaag 
76*758e9fbaSOystein Eftevaag     int rc, flags = fcntl(fileno(io->stream), F_GETFL, 0);
77*758e9fbaSOystein Eftevaag     rc = fcntl(fileno(io->stream), F_SETFL, flags | O_NONBLOCK);
78*758e9fbaSOystein Eftevaag     if (rc < 0) {
79*758e9fbaSOystein Eftevaag         LOG_ERROR("fcntl failed with %d", errno);
80*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_IO_ERROR;
81*758e9fbaSOystein Eftevaag     }
82*758e9fbaSOystein Eftevaag 
83*758e9fbaSOystein Eftevaag     io->buffer_length = length;
84*758e9fbaSOystein Eftevaag     io->buffer_idx = 0;
85*758e9fbaSOystein Eftevaag     io->char_rbuffer[length] = '\0';
86*758e9fbaSOystein Eftevaag 
87*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
88*758e9fbaSOystein Eftevaag }
89*758e9fbaSOystein Eftevaag 
90*758e9fbaSOystein Eftevaag /** Finish reading a file's complete content into memory in an asynchronous way.
91*758e9fbaSOystein Eftevaag  *
92*758e9fbaSOystein Eftevaag  * This function needs to be called repeatedly until it does not return TSS2_FAPI_RC_TRY_AGAIN.
93*758e9fbaSOystein Eftevaag  *
94*758e9fbaSOystein Eftevaag  * @param[in,out] io The input/output context being used for file I/O.
95*758e9fbaSOystein Eftevaag  * @param[out] buffer The data that was read from file. (callee-allocated; use free())
96*758e9fbaSOystein Eftevaag  * @param[out] length The length of the data that was read from file.
97*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS: if the function call was a success.
98*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR: if an I/O error was encountered; such as the file was not found.
99*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet complete.
100*758e9fbaSOystein Eftevaag  *         Call this function again later.
101*758e9fbaSOystein Eftevaag  */
102*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_io_read_finish(struct IFAPI_IO * io,uint8_t ** buffer,size_t * length)103*758e9fbaSOystein Eftevaag ifapi_io_read_finish(
104*758e9fbaSOystein Eftevaag     struct IFAPI_IO *io,
105*758e9fbaSOystein Eftevaag     uint8_t **buffer,
106*758e9fbaSOystein Eftevaag     size_t *length)
107*758e9fbaSOystein Eftevaag {
108*758e9fbaSOystein Eftevaag     io->pollevents = POLLIN;
109*758e9fbaSOystein Eftevaag     if (_ifapi_io_retry-- > 0)
110*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_TRY_AGAIN;
111*758e9fbaSOystein Eftevaag     else
112*758e9fbaSOystein Eftevaag         _ifapi_io_retry = _IFAPI_IO_RETRIES;
113*758e9fbaSOystein Eftevaag 
114*758e9fbaSOystein Eftevaag     ssize_t ret = read(fileno(io->stream),
115*758e9fbaSOystein Eftevaag                        &io->char_rbuffer[io->buffer_idx],
116*758e9fbaSOystein Eftevaag                        io->buffer_length - io->buffer_idx);
117*758e9fbaSOystein Eftevaag     if (ret < 0 && (errno == EINTR || errno == EAGAIN))
118*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_TRY_AGAIN;
119*758e9fbaSOystein Eftevaag 
120*758e9fbaSOystein Eftevaag     if (ret < 0) {
121*758e9fbaSOystein Eftevaag         LOG_ERROR("Error reading from file: %i.", errno);
122*758e9fbaSOystein Eftevaag         fclose(io->stream);
123*758e9fbaSOystein Eftevaag         io->pollevents = 0;
124*758e9fbaSOystein Eftevaag         SAFE_FREE(io->char_rbuffer);
125*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_IO_ERROR;
126*758e9fbaSOystein Eftevaag     }
127*758e9fbaSOystein Eftevaag 
128*758e9fbaSOystein Eftevaag     io->pollevents = 0;
129*758e9fbaSOystein Eftevaag     io->buffer_idx += ret;
130*758e9fbaSOystein Eftevaag     if (io->buffer_idx < io->buffer_length)
131*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_TRY_AGAIN;
132*758e9fbaSOystein Eftevaag 
133*758e9fbaSOystein Eftevaag     fclose(io->stream);
134*758e9fbaSOystein Eftevaag 
135*758e9fbaSOystein Eftevaag     if (!buffer) {
136*758e9fbaSOystein Eftevaag         LOG_WARNING("The old file read API is still being used");
137*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
138*758e9fbaSOystein Eftevaag     }
139*758e9fbaSOystein Eftevaag     *buffer = (uint8_t *)io->char_rbuffer;
140*758e9fbaSOystein Eftevaag     io->char_rbuffer = NULL;
141*758e9fbaSOystein Eftevaag 
142*758e9fbaSOystein Eftevaag     if (length)
143*758e9fbaSOystein Eftevaag         *length = io->buffer_length;
144*758e9fbaSOystein Eftevaag 
145*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
146*758e9fbaSOystein Eftevaag }
147*758e9fbaSOystein Eftevaag 
148*758e9fbaSOystein Eftevaag /** Start writing a buffer into a file in an asynchronous way.
149*758e9fbaSOystein Eftevaag  *
150*758e9fbaSOystein Eftevaag  * @param[in,out] io The input/output context being used for file I/O.
151*758e9fbaSOystein Eftevaag  * @param[in] filename The name of the file to be read into memory.
152*758e9fbaSOystein Eftevaag  * @param[in] buffer The buffer to be written.
153*758e9fbaSOystein Eftevaag  * @param[in] length The number of bytes to be written.
154*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS: if the function call was a success.
155*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR: if an I/O error was encountered; such as the file was not found.
156*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated to hold the read data.
157*758e9fbaSOystein Eftevaag  */
158*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_io_write_async(struct IFAPI_IO * io,const char * filename,const uint8_t * buffer,size_t length)159*758e9fbaSOystein Eftevaag ifapi_io_write_async(
160*758e9fbaSOystein Eftevaag     struct IFAPI_IO *io,
161*758e9fbaSOystein Eftevaag     const char *filename,
162*758e9fbaSOystein Eftevaag     const uint8_t *buffer,
163*758e9fbaSOystein Eftevaag     size_t length)
164*758e9fbaSOystein Eftevaag {
165*758e9fbaSOystein Eftevaag     if (io->char_rbuffer) {
166*758e9fbaSOystein Eftevaag         LOG_ERROR("rbuffer still in use; maybe use of old API.");
167*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_IO_ERROR;
168*758e9fbaSOystein Eftevaag     }
169*758e9fbaSOystein Eftevaag 
170*758e9fbaSOystein Eftevaag     io->buffer_length = length;
171*758e9fbaSOystein Eftevaag     io->buffer_idx = 0;
172*758e9fbaSOystein Eftevaag     io->char_rbuffer = malloc(length);
173*758e9fbaSOystein Eftevaag     if (io->char_rbuffer == NULL) {
174*758e9fbaSOystein Eftevaag         LOG_ERROR("Memory could not be allocated. %zi bytes requested", length);
175*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_MEMORY;
176*758e9fbaSOystein Eftevaag     }
177*758e9fbaSOystein Eftevaag     memcpy(io->char_rbuffer, buffer, length);
178*758e9fbaSOystein Eftevaag 
179*758e9fbaSOystein Eftevaag     io->stream = fopen(filename, "wt");
180*758e9fbaSOystein Eftevaag     if (io->stream == NULL) {
181*758e9fbaSOystein Eftevaag         SAFE_FREE(io->char_rbuffer);
182*758e9fbaSOystein Eftevaag         LOG_ERROR("Could not open file \"%s\" for writing.", filename);
183*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_IO_ERROR;
184*758e9fbaSOystein Eftevaag     }
185*758e9fbaSOystein Eftevaag     /* Locking the file. Lock will be release upon close */
186*758e9fbaSOystein Eftevaag     if (lockf(fileno(io->stream), F_TLOCK, 0) == -1 && errno == EAGAIN) {
187*758e9fbaSOystein Eftevaag         LOG_ERROR("File %s currently locked.", filename);
188*758e9fbaSOystein Eftevaag         fclose(io->stream);
189*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_IO_ERROR;
190*758e9fbaSOystein Eftevaag     }
191*758e9fbaSOystein Eftevaag 
192*758e9fbaSOystein Eftevaag     /* Use non blocking IO, so asynchronous write will be needed */
193*758e9fbaSOystein Eftevaag     int rc, flags = fcntl(fileno(io->stream), F_GETFL, 0);
194*758e9fbaSOystein Eftevaag     rc = fcntl(fileno(io->stream), F_SETFL, flags | O_NONBLOCK);
195*758e9fbaSOystein Eftevaag     if (rc < 0) {
196*758e9fbaSOystein Eftevaag         LOG_ERROR("fcntl failed with %d", errno);
197*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_IO_ERROR;
198*758e9fbaSOystein Eftevaag     }
199*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
200*758e9fbaSOystein Eftevaag }
201*758e9fbaSOystein Eftevaag 
202*758e9fbaSOystein Eftevaag /** Finish writing a buffer into a file in an asynchronous way.
203*758e9fbaSOystein Eftevaag  *
204*758e9fbaSOystein Eftevaag  * This function needs to be called repeatedly until it does not return TSS2_FAPI_RC_TRY_AGAIN.
205*758e9fbaSOystein Eftevaag  *
206*758e9fbaSOystein Eftevaag  * @param[in,out] io The input/output context being used for file I/O.
207*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS: if the function call was a success.
208*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR: if an I/O error was encountered; such as the file was not found.
209*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet complete.
210*758e9fbaSOystein Eftevaag  *         Call this function again later.
211*758e9fbaSOystein Eftevaag  */
212*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_io_write_finish(struct IFAPI_IO * io)213*758e9fbaSOystein Eftevaag ifapi_io_write_finish(
214*758e9fbaSOystein Eftevaag     struct IFAPI_IO *io)
215*758e9fbaSOystein Eftevaag {
216*758e9fbaSOystein Eftevaag     io->pollevents = POLLOUT;
217*758e9fbaSOystein Eftevaag     if (_ifapi_io_retry-- > 0)
218*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_TRY_AGAIN;
219*758e9fbaSOystein Eftevaag     else
220*758e9fbaSOystein Eftevaag         _ifapi_io_retry = _IFAPI_IO_RETRIES;
221*758e9fbaSOystein Eftevaag 
222*758e9fbaSOystein Eftevaag     ssize_t ret = write(fileno(io->stream),
223*758e9fbaSOystein Eftevaag                         &io->char_rbuffer[io->buffer_idx],
224*758e9fbaSOystein Eftevaag                         io->buffer_length - io->buffer_idx);
225*758e9fbaSOystein Eftevaag     if (ret < 0 && (errno == EINTR || errno == EAGAIN))
226*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_TRY_AGAIN;
227*758e9fbaSOystein Eftevaag 
228*758e9fbaSOystein Eftevaag     if (ret < 0) {
229*758e9fbaSOystein Eftevaag         LOG_ERROR("Error writing to file: %i.", errno);
230*758e9fbaSOystein Eftevaag         fclose(io->stream);
231*758e9fbaSOystein Eftevaag         io->pollevents = 0;
232*758e9fbaSOystein Eftevaag         SAFE_FREE(io->char_rbuffer);
233*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_IO_ERROR;
234*758e9fbaSOystein Eftevaag     }
235*758e9fbaSOystein Eftevaag 
236*758e9fbaSOystein Eftevaag     io->pollevents = 0;
237*758e9fbaSOystein Eftevaag     io->buffer_idx += ret;
238*758e9fbaSOystein Eftevaag     if (io->buffer_idx < io->buffer_length)
239*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_TRY_AGAIN;
240*758e9fbaSOystein Eftevaag 
241*758e9fbaSOystein Eftevaag     SAFE_FREE(io->char_rbuffer);
242*758e9fbaSOystein Eftevaag     fclose(io->stream);
243*758e9fbaSOystein Eftevaag 
244*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
245*758e9fbaSOystein Eftevaag }
246*758e9fbaSOystein Eftevaag 
247*758e9fbaSOystein Eftevaag /** Check whether a file is writeable.
248*758e9fbaSOystein Eftevaag  *
249*758e9fbaSOystein Eftevaag  * @param[in] file  The name of the fileto be checked.
250*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS if the directories existed or were successfully created
251*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR if an I/O error occurred
252*758e9fbaSOystein Eftevaag  */
253*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_io_check_file_writeable(const char * file)254*758e9fbaSOystein Eftevaag ifapi_io_check_file_writeable(
255*758e9fbaSOystein Eftevaag     const char *file)
256*758e9fbaSOystein Eftevaag {
257*758e9fbaSOystein Eftevaag     /* Check access rights to file  */
258*758e9fbaSOystein Eftevaag     if (access(file, W_OK)) {
259*758e9fbaSOystein Eftevaag         return_error2(TSS2_FAPI_RC_IO_ERROR, "File %s is not writeable.", file);
260*758e9fbaSOystein Eftevaag     }
261*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
262*758e9fbaSOystein Eftevaag }
263*758e9fbaSOystein Eftevaag 
264*758e9fbaSOystein Eftevaag /** Check for the existence of a directory and create it if it does not yet exist.
265*758e9fbaSOystein Eftevaag  *
266*758e9fbaSOystein Eftevaag  * @param[in] dirname The name of the directory to be checked / created
267*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS if the directories existed or were successfully created
268*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR if an I/O error occurred
269*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
270*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
271*758e9fbaSOystein Eftevaag  *         the function.
272*758e9fbaSOystein Eftevaag  */
273*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_io_check_create_dir(const char * dirname)274*758e9fbaSOystein Eftevaag ifapi_io_check_create_dir(
275*758e9fbaSOystein Eftevaag     const char *dirname)
276*758e9fbaSOystein Eftevaag {
277*758e9fbaSOystein Eftevaag     TSS2_RC r;
278*758e9fbaSOystein Eftevaag     struct stat fbuffer;
279*758e9fbaSOystein Eftevaag 
280*758e9fbaSOystein Eftevaag     /* Check existence of dirname and try to create it otherwise */
281*758e9fbaSOystein Eftevaag     if (stat(dirname, &fbuffer)) {
282*758e9fbaSOystein Eftevaag         LOG_WARNING("Directory %s does not exist, creating", dirname);
283*758e9fbaSOystein Eftevaag 
284*758e9fbaSOystein Eftevaag         r = ifapi_create_dirs("", dirname);
285*758e9fbaSOystein Eftevaag         return_if_error2(r, "Directory %s can't be created.", dirname);
286*758e9fbaSOystein Eftevaag 
287*758e9fbaSOystein Eftevaag         LOG_DEBUG("Created directory: %s", dirname);
288*758e9fbaSOystein Eftevaag     }
289*758e9fbaSOystein Eftevaag 
290*758e9fbaSOystein Eftevaag     /* Check access rights to dirname */
291*758e9fbaSOystein Eftevaag     if (access(dirname, W_OK)) {
292*758e9fbaSOystein Eftevaag         return_error2(TSS2_FAPI_RC_IO_ERROR, "Directory %s is not writeable.", dirname);
293*758e9fbaSOystein Eftevaag     }
294*758e9fbaSOystein Eftevaag 
295*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
296*758e9fbaSOystein Eftevaag }
297*758e9fbaSOystein Eftevaag 
298*758e9fbaSOystein Eftevaag /** Remove a file.
299*758e9fbaSOystein Eftevaag  *
300*758e9fbaSOystein Eftevaag  * @param[in] file The absolute path of the file to be removed.
301*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS If the file was successfully removed
302*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR If the file could not be removed.
303*758e9fbaSOystein Eftevaag  */
304*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_io_remove_file(const char * file)305*758e9fbaSOystein Eftevaag ifapi_io_remove_file(const char *file)
306*758e9fbaSOystein Eftevaag {
307*758e9fbaSOystein Eftevaag     if (remove(file) != 0) {
308*758e9fbaSOystein Eftevaag         LOG_ERROR("File: %s can't be deleted.", file);
309*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_IO_ERROR;
310*758e9fbaSOystein Eftevaag     }
311*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
312*758e9fbaSOystein Eftevaag }
313*758e9fbaSOystein Eftevaag 
314*758e9fbaSOystein Eftevaag /** Remove a directory recursively; i.e. including its subdirectories.
315*758e9fbaSOystein Eftevaag  *
316*758e9fbaSOystein Eftevaag  * @param[in] dirname The directory to be removed
317*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS if the directories were successfully removed
318*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR if an I/O error occurred
319*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated to hold the read data.
320*758e9fbaSOystein Eftevaag  */
321*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_io_remove_directories(const char * dirname)322*758e9fbaSOystein Eftevaag ifapi_io_remove_directories(
323*758e9fbaSOystein Eftevaag     const char *dirname)
324*758e9fbaSOystein Eftevaag {
325*758e9fbaSOystein Eftevaag     DIR *dir;
326*758e9fbaSOystein Eftevaag     struct dirent *entry;
327*758e9fbaSOystein Eftevaag     TSS2_RC r;
328*758e9fbaSOystein Eftevaag     char *path;
329*758e9fbaSOystein Eftevaag 
330*758e9fbaSOystein Eftevaag     LOG_TRACE("Removing directory: %s", dirname);
331*758e9fbaSOystein Eftevaag 
332*758e9fbaSOystein Eftevaag     if (!(dir = opendir(dirname))) {
333*758e9fbaSOystein Eftevaag         return_error2(TSS2_FAPI_RC_IO_ERROR, "Could not open directory: %s",
334*758e9fbaSOystein Eftevaag                       dirname);
335*758e9fbaSOystein Eftevaag     }
336*758e9fbaSOystein Eftevaag 
337*758e9fbaSOystein Eftevaag     /* Iterating through the list of entries inside the directory. */
338*758e9fbaSOystein Eftevaag     while ((entry = readdir(dir)) != NULL) {
339*758e9fbaSOystein Eftevaag         LOG_TRACE("Deleting directory entry %s", entry->d_name);
340*758e9fbaSOystein Eftevaag 
341*758e9fbaSOystein Eftevaag         /* Entries . and .. are obviously ignored */
342*758e9fbaSOystein Eftevaag         if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
343*758e9fbaSOystein Eftevaag             continue;
344*758e9fbaSOystein Eftevaag 
345*758e9fbaSOystein Eftevaag         /* If an entry is a directory then we call ourself recursively to remove those */
346*758e9fbaSOystein Eftevaag         if (entry->d_type == DT_DIR) {
347*758e9fbaSOystein Eftevaag             r = ifapi_asprintf(&path, "%s/%s", dirname, entry->d_name);
348*758e9fbaSOystein Eftevaag             goto_if_error(r, "Out of memory", error_cleanup);
349*758e9fbaSOystein Eftevaag 
350*758e9fbaSOystein Eftevaag             r = ifapi_io_remove_directories(path);
351*758e9fbaSOystein Eftevaag             free(path);
352*758e9fbaSOystein Eftevaag             goto_if_error(r, "remove directories.", error_cleanup);
353*758e9fbaSOystein Eftevaag 
354*758e9fbaSOystein Eftevaag             continue;
355*758e9fbaSOystein Eftevaag         }
356*758e9fbaSOystein Eftevaag 
357*758e9fbaSOystein Eftevaag         /* If an entry is a file or symlink or anything else, we remove it */
358*758e9fbaSOystein Eftevaag         r = ifapi_asprintf(&path, "%s/%s", dirname, entry->d_name);
359*758e9fbaSOystein Eftevaag         goto_if_error(r, "Out of memory", error_cleanup);
360*758e9fbaSOystein Eftevaag 
361*758e9fbaSOystein Eftevaag         LOG_WARNING("Found a file in directory; removing: %s", path);
362*758e9fbaSOystein Eftevaag 
363*758e9fbaSOystein Eftevaag         if (remove(path) != 0) {
364*758e9fbaSOystein Eftevaag             free(path);
365*758e9fbaSOystein Eftevaag             closedir(dir);
366*758e9fbaSOystein Eftevaag             return_error2(TSS2_FAPI_RC_IO_ERROR, "Removing file");
367*758e9fbaSOystein Eftevaag         }
368*758e9fbaSOystein Eftevaag 
369*758e9fbaSOystein Eftevaag         free(path);
370*758e9fbaSOystein Eftevaag     }
371*758e9fbaSOystein Eftevaag     closedir(dir);
372*758e9fbaSOystein Eftevaag     LOG_TRACE("Removing target directory %s", dirname);
373*758e9fbaSOystein Eftevaag 
374*758e9fbaSOystein Eftevaag     if (rmdir(dirname) != 0)
375*758e9fbaSOystein Eftevaag         return_error2(TSS2_FAPI_RC_IO_ERROR, "Removing directory: %s", dirname);
376*758e9fbaSOystein Eftevaag 
377*758e9fbaSOystein Eftevaag     LOG_TRACE("SUCCESS");
378*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
379*758e9fbaSOystein Eftevaag 
380*758e9fbaSOystein Eftevaag error_cleanup:
381*758e9fbaSOystein Eftevaag     closedir(dir);
382*758e9fbaSOystein Eftevaag     return r;
383*758e9fbaSOystein Eftevaag }
384*758e9fbaSOystein Eftevaag 
385*758e9fbaSOystein Eftevaag /** Enumerate the list of files in a directory.
386*758e9fbaSOystein Eftevaag  *
387*758e9fbaSOystein Eftevaag  * Enumerage the regular files (no directories, symlinks etc) from a given directory.
388*758e9fbaSOystein Eftevaag  *
389*758e9fbaSOystein Eftevaag  * @param[in] dirname The directory to list files from.
390*758e9fbaSOystein Eftevaag  * @param[out] files The list of file names.
391*758e9fbaSOystein Eftevaag  * @param[out] numfiles The size of files.
392*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS if the directories were successfully removed
393*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR if an I/O error occurred
394*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated to hold the read data.
395*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
396*758e9fbaSOystein Eftevaag  */
397*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_io_dirfiles(const char * dirname,char *** files,size_t * numfiles)398*758e9fbaSOystein Eftevaag ifapi_io_dirfiles(
399*758e9fbaSOystein Eftevaag     const char *dirname,
400*758e9fbaSOystein Eftevaag     char ***files,
401*758e9fbaSOystein Eftevaag     size_t *numfiles)
402*758e9fbaSOystein Eftevaag {
403*758e9fbaSOystein Eftevaag     DIR *dir;
404*758e9fbaSOystein Eftevaag     struct dirent *entry;
405*758e9fbaSOystein Eftevaag     char **paths;
406*758e9fbaSOystein Eftevaag     size_t numpaths = 0;
407*758e9fbaSOystein Eftevaag     check_not_null(dirname);
408*758e9fbaSOystein Eftevaag     check_not_null(files);
409*758e9fbaSOystein Eftevaag     check_not_null(numfiles);
410*758e9fbaSOystein Eftevaag 
411*758e9fbaSOystein Eftevaag     LOG_TRACE("Removing directory: %s", dirname);
412*758e9fbaSOystein Eftevaag 
413*758e9fbaSOystein Eftevaag     paths = calloc(10, sizeof(*paths));
414*758e9fbaSOystein Eftevaag     check_oom(paths);
415*758e9fbaSOystein Eftevaag 
416*758e9fbaSOystein Eftevaag     if (!(dir = opendir(dirname))) {
417*758e9fbaSOystein Eftevaag         free(paths);
418*758e9fbaSOystein Eftevaag         return_error2(TSS2_FAPI_RC_IO_ERROR, "Could not open directory: %s",
419*758e9fbaSOystein Eftevaag                       dirname);
420*758e9fbaSOystein Eftevaag     }
421*758e9fbaSOystein Eftevaag 
422*758e9fbaSOystein Eftevaag     /* Iterating through the list of entries inside the directory. */
423*758e9fbaSOystein Eftevaag     while ((entry = readdir(dir)) != NULL) {
424*758e9fbaSOystein Eftevaag         LOG_TRACE("Looking at %s", entry->d_name);
425*758e9fbaSOystein Eftevaag         if (entry->d_type != DT_REG)
426*758e9fbaSOystein Eftevaag             continue;
427*758e9fbaSOystein Eftevaag 
428*758e9fbaSOystein Eftevaag         if (numpaths % 10 == 9) {
429*758e9fbaSOystein Eftevaag #ifdef HAVE_REALLOCARRAY
430*758e9fbaSOystein Eftevaag             paths = reallocarray(paths, numpaths + 10, sizeof(*paths));
431*758e9fbaSOystein Eftevaag #else /* HAVE_REALLOCARRAY */
432*758e9fbaSOystein Eftevaag             paths = realloc(paths, (numpaths + 10) * sizeof(*paths));
433*758e9fbaSOystein Eftevaag #endif /* HAVE_REALLOCARRAY */
434*758e9fbaSOystein Eftevaag             if (!paths)
435*758e9fbaSOystein Eftevaag                 closedir(dir);
436*758e9fbaSOystein Eftevaag             check_oom(paths);
437*758e9fbaSOystein Eftevaag         }
438*758e9fbaSOystein Eftevaag 
439*758e9fbaSOystein Eftevaag         paths[numpaths] = strdup(entry->d_name);
440*758e9fbaSOystein Eftevaag         if (!paths[numpaths])
441*758e9fbaSOystein Eftevaag             goto error_oom;
442*758e9fbaSOystein Eftevaag 
443*758e9fbaSOystein Eftevaag         LOG_TRACE("Added %s to the list at index %zi", paths[numpaths], numpaths);
444*758e9fbaSOystein Eftevaag         numpaths += 1;
445*758e9fbaSOystein Eftevaag     }
446*758e9fbaSOystein Eftevaag     closedir(dir);
447*758e9fbaSOystein Eftevaag 
448*758e9fbaSOystein Eftevaag     *files = paths;
449*758e9fbaSOystein Eftevaag     *numfiles = numpaths;
450*758e9fbaSOystein Eftevaag 
451*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
452*758e9fbaSOystein Eftevaag 
453*758e9fbaSOystein Eftevaag error_oom:
454*758e9fbaSOystein Eftevaag     closedir(dir);
455*758e9fbaSOystein Eftevaag     LOG_ERROR("Out of memory");
456*758e9fbaSOystein Eftevaag     for (size_t i = 0; i < numpaths; i++)
457*758e9fbaSOystein Eftevaag         free(paths[i]);
458*758e9fbaSOystein Eftevaag     free(paths);
459*758e9fbaSOystein Eftevaag     return TSS2_FAPI_RC_MEMORY;
460*758e9fbaSOystein Eftevaag }
461*758e9fbaSOystein Eftevaag 
462*758e9fbaSOystein Eftevaag /** Get a linked list of files in a directory and all sub directories.
463*758e9fbaSOystein Eftevaag  *
464*758e9fbaSOystein Eftevaag  * Enumerage the regular files (no directories, symlinks etc) from a given directory.
465*758e9fbaSOystein Eftevaag  *
466*758e9fbaSOystein Eftevaag  * @param[in]  dir_name The directory to list files from.
467*758e9fbaSOystein Eftevaag  * @param[out] list  The linked list with the file names.
468*758e9fbaSOystein Eftevaag  * @param[out] n The number of filesl
469*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS if the directories were successfully removed
470*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated to hold the read data.
471*758e9fbaSOystein Eftevaag  */
472*758e9fbaSOystein Eftevaag static TSS2_RC
dirfiles_all(const char * dir_name,NODE_OBJECT_T ** list,size_t * n)473*758e9fbaSOystein Eftevaag dirfiles_all(const char *dir_name, NODE_OBJECT_T **list, size_t *n)
474*758e9fbaSOystein Eftevaag {
475*758e9fbaSOystein Eftevaag     DIR *dir;
476*758e9fbaSOystein Eftevaag     struct dirent *entry;
477*758e9fbaSOystein Eftevaag     TSS2_RC r;
478*758e9fbaSOystein Eftevaag     char *path;
479*758e9fbaSOystein Eftevaag     NODE_OBJECT_T *second;
480*758e9fbaSOystein Eftevaag 
481*758e9fbaSOystein Eftevaag     if (!(dir = opendir(dir_name))) {
482*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
483*758e9fbaSOystein Eftevaag     }
484*758e9fbaSOystein Eftevaag 
485*758e9fbaSOystein Eftevaag     /* Iterating through the list of entries inside the directory. */
486*758e9fbaSOystein Eftevaag     while ((entry = readdir(dir)) != NULL) {
487*758e9fbaSOystein Eftevaag         path = NULL;
488*758e9fbaSOystein Eftevaag         if (entry->d_type == DT_DIR) {
489*758e9fbaSOystein Eftevaag             /* Recursive call for sub directories */
490*758e9fbaSOystein Eftevaag             if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
491*758e9fbaSOystein Eftevaag                 continue;
492*758e9fbaSOystein Eftevaag             r = ifapi_asprintf(&path, "%s/%s", dir_name, entry->d_name);
493*758e9fbaSOystein Eftevaag             if (r)
494*758e9fbaSOystein Eftevaag                 closedir(dir);
495*758e9fbaSOystein Eftevaag             return_if_error(r, "Out of memory");
496*758e9fbaSOystein Eftevaag 
497*758e9fbaSOystein Eftevaag             LOG_TRACE("Directory: %s", path);
498*758e9fbaSOystein Eftevaag             r = dirfiles_all(path, list, n);
499*758e9fbaSOystein Eftevaag             SAFE_FREE(path);
500*758e9fbaSOystein Eftevaag             if (r)
501*758e9fbaSOystein Eftevaag                 closedir(dir);
502*758e9fbaSOystein Eftevaag             return_if_error(r, "get_entities");
503*758e9fbaSOystein Eftevaag 
504*758e9fbaSOystein Eftevaag         } else {
505*758e9fbaSOystein Eftevaag             r = ifapi_asprintf(&path, "%s/%s", dir_name, entry->d_name);
506*758e9fbaSOystein Eftevaag             if (r)
507*758e9fbaSOystein Eftevaag                 closedir(dir);
508*758e9fbaSOystein Eftevaag             return_if_error(r, "Out of memory");
509*758e9fbaSOystein Eftevaag 
510*758e9fbaSOystein Eftevaag             NODE_OBJECT_T *file_obj = calloc(sizeof(NODE_OBJECT_T), 1);
511*758e9fbaSOystein Eftevaag             if (!file_obj) {
512*758e9fbaSOystein Eftevaag                 LOG_ERROR("Out of memory.");
513*758e9fbaSOystein Eftevaag                 SAFE_FREE(path);
514*758e9fbaSOystein Eftevaag                 closedir(dir);
515*758e9fbaSOystein Eftevaag                 return TSS2_FAPI_RC_MEMORY;
516*758e9fbaSOystein Eftevaag             }
517*758e9fbaSOystein Eftevaag 
518*758e9fbaSOystein Eftevaag             *n += 1;
519*758e9fbaSOystein Eftevaag             /* Add file name to linked list */
520*758e9fbaSOystein Eftevaag             file_obj->object = strdup(path);
521*758e9fbaSOystein Eftevaag             if (file_obj->object == NULL) {
522*758e9fbaSOystein Eftevaag                 LOG_ERROR("Out of memory.");
523*758e9fbaSOystein Eftevaag                 SAFE_FREE(file_obj);
524*758e9fbaSOystein Eftevaag                 SAFE_FREE(path);
525*758e9fbaSOystein Eftevaag                 closedir(dir);
526*758e9fbaSOystein Eftevaag                 return TSS2_FAPI_RC_MEMORY;
527*758e9fbaSOystein Eftevaag             }
528*758e9fbaSOystein Eftevaag             if (*list != NULL) {
529*758e9fbaSOystein Eftevaag                 second = *list;
530*758e9fbaSOystein Eftevaag                 file_obj->next = second;
531*758e9fbaSOystein Eftevaag             }
532*758e9fbaSOystein Eftevaag             *list = file_obj;
533*758e9fbaSOystein Eftevaag             LOG_TRACE("File: %s", path);
534*758e9fbaSOystein Eftevaag             SAFE_FREE(path);
535*758e9fbaSOystein Eftevaag         }
536*758e9fbaSOystein Eftevaag     }
537*758e9fbaSOystein Eftevaag     closedir(dir);
538*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
539*758e9fbaSOystein Eftevaag }
540*758e9fbaSOystein Eftevaag 
541*758e9fbaSOystein Eftevaag 
542*758e9fbaSOystein Eftevaag /** Recursive enumerate the list of files in a directory.
543*758e9fbaSOystein Eftevaag  *
544*758e9fbaSOystein Eftevaag  * Enumerage the regular files (no directories, symlinks etc) from a given directory.
545*758e9fbaSOystein Eftevaag  *
546*758e9fbaSOystein Eftevaag  * @param[in] searchPath The directory to list files from.
547*758e9fbaSOystein Eftevaag  * @param[out] pathlist The list of file names.
548*758e9fbaSOystein Eftevaag  * @param[out] numPaths The size of files.
549*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS if the directories were successfully removed
550*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR if an I/O error occurred
551*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY: if memory could not be allocated to hold the read data.
552*758e9fbaSOystein Eftevaag  */
553*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_io_dirfiles_all(const char * searchPath,char *** pathlist,size_t * numPaths)554*758e9fbaSOystein Eftevaag ifapi_io_dirfiles_all(
555*758e9fbaSOystein Eftevaag     const char *searchPath,
556*758e9fbaSOystein Eftevaag     char ***pathlist,
557*758e9fbaSOystein Eftevaag     size_t *numPaths)
558*758e9fbaSOystein Eftevaag {
559*758e9fbaSOystein Eftevaag     TSS2_RC r;
560*758e9fbaSOystein Eftevaag     size_t n;
561*758e9fbaSOystein Eftevaag     NODE_OBJECT_T *head;
562*758e9fbaSOystein Eftevaag 
563*758e9fbaSOystein Eftevaag     *numPaths = 0;
564*758e9fbaSOystein Eftevaag     char **pathlist2;
565*758e9fbaSOystein Eftevaag 
566*758e9fbaSOystein Eftevaag     NODE_OBJECT_T *file_list = NULL;
567*758e9fbaSOystein Eftevaag     r = dirfiles_all(searchPath, &file_list, numPaths);
568*758e9fbaSOystein Eftevaag     goto_if_error(r, "get all sub files of directory", cleanup);
569*758e9fbaSOystein Eftevaag 
570*758e9fbaSOystein Eftevaag     if (*numPaths > 0) {
571*758e9fbaSOystein Eftevaag         size_t size_path_list = *numPaths * sizeof(char *);
572*758e9fbaSOystein Eftevaag         pathlist2 = calloc(1, size_path_list);
573*758e9fbaSOystein Eftevaag         goto_if_null2(pathlist2, "Out of memory.", r, TSS2_FAPI_RC_MEMORY,
574*758e9fbaSOystein Eftevaag                       cleanup);
575*758e9fbaSOystein Eftevaag         n = *numPaths;
576*758e9fbaSOystein Eftevaag 
577*758e9fbaSOystein Eftevaag         /* Move file names from list to array */
578*758e9fbaSOystein Eftevaag         while (n > 0 && file_list) {
579*758e9fbaSOystein Eftevaag             n -= 1;
580*758e9fbaSOystein Eftevaag             pathlist2[n] = file_list->object;
581*758e9fbaSOystein Eftevaag             head = file_list;
582*758e9fbaSOystein Eftevaag             file_list = file_list->next;
583*758e9fbaSOystein Eftevaag             SAFE_FREE(head);
584*758e9fbaSOystein Eftevaag         }
585*758e9fbaSOystein Eftevaag         *pathlist = pathlist2;
586*758e9fbaSOystein Eftevaag     }
587*758e9fbaSOystein Eftevaag cleanup:
588*758e9fbaSOystein Eftevaag     /* Free linked list with file names */
589*758e9fbaSOystein Eftevaag     while (file_list) {
590*758e9fbaSOystein Eftevaag         head = file_list;
591*758e9fbaSOystein Eftevaag         file_list = file_list->next;
592*758e9fbaSOystein Eftevaag         SAFE_FREE(head);
593*758e9fbaSOystein Eftevaag     }
594*758e9fbaSOystein Eftevaag     return r;
595*758e9fbaSOystein Eftevaag }
596*758e9fbaSOystein Eftevaag 
597*758e9fbaSOystein Eftevaag /** Determine whether a path exists.
598*758e9fbaSOystein Eftevaag  *
599*758e9fbaSOystein Eftevaag  * @param[in] path The absolute path of the file.
600*758e9fbaSOystein Eftevaag  * @retval true The file exists.
601*758e9fbaSOystein Eftevaag  * @retval false The file does not exist.
602*758e9fbaSOystein Eftevaag  */
603*758e9fbaSOystein Eftevaag bool
ifapi_io_path_exists(const char * path)604*758e9fbaSOystein Eftevaag ifapi_io_path_exists(const char *path)
605*758e9fbaSOystein Eftevaag {
606*758e9fbaSOystein Eftevaag     struct stat fbuffer;
607*758e9fbaSOystein Eftevaag 
608*758e9fbaSOystein Eftevaag     if (stat(path, &fbuffer) == 0)
609*758e9fbaSOystein Eftevaag         return true;
610*758e9fbaSOystein Eftevaag     else
611*758e9fbaSOystein Eftevaag         return false;
612*758e9fbaSOystein Eftevaag }
613*758e9fbaSOystein Eftevaag 
614*758e9fbaSOystein Eftevaag 
615*758e9fbaSOystein Eftevaag /** Wait for file I/O to be ready.
616*758e9fbaSOystein Eftevaag  *
617*758e9fbaSOystein Eftevaag  * If FAPI state automata are in a file I/O state it will be waited for an
618*758e9fbaSOystein Eftevaag  * event on a file descriptor.
619*758e9fbaSOystein Eftevaag  *
620*758e9fbaSOystein Eftevaag  * @param[in] io The input/output context being used for file I/O.
621*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS After the end of the wait.
622*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_IO_ERROR if the poll function returns an error.
623*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
624*758e9fbaSOystein Eftevaag  */
625*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_io_poll(IFAPI_IO * io)626*758e9fbaSOystein Eftevaag ifapi_io_poll(IFAPI_IO * io) {
627*758e9fbaSOystein Eftevaag     int rc;
628*758e9fbaSOystein Eftevaag     /* Check for NULL parameters */
629*758e9fbaSOystein Eftevaag     check_not_null(io);
630*758e9fbaSOystein Eftevaag 
631*758e9fbaSOystein Eftevaag     if (io->pollevents) {
632*758e9fbaSOystein Eftevaag         struct pollfd fds;
633*758e9fbaSOystein Eftevaag         fds.events = io->pollevents;
634*758e9fbaSOystein Eftevaag         fds.fd = fileno(io->stream);
635*758e9fbaSOystein Eftevaag         LOG_TRACE("Waiting for fd %i with event %i", fds.fd, fds.events);
636*758e9fbaSOystein Eftevaag         rc = poll(&fds, 1, -1);
637*758e9fbaSOystein Eftevaag         if (rc < 0) {
638*758e9fbaSOystein Eftevaag             LOG_ERROR("Poll failed with %d", errno);
639*758e9fbaSOystein Eftevaag             return TSS2_FAPI_RC_IO_ERROR;
640*758e9fbaSOystein Eftevaag         }
641*758e9fbaSOystein Eftevaag     }
642*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
643*758e9fbaSOystein Eftevaag }
644*758e9fbaSOystein Eftevaag 
645*758e9fbaSOystein Eftevaag /**  Get a list of poll handles.
646*758e9fbaSOystein Eftevaag  *
647*758e9fbaSOystein Eftevaag  * @param[in] io The input/output context being used for file I/O.
648*758e9fbaSOystein Eftevaag  * @param[out] handles The array with the poll handles.
649*758e9fbaSOystein Eftevaag  * @param[out] num_handles The number of poll handles.
650*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
651*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_NO_HANDLE In no poll events are stored in IO context.
652*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY If the output data cannot be allocated.
653*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
654*758e9fbaSOystein Eftevaag  */
655*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_io_poll_handles(IFAPI_IO * io,FAPI_POLL_HANDLE ** handles,size_t * num_handles)656*758e9fbaSOystein Eftevaag ifapi_io_poll_handles(IFAPI_IO *io, FAPI_POLL_HANDLE **handles, size_t *num_handles) {
657*758e9fbaSOystein Eftevaag     /* Check for NULL parameters */
658*758e9fbaSOystein Eftevaag     check_not_null(io);
659*758e9fbaSOystein Eftevaag     check_not_null(handles);
660*758e9fbaSOystein Eftevaag     check_not_null(num_handles);
661*758e9fbaSOystein Eftevaag 
662*758e9fbaSOystein Eftevaag     if (!io->pollevents) {
663*758e9fbaSOystein Eftevaag         /* We're not spilling out error here, because this is called in the
664*758e9fbaSOystein Eftevaag            functional path of Fapi_GetPollHandles(). */
665*758e9fbaSOystein Eftevaag         LOG_DEBUG("No pollable operation in progress.");
666*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_NO_HANDLE;
667*758e9fbaSOystein Eftevaag     }
668*758e9fbaSOystein Eftevaag 
669*758e9fbaSOystein Eftevaag     *handles = calloc(1, sizeof(**handles));
670*758e9fbaSOystein Eftevaag     check_oom(*handles);
671*758e9fbaSOystein Eftevaag     (*handles)->events = io->pollevents;
672*758e9fbaSOystein Eftevaag     (*handles)->fd = fileno(io->stream);
673*758e9fbaSOystein Eftevaag     *num_handles = 1;
674*758e9fbaSOystein Eftevaag 
675*758e9fbaSOystein Eftevaag     LOG_TRACE("Returning %zi poll handles for fd %i with event %i",
676*758e9fbaSOystein Eftevaag               *num_handles, (*handles)->fd, (*handles)->events);
677*758e9fbaSOystein Eftevaag 
678*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
679*758e9fbaSOystein Eftevaag }
680