blob: 9eed077d9a23185e774dec212fa74ee72da67ae1 [file] [log] [blame]
Radek Krejcid3ca0632019-04-16 16:54:54 +02001/**
Michal Vaskoafac7822020-10-20 14:22:26 +02002 * @file out.c
Radek Krejcid3ca0632019-04-16 16:54:54 +02003 * @author Radek Krejci <rkrejci@cesnet.cz>
Michal Vaskoafac7822020-10-20 14:22:26 +02004 * @brief libyang output functions.
Radek Krejcid3ca0632019-04-16 16:54:54 +02005 *
Michal Vaskoafac7822020-10-20 14:22:26 +02006 * Copyright (c) 2015 - 2020 CESNET, z.s.p.o.
Radek Krejcid3ca0632019-04-16 16:54:54 +02007 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
Christian Hopps32874e12021-05-01 09:43:54 -040015#define _GNU_SOURCE /* asprintf, strdup */
Radek Krejcid3ca0632019-04-16 16:54:54 +020016
Michal Vaskoafac7822020-10-20 14:22:26 +020017#include "out.h"
18#include "out_internal.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020019
20#include <assert.h>
Radek Krejcid3ca0632019-04-16 16:54:54 +020021#include <errno.h>
22#include <stdarg.h>
Radek Krejci47fab892020-11-05 17:02:41 +010023#include <stdint.h>
Radek Krejcie7b95092019-05-15 11:03:07 +020024#include <stdio.h>
25#include <stdlib.h>
Radek Krejcid3ca0632019-04-16 16:54:54 +020026#include <string.h>
Radek Krejcie7b95092019-05-15 11:03:07 +020027#include <unistd.h>
Radek Krejcid3ca0632019-04-16 16:54:54 +020028
Michal Vasko5aa44c02020-06-29 11:47:02 +020029#include "compat.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020030#include "log.h"
Michal Vasko8f702ee2024-02-20 15:44:24 +010031#include "ly_common.h"
aPiecek6cf1d162023-11-08 16:07:00 +010032#include "metadata.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020033#include "printer_data.h"
Radek Krejci47fab892020-11-05 17:02:41 +010034#include "tree_data.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020035#include "tree_schema.h"
Radek Krejcid3ca0632019-04-16 16:54:54 +020036
aPiecek61d76952021-08-30 10:28:04 +020037/**
38 * @brief Align the desired size to 1 KB.
39 */
40#define REALLOC_CHUNK(NEW_SIZE) \
41 NEW_SIZE + (1024 - (NEW_SIZE % 1024))
42
Michal Vasko8db584d2022-03-30 13:42:48 +020043LIBYANG_API_DEF ly_bool
44lyd_node_should_print(const struct lyd_node *node, uint32_t options)
Michal Vasko9b368d32020-02-14 13:53:31 +010045{
Michal Vaskob4fd37f2021-02-26 10:09:44 +010046 const struct lyd_node *elem;
Michal Vasko9b368d32020-02-14 13:53:31 +010047
Radek Krejci7931b192020-06-25 17:05:03 +020048 if (options & LYD_PRINT_WD_TRIM) {
Michal Vasko9b368d32020-02-14 13:53:31 +010049 /* do not print default nodes */
50 if (node->flags & LYD_DEFAULT) {
51 /* implicit default node/NP container with only default nodes */
52 return 0;
Michal Vaskobd777662021-07-09 13:58:40 +020053 } else if (node->schema && (node->schema->nodetype & LYD_NODE_TERM)) {
Radek Krejci19611252020-10-04 13:54:53 +020054 if (lyd_is_default(node)) {
Michal Vasko9b368d32020-02-14 13:53:31 +010055 /* explicit default node */
56 return 0;
57 }
58 }
Michal Vasko1dd384e2021-07-08 13:59:55 +020059 } else if ((node->flags & LYD_DEFAULT) && (node->schema->nodetype == LYS_CONTAINER)) {
60 if (options & LYD_PRINT_KEEPEMPTYCONT) {
61 /* explicit request to print */
62 return 1;
63 }
64
65 /* avoid empty default containers */
66 LYD_TREE_DFS_BEGIN(node, elem) {
Michal Vasko8db584d2022-03-30 13:42:48 +020067 if ((elem != node) && lyd_node_should_print(elem, options)) {
Michal Vasko1dd384e2021-07-08 13:59:55 +020068 return 1;
69 }
70 assert(elem->flags & LYD_DEFAULT);
71 LYD_TREE_DFS_END(node, elem)
72 }
73 return 0;
Michal Vasko0d5ea7e2021-02-26 10:10:15 +010074 } else if ((node->flags & LYD_DEFAULT) && !(options & LYD_PRINT_WD_MASK) && !(node->schema->flags & LYS_CONFIG_R)) {
Michal Vasko5be03d62020-12-09 18:08:39 +010075 /* LYD_PRINT_WD_EXPLICIT, find out if this is some input/output */
Michal Vaskob4fd37f2021-02-26 10:09:44 +010076 if (!(node->schema->flags & (LYS_IS_INPUT | LYS_IS_OUTPUT | LYS_IS_NOTIF)) && (node->schema->flags & LYS_CONFIG_W)) {
Michal Vasko5be03d62020-12-09 18:08:39 +010077 /* print only if it contains status data in its subtree */
78 LYD_TREE_DFS_BEGIN(node, elem) {
79 if ((elem->schema->nodetype != LYS_CONTAINER) || (elem->schema->flags & LYS_PRESENCE)) {
80 if (elem->schema->flags & LYS_CONFIG_R) {
81 return 1;
82 }
Michal Vaskodb4f9e42020-06-01 17:29:56 +020083 }
Michal Vasko5be03d62020-12-09 18:08:39 +010084 LYD_TREE_DFS_END(node, elem)
Michal Vasko9b368d32020-02-14 13:53:31 +010085 }
Michal Vasko9b368d32020-02-14 13:53:31 +010086 }
87 return 0;
Michal Vasko9b368d32020-02-14 13:53:31 +010088 }
89
90 return 1;
91}
92
aPiecek6cf1d162023-11-08 16:07:00 +010093LIBYANG_API_DEF ly_bool
94lyd_metadata_should_print(const struct lyd_meta *meta)
95{
96 const char *arg;
97
98 assert(meta->annotation);
99
100 arg = meta->annotation->argument;
101 if (!strcmp(arg, "lyds_tree")) {
102 return 0;
103 } else {
104 return 1;
105 }
106}
107
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100108LIBYANG_API_DEF LY_OUT_TYPE
Radek Krejci241f6b52020-05-21 18:13:49 +0200109ly_out_type(const struct ly_out *out)
Radek Krejcia5bba312020-01-09 15:41:20 +0100110{
Radek Krejci241f6b52020-05-21 18:13:49 +0200111 LY_CHECK_ARG_RET(NULL, out, LY_OUT_ERROR);
Radek Krejcia5bba312020-01-09 15:41:20 +0100112 return out->type;
113}
114
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100115LIBYANG_API_DEF LY_ERR
Michal Vaskoce2b8742020-08-24 13:20:25 +0200116ly_out_new_clb(ly_write_clb writeclb, void *user_data, struct ly_out **out)
Radek Krejcia5bba312020-01-09 15:41:20 +0100117{
Radek Krejci84ce7b12020-06-11 17:28:25 +0200118 LY_CHECK_ARG_RET(NULL, out, writeclb, LY_EINVAL);
Radek Krejcia5bba312020-01-09 15:41:20 +0100119
Radek Krejci84ce7b12020-06-11 17:28:25 +0200120 *out = calloc(1, sizeof **out);
121 LY_CHECK_ERR_RET(!*out, LOGMEM(NULL), LY_EMEM);
Radek Krejcia5bba312020-01-09 15:41:20 +0100122
Radek Krejci84ce7b12020-06-11 17:28:25 +0200123 (*out)->type = LY_OUT_CALLBACK;
124 (*out)->method.clb.func = writeclb;
Michal Vaskoce2b8742020-08-24 13:20:25 +0200125 (*out)->method.clb.arg = user_data;
Radek Krejcia5bba312020-01-09 15:41:20 +0100126
Radek Krejci84ce7b12020-06-11 17:28:25 +0200127 return LY_SUCCESS;
Radek Krejcia5bba312020-01-09 15:41:20 +0100128}
129
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100130LIBYANG_API_DEF ly_write_clb
Michal Vasko69730152020-10-09 16:30:07 +0200131ly_out_clb(struct ly_out *out, ly_write_clb writeclb)
Radek Krejcia5bba312020-01-09 15:41:20 +0100132{
Michal Vasko59e90fc2021-09-22 12:17:08 +0200133 ly_write_clb prev_clb;
Radek Krejcia5bba312020-01-09 15:41:20 +0100134
Radek Krejci241f6b52020-05-21 18:13:49 +0200135 LY_CHECK_ARG_RET(NULL, out, out->type == LY_OUT_CALLBACK, NULL);
Radek Krejcia5bba312020-01-09 15:41:20 +0100136
137 prev_clb = out->method.clb.func;
138
139 if (writeclb) {
140 out->method.clb.func = writeclb;
141 }
142
143 return prev_clb;
144}
145
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100146LIBYANG_API_DEF void *
Radek Krejci241f6b52020-05-21 18:13:49 +0200147ly_out_clb_arg(struct ly_out *out, void *arg)
Radek Krejcia5bba312020-01-09 15:41:20 +0100148{
149 void *prev_arg;
150
Radek Krejci241f6b52020-05-21 18:13:49 +0200151 LY_CHECK_ARG_RET(NULL, out, out->type == LY_OUT_CALLBACK, NULL);
Radek Krejcia5bba312020-01-09 15:41:20 +0100152
153 prev_arg = out->method.clb.arg;
154
155 if (arg) {
156 out->method.clb.arg = arg;
157 }
158
159 return prev_arg;
160}
161
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100162LIBYANG_API_DEF LY_ERR
Radek Krejci84ce7b12020-06-11 17:28:25 +0200163ly_out_new_fd(int fd, struct ly_out **out)
Radek Krejcia5bba312020-01-09 15:41:20 +0100164{
Radek Krejci84ce7b12020-06-11 17:28:25 +0200165 LY_CHECK_ARG_RET(NULL, out, fd != -1, LY_EINVAL);
Radek Krejcia5bba312020-01-09 15:41:20 +0100166
Radek Krejci84ce7b12020-06-11 17:28:25 +0200167 *out = calloc(1, sizeof **out);
168 LY_CHECK_ERR_RET(!*out, LOGMEM(NULL), LY_EMEM);
Radek Krejci84ce7b12020-06-11 17:28:25 +0200169 (*out)->type = LY_OUT_FD;
170 (*out)->method.fd = fd;
Radek Krejcia5bba312020-01-09 15:41:20 +0100171
Radek Krejci84ce7b12020-06-11 17:28:25 +0200172 return LY_SUCCESS;
Radek Krejcia5bba312020-01-09 15:41:20 +0100173}
174
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100175LIBYANG_API_DEF int
Radek Krejci241f6b52020-05-21 18:13:49 +0200176ly_out_fd(struct ly_out *out, int fd)
Radek Krejcia5bba312020-01-09 15:41:20 +0100177{
178 int prev_fd;
179
Radek Krejci241f6b52020-05-21 18:13:49 +0200180 LY_CHECK_ARG_RET(NULL, out, out->type <= LY_OUT_FDSTREAM, -1);
Radek Krejcia5bba312020-01-09 15:41:20 +0100181
Radek Krejci241f6b52020-05-21 18:13:49 +0200182 if (out->type == LY_OUT_FDSTREAM) {
Radek Krejcia5bba312020-01-09 15:41:20 +0100183 prev_fd = out->method.fdstream.fd;
Radek Krejci241f6b52020-05-21 18:13:49 +0200184 } else { /* LY_OUT_FD */
Radek Krejcia5bba312020-01-09 15:41:20 +0100185 prev_fd = out->method.fd;
186 }
187
188 if (fd != -1) {
189 /* replace output stream */
Radek Krejci241f6b52020-05-21 18:13:49 +0200190 if (out->type == LY_OUT_FDSTREAM) {
Radek Krejcia5bba312020-01-09 15:41:20 +0100191 int streamfd;
192 FILE *stream;
193
194 streamfd = dup(fd);
195 if (streamfd < 0) {
196 LOGERR(NULL, LY_ESYS, "Unable to duplicate provided file descriptor (%d) for printing the output (%s).", fd, strerror(errno));
197 return -1;
198 }
199 stream = fdopen(streamfd, "a");
200 if (!stream) {
201 LOGERR(NULL, LY_ESYS, "Unable to open provided file descriptor (%d) for printing the output (%s).", fd, strerror(errno));
202 close(streamfd);
203 return -1;
204 }
205 /* close only the internally created stream, file descriptor is returned and supposed to be closed by the caller */
206 fclose(out->method.fdstream.f);
207 out->method.fdstream.f = stream;
208 out->method.fdstream.fd = streamfd;
Radek Krejci241f6b52020-05-21 18:13:49 +0200209 } else { /* LY_OUT_FD */
Radek Krejcia5bba312020-01-09 15:41:20 +0100210 out->method.fd = fd;
211 }
212 }
213
214 return prev_fd;
215}
216
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100217LIBYANG_API_DEF LY_ERR
Radek Krejci84ce7b12020-06-11 17:28:25 +0200218ly_out_new_file(FILE *f, struct ly_out **out)
Radek Krejcia5bba312020-01-09 15:41:20 +0100219{
Radek Krejci84ce7b12020-06-11 17:28:25 +0200220 LY_CHECK_ARG_RET(NULL, out, f, LY_EINVAL);
Radek Krejcia5bba312020-01-09 15:41:20 +0100221
Radek Krejci84ce7b12020-06-11 17:28:25 +0200222 *out = calloc(1, sizeof **out);
223 LY_CHECK_ERR_RET(!*out, LOGMEM(NULL), LY_EMEM);
Radek Krejcia5bba312020-01-09 15:41:20 +0100224
Radek Krejci84ce7b12020-06-11 17:28:25 +0200225 (*out)->type = LY_OUT_FILE;
226 (*out)->method.f = f;
Radek Krejcia5bba312020-01-09 15:41:20 +0100227
Radek Krejci84ce7b12020-06-11 17:28:25 +0200228 return LY_SUCCESS;
Radek Krejcia5bba312020-01-09 15:41:20 +0100229}
230
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100231LIBYANG_API_DEF FILE *
Radek Krejci241f6b52020-05-21 18:13:49 +0200232ly_out_file(struct ly_out *out, FILE *f)
Radek Krejcia5bba312020-01-09 15:41:20 +0100233{
234 FILE *prev_f;
235
Radek Krejci241f6b52020-05-21 18:13:49 +0200236 LY_CHECK_ARG_RET(NULL, out, out->type == LY_OUT_FILE, NULL);
Radek Krejcia5bba312020-01-09 15:41:20 +0100237
238 prev_f = out->method.f;
239
240 if (f) {
241 out->method.f = f;
242 }
243
244 return prev_f;
245}
246
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100247LIBYANG_API_DEF LY_ERR
Radek Krejci84ce7b12020-06-11 17:28:25 +0200248ly_out_new_memory(char **strp, size_t size, struct ly_out **out)
Radek Krejcia5bba312020-01-09 15:41:20 +0100249{
Radek Krejci84ce7b12020-06-11 17:28:25 +0200250 LY_CHECK_ARG_RET(NULL, out, strp, LY_EINVAL);
Radek Krejcia5bba312020-01-09 15:41:20 +0100251
Radek Krejci84ce7b12020-06-11 17:28:25 +0200252 *out = calloc(1, sizeof **out);
253 LY_CHECK_ERR_RET(!*out, LOGMEM(NULL), LY_EMEM);
Radek Krejcia5bba312020-01-09 15:41:20 +0100254
Radek Krejci84ce7b12020-06-11 17:28:25 +0200255 (*out)->type = LY_OUT_MEMORY;
256 (*out)->method.mem.buf = strp;
Radek Krejcia5bba312020-01-09 15:41:20 +0100257 if (!size) {
258 /* buffer is supposed to be allocated */
259 *strp = NULL;
260 } else if (*strp) {
261 /* there is already buffer to use */
Radek Krejci84ce7b12020-06-11 17:28:25 +0200262 (*out)->method.mem.size = size;
Radek Krejcia5bba312020-01-09 15:41:20 +0100263 }
264
Radek Krejci84ce7b12020-06-11 17:28:25 +0200265 return LY_SUCCESS;
Radek Krejcia5bba312020-01-09 15:41:20 +0100266}
267
268char *
Radek Krejci241f6b52020-05-21 18:13:49 +0200269ly_out_memory(struct ly_out *out, char **strp, size_t size)
Radek Krejcia5bba312020-01-09 15:41:20 +0100270{
271 char *data;
272
Radek Krejci241f6b52020-05-21 18:13:49 +0200273 LY_CHECK_ARG_RET(NULL, out, out->type == LY_OUT_MEMORY, NULL);
Radek Krejcia5bba312020-01-09 15:41:20 +0100274
275 data = *out->method.mem.buf;
276
277 if (strp) {
278 out->method.mem.buf = strp;
279 out->method.mem.len = out->method.mem.size = 0;
280 out->printed = 0;
281 if (!size) {
282 /* buffer is supposed to be allocated */
283 *strp = NULL;
284 } else if (*strp) {
285 /* there is already buffer to use */
286 out->method.mem.size = size;
287 }
288 }
289
290 return data;
291}
292
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100293LIBYANG_API_DEF LY_ERR
Radek Krejci241f6b52020-05-21 18:13:49 +0200294ly_out_reset(struct ly_out *out)
Radek Krejcia5bba312020-01-09 15:41:20 +0100295{
296 LY_CHECK_ARG_RET(NULL, out, LY_EINVAL);
297
Michal Vaskod989ba02020-08-24 10:59:24 +0200298 switch (out->type) {
Radek Krejci241f6b52020-05-21 18:13:49 +0200299 case LY_OUT_ERROR:
Radek Krejcia5bba312020-01-09 15:41:20 +0100300 LOGINT(NULL);
301 return LY_EINT;
Radek Krejci241f6b52020-05-21 18:13:49 +0200302 case LY_OUT_FD:
Michal Vasko69730152020-10-09 16:30:07 +0200303 if ((lseek(out->method.fd, 0, SEEK_SET) == -1) && (errno != ESPIPE)) {
Radek Krejcia5bba312020-01-09 15:41:20 +0100304 LOGERR(NULL, LY_ESYS, "Seeking output file descriptor failed (%s).", strerror(errno));
305 return LY_ESYS;
306 }
Michal Vasko69730152020-10-09 16:30:07 +0200307 if ((errno != ESPIPE) && (ftruncate(out->method.fd, 0) == -1)) {
Radek Krejcic5a12e12020-05-27 17:09:59 +0200308 LOGERR(NULL, LY_ESYS, "Truncating output file failed (%s).", strerror(errno));
309 return LY_ESYS;
310 }
Radek Krejcia5bba312020-01-09 15:41:20 +0100311 break;
Radek Krejci241f6b52020-05-21 18:13:49 +0200312 case LY_OUT_FDSTREAM:
313 case LY_OUT_FILE:
314 case LY_OUT_FILEPATH:
Michal Vasko69730152020-10-09 16:30:07 +0200315 if ((fseek(out->method.f, 0, SEEK_SET) == -1) && (errno != ESPIPE)) {
Radek Krejcia5bba312020-01-09 15:41:20 +0100316 LOGERR(NULL, LY_ESYS, "Seeking output file stream failed (%s).", strerror(errno));
317 return LY_ESYS;
318 }
Michal Vasko69730152020-10-09 16:30:07 +0200319 if ((errno != ESPIPE) && (ftruncate(fileno(out->method.f), 0) == -1)) {
Radek Krejcic5a12e12020-05-27 17:09:59 +0200320 LOGERR(NULL, LY_ESYS, "Truncating output file failed (%s).", strerror(errno));
321 return LY_ESYS;
322 }
Radek Krejcia5bba312020-01-09 15:41:20 +0100323 break;
Radek Krejci241f6b52020-05-21 18:13:49 +0200324 case LY_OUT_MEMORY:
Radek Krejcic5a12e12020-05-27 17:09:59 +0200325 if (out->method.mem.buf && *out->method.mem.buf) {
326 memset(*out->method.mem.buf, 0, out->method.mem.len);
327 }
Radek Krejcia5bba312020-01-09 15:41:20 +0100328 out->printed = 0;
329 out->method.mem.len = 0;
330 break;
Radek Krejci241f6b52020-05-21 18:13:49 +0200331 case LY_OUT_CALLBACK:
Radek Krejcia5bba312020-01-09 15:41:20 +0100332 /* nothing to do (not seekable) */
333 break;
334 }
335
336 return LY_SUCCESS;
337}
338
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100339LIBYANG_API_DEF LY_ERR
Radek Krejci84ce7b12020-06-11 17:28:25 +0200340ly_out_new_filepath(const char *filepath, struct ly_out **out)
Radek Krejcia5bba312020-01-09 15:41:20 +0100341{
Radek Krejci84ce7b12020-06-11 17:28:25 +0200342 LY_CHECK_ARG_RET(NULL, out, filepath, LY_EINVAL);
Radek Krejcia5bba312020-01-09 15:41:20 +0100343
Radek Krejci84ce7b12020-06-11 17:28:25 +0200344 *out = calloc(1, sizeof **out);
345 LY_CHECK_ERR_RET(!*out, LOGMEM(NULL), LY_EMEM);
Radek Krejcia5bba312020-01-09 15:41:20 +0100346
Radek Krejci84ce7b12020-06-11 17:28:25 +0200347 (*out)->type = LY_OUT_FILEPATH;
Jan Kundrátb1aa77f2021-12-13 15:16:47 +0100348 (*out)->method.fpath.f = fopen(filepath, "wb");
Radek Krejci84ce7b12020-06-11 17:28:25 +0200349 if (!(*out)->method.fpath.f) {
Radek Krejcia5bba312020-01-09 15:41:20 +0100350 LOGERR(NULL, LY_ESYS, "Failed to open file \"%s\" (%s).", filepath, strerror(errno));
Radek Krejcif6923e82020-07-02 16:36:53 +0200351 free(*out);
352 *out = NULL;
Radek Krejci84ce7b12020-06-11 17:28:25 +0200353 return LY_ESYS;
Radek Krejcia5bba312020-01-09 15:41:20 +0100354 }
Radek Krejci84ce7b12020-06-11 17:28:25 +0200355 (*out)->method.fpath.filepath = strdup(filepath);
356 return LY_SUCCESS;
Radek Krejcia5bba312020-01-09 15:41:20 +0100357}
358
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100359LIBYANG_API_DEF const char *
Radek Krejci241f6b52020-05-21 18:13:49 +0200360ly_out_filepath(struct ly_out *out, const char *filepath)
Radek Krejcia5bba312020-01-09 15:41:20 +0100361{
362 FILE *f;
363
Radek Krejci241f6b52020-05-21 18:13:49 +0200364 LY_CHECK_ARG_RET(NULL, out, out->type == LY_OUT_FILEPATH, filepath ? NULL : ((void *)-1));
Radek Krejcia5bba312020-01-09 15:41:20 +0100365
366 if (!filepath) {
367 return out->method.fpath.filepath;
368 }
369
370 /* replace filepath */
371 f = out->method.fpath.f;
Jan Kundrátb1aa77f2021-12-13 15:16:47 +0100372 out->method.fpath.f = fopen(filepath, "wb");
Radek Krejcia5bba312020-01-09 15:41:20 +0100373 if (!out->method.fpath.f) {
374 LOGERR(NULL, LY_ESYS, "Failed to open file \"%s\" (%s).", filepath, strerror(errno));
375 out->method.fpath.f = f;
Michal Vasko69730152020-10-09 16:30:07 +0200376 return (void *)-1;
Radek Krejcia5bba312020-01-09 15:41:20 +0100377 }
378 fclose(f);
379 free(out->method.fpath.filepath);
380 out->method.fpath.filepath = strdup(filepath);
381
382 return NULL;
383}
384
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100385LIBYANG_API_DEF void
Radek Krejci857189e2020-09-01 13:26:36 +0200386ly_out_free(struct ly_out *out, void (*clb_arg_destructor)(void *arg), ly_bool destroy)
Radek Krejcia5bba312020-01-09 15:41:20 +0100387{
388 if (!out) {
389 return;
390 }
391
392 switch (out->type) {
Radek Krejci241f6b52020-05-21 18:13:49 +0200393 case LY_OUT_CALLBACK:
Radek Krejcia5bba312020-01-09 15:41:20 +0100394 if (clb_arg_destructor) {
395 clb_arg_destructor(out->method.clb.arg);
396 }
397 break;
Radek Krejci241f6b52020-05-21 18:13:49 +0200398 case LY_OUT_FDSTREAM:
Radek Krejcia5bba312020-01-09 15:41:20 +0100399 fclose(out->method.fdstream.f);
400 if (destroy) {
401 close(out->method.fdstream.fd);
402 }
403 break;
Radek Krejci241f6b52020-05-21 18:13:49 +0200404 case LY_OUT_FD:
Radek Krejcia5bba312020-01-09 15:41:20 +0100405 if (destroy) {
406 close(out->method.fd);
407 }
408 break;
Radek Krejci241f6b52020-05-21 18:13:49 +0200409 case LY_OUT_FILE:
Radek Krejcia5bba312020-01-09 15:41:20 +0100410 if (destroy) {
411 fclose(out->method.f);
412 }
413 break;
Radek Krejci241f6b52020-05-21 18:13:49 +0200414 case LY_OUT_MEMORY:
Radek Krejcia5bba312020-01-09 15:41:20 +0100415 if (destroy) {
416 free(*out->method.mem.buf);
417 }
418 break;
Radek Krejci241f6b52020-05-21 18:13:49 +0200419 case LY_OUT_FILEPATH:
Radek Krejcia5bba312020-01-09 15:41:20 +0100420 free(out->method.fpath.filepath);
Radek Krejci2aae3752020-05-27 18:16:30 +0200421 fclose(out->method.fpath.f);
Radek Krejcia5bba312020-01-09 15:41:20 +0100422 break;
Radek Krejci241f6b52020-05-21 18:13:49 +0200423 case LY_OUT_ERROR:
Radek Krejcia5bba312020-01-09 15:41:20 +0100424 LOGINT(NULL);
425 }
Michal Vasko159b8872020-11-18 18:14:16 +0100426
427 free(out->buffered);
Radek Krejcia5bba312020-01-09 15:41:20 +0100428 free(out);
429}
430
Michal Vasko5233e962020-08-14 14:26:20 +0200431static LY_ERR
432ly_vprint_(struct ly_out *out, const char *format, va_list ap)
Radek Krejcid3ca0632019-04-16 16:54:54 +0200433{
Michal Vasko5233e962020-08-14 14:26:20 +0200434 LY_ERR ret;
435 int written = 0;
Barbaros Tokaogluffc05ea2023-08-12 15:19:11 +0300436 char *msg = NULL;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200437
438 switch (out->type) {
Radek Krejci241f6b52020-05-21 18:13:49 +0200439 case LY_OUT_FD:
Michal Vasko5233e962020-08-14 14:26:20 +0200440 written = vdprintf(out->method.fd, format, ap);
Radek Krejcid3ca0632019-04-16 16:54:54 +0200441 break;
Radek Krejci241f6b52020-05-21 18:13:49 +0200442 case LY_OUT_FDSTREAM:
443 case LY_OUT_FILEPATH:
444 case LY_OUT_FILE:
Michal Vasko5233e962020-08-14 14:26:20 +0200445 written = vfprintf(out->method.f, format, ap);
Radek Krejcid3ca0632019-04-16 16:54:54 +0200446 break;
Radek Krejci241f6b52020-05-21 18:13:49 +0200447 case LY_OUT_MEMORY:
Michal Vasko5233e962020-08-14 14:26:20 +0200448 if ((written = vasprintf(&msg, format, ap)) < 0) {
Radek Krejci897ad2e2019-04-29 16:43:07 +0200449 break;
450 }
Michal Vasko5233e962020-08-14 14:26:20 +0200451 if (out->method.mem.len + written + 1 > out->method.mem.size) {
Barbaros Tokaogluffc05ea2023-08-12 15:19:11 +0300452 *out->method.mem.buf = ly_realloc(*out->method.mem.buf, out->method.mem.len + written + 1);
453 if (!*out->method.mem.buf) {
Radek Krejcid3ca0632019-04-16 16:54:54 +0200454 out->method.mem.len = 0;
455 out->method.mem.size = 0;
optimden3fb41f32024-02-14 15:45:46 +0545456 free(msg);
Radek Krejcid3ca0632019-04-16 16:54:54 +0200457 LOGMEM(NULL);
Michal Vasko5233e962020-08-14 14:26:20 +0200458 return LY_EMEM;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200459 }
Michal Vasko5233e962020-08-14 14:26:20 +0200460 out->method.mem.size = out->method.mem.len + written + 1;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200461 }
Michal Vasko08e9b112021-06-11 15:41:17 +0200462 if (written) {
463 memcpy(&(*out->method.mem.buf)[out->method.mem.len], msg, written);
464 }
Michal Vasko5233e962020-08-14 14:26:20 +0200465 out->method.mem.len += written;
Radek Krejcia5bba312020-01-09 15:41:20 +0100466 (*out->method.mem.buf)[out->method.mem.len] = '\0';
Radek Krejcid3ca0632019-04-16 16:54:54 +0200467 free(msg);
468 break;
Radek Krejci241f6b52020-05-21 18:13:49 +0200469 case LY_OUT_CALLBACK:
Michal Vasko5233e962020-08-14 14:26:20 +0200470 if ((written = vasprintf(&msg, format, ap)) < 0) {
Radek Krejci897ad2e2019-04-29 16:43:07 +0200471 break;
472 }
Michal Vasko5233e962020-08-14 14:26:20 +0200473 written = out->method.clb.func(out->method.clb.arg, msg, written);
Radek Krejcid3ca0632019-04-16 16:54:54 +0200474 free(msg);
475 break;
Radek Krejci241f6b52020-05-21 18:13:49 +0200476 case LY_OUT_ERROR:
Radek Krejcia5bba312020-01-09 15:41:20 +0100477 LOGINT(NULL);
Michal Vasko5233e962020-08-14 14:26:20 +0200478 return LY_EINT;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200479 }
480
Michal Vasko5233e962020-08-14 14:26:20 +0200481 if (written < 0) {
482 LOGERR(NULL, LY_ESYS, "%s: writing data failed (%s).", __func__, strerror(errno));
483 written = 0;
484 ret = LY_ESYS;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200485 } else {
Radek Krejci241f6b52020-05-21 18:13:49 +0200486 if (out->type == LY_OUT_FDSTREAM) {
Radek Krejcia5bba312020-01-09 15:41:20 +0100487 /* move the original file descriptor to the end of the output file */
488 lseek(out->method.fdstream.fd, 0, SEEK_END);
489 }
Michal Vasko5233e962020-08-14 14:26:20 +0200490 ret = LY_SUCCESS;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200491 }
Michal Vasko5233e962020-08-14 14:26:20 +0200492
493 out->printed += written;
494 out->func_printed += written;
495 return ret;
496}
497
498LY_ERR
499ly_print_(struct ly_out *out, const char *format, ...)
500{
501 LY_ERR ret;
502 va_list ap;
503
504 va_start(ap, format);
505 ret = ly_vprint_(out, format, ap);
506 va_end(ap);
507
508 return ret;
509}
510
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100511LIBYANG_API_DEF LY_ERR
Michal Vasko5233e962020-08-14 14:26:20 +0200512ly_print(struct ly_out *out, const char *format, ...)
513{
514 LY_ERR ret;
515 va_list ap;
516
517 out->func_printed = 0;
518
519 va_start(ap, format);
520 ret = ly_vprint_(out, format, ap);
521 va_end(ap);
522
523 return ret;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200524}
525
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100526LIBYANG_API_DEF void
Radek Krejci241f6b52020-05-21 18:13:49 +0200527ly_print_flush(struct ly_out *out)
Radek Krejcid3ca0632019-04-16 16:54:54 +0200528{
529 switch (out->type) {
Radek Krejci241f6b52020-05-21 18:13:49 +0200530 case LY_OUT_FDSTREAM:
Radek Krejcia5bba312020-01-09 15:41:20 +0100531 /* move the original file descriptor to the end of the output file */
532 lseek(out->method.fdstream.fd, 0, SEEK_END);
533 fflush(out->method.fdstream.f);
534 break;
Radek Krejci241f6b52020-05-21 18:13:49 +0200535 case LY_OUT_FILEPATH:
536 case LY_OUT_FILE:
Radek Krejcid3ca0632019-04-16 16:54:54 +0200537 fflush(out->method.f);
538 break;
Radek Krejci241f6b52020-05-21 18:13:49 +0200539 case LY_OUT_FD:
Radek Krejcie7b95092019-05-15 11:03:07 +0200540 fsync(out->method.fd);
541 break;
Radek Krejci241f6b52020-05-21 18:13:49 +0200542 case LY_OUT_MEMORY:
543 case LY_OUT_CALLBACK:
Radek Krejcid3ca0632019-04-16 16:54:54 +0200544 /* nothing to do */
545 break;
Radek Krejci241f6b52020-05-21 18:13:49 +0200546 case LY_OUT_ERROR:
Radek Krejcia5bba312020-01-09 15:41:20 +0100547 LOGINT(NULL);
Radek Krejcid3ca0632019-04-16 16:54:54 +0200548 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200549
550 free(out->buffered);
551 out->buf_size = out->buf_len = 0;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200552}
553
Michal Vasko5233e962020-08-14 14:26:20 +0200554LY_ERR
555ly_write_(struct ly_out *out, const char *buf, size_t len)
Radek Krejcid3ca0632019-04-16 16:54:54 +0200556{
Radek Krejci1deb5be2020-08-26 16:43:36 +0200557 LY_ERR ret = LY_SUCCESS;
aPiecek61d76952021-08-30 10:28:04 +0200558 size_t written = 0, new_mem_size;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200559
560 if (out->hole_count) {
561 /* we are buffering data after a hole */
Radek Krejcie7b95092019-05-15 11:03:07 +0200562 if (out->buf_len + len > out->buf_size) {
563 out->buffered = ly_realloc(out->buffered, out->buf_len + len);
Radek Krejcid3ca0632019-04-16 16:54:54 +0200564 if (!out->buffered) {
565 out->buf_len = 0;
566 out->buf_size = 0;
Radek Krejcibaeb8382020-05-27 16:44:53 +0200567 LOGMEM(NULL);
Michal Vasko5233e962020-08-14 14:26:20 +0200568 return LY_EMEM;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200569 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200570 out->buf_size = out->buf_len + len;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200571 }
572
Michal Vasko08e9b112021-06-11 15:41:17 +0200573 if (len) {
574 memcpy(&out->buffered[out->buf_len], buf, len);
575 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200576 out->buf_len += len;
Michal Vasko5233e962020-08-14 14:26:20 +0200577
578 out->printed += len;
579 out->func_printed += len;
580 return LY_SUCCESS;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200581 }
582
Radek Krejci897ad2e2019-04-29 16:43:07 +0200583repeat:
Radek Krejcid3ca0632019-04-16 16:54:54 +0200584 switch (out->type) {
Radek Krejci241f6b52020-05-21 18:13:49 +0200585 case LY_OUT_MEMORY:
aPiecek61d76952021-08-30 10:28:04 +0200586 new_mem_size = out->method.mem.len + len + 1;
587 if (new_mem_size > out->method.mem.size) {
588 new_mem_size = REALLOC_CHUNK(new_mem_size);
589 *out->method.mem.buf = ly_realloc(*out->method.mem.buf, new_mem_size);
Radek Krejcia5bba312020-01-09 15:41:20 +0100590 if (!*out->method.mem.buf) {
Radek Krejcid3ca0632019-04-16 16:54:54 +0200591 out->method.mem.len = 0;
592 out->method.mem.size = 0;
Radek Krejcibaeb8382020-05-27 16:44:53 +0200593 LOGMEM(NULL);
Michal Vasko5233e962020-08-14 14:26:20 +0200594 return LY_EMEM;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200595 }
aPiecek61d76952021-08-30 10:28:04 +0200596 out->method.mem.size = new_mem_size;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200597 }
Michal Vasko08e9b112021-06-11 15:41:17 +0200598 if (len) {
599 memcpy(&(*out->method.mem.buf)[out->method.mem.len], buf, len);
600 }
Radek Krejcie7b95092019-05-15 11:03:07 +0200601 out->method.mem.len += len;
Radek Krejcia5bba312020-01-09 15:41:20 +0100602 (*out->method.mem.buf)[out->method.mem.len] = '\0';
Radek Krejci897ad2e2019-04-29 16:43:07 +0200603
Michal Vasko5233e962020-08-14 14:26:20 +0200604 written = len;
605 break;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200606 case LY_OUT_FD: {
607 ssize_t r;
Michal Vasko26bbb272022-08-02 14:54:33 +0200608
Radek Krejci1deb5be2020-08-26 16:43:36 +0200609 r = write(out->method.fd, buf, len);
610 if (r < 0) {
611 ret = LY_ESYS;
612 } else {
613 written = (size_t)r;
614 }
Radek Krejcid3ca0632019-04-16 16:54:54 +0200615 break;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200616 }
Radek Krejci241f6b52020-05-21 18:13:49 +0200617 case LY_OUT_FDSTREAM:
618 case LY_OUT_FILEPATH:
619 case LY_OUT_FILE:
Michal Vasko63f3d842020-07-08 10:10:14 +0200620 written = fwrite(buf, sizeof *buf, len, out->method.f);
Radek Krejci1deb5be2020-08-26 16:43:36 +0200621 if (written != len) {
622 ret = LY_ESYS;
623 }
Radek Krejcid3ca0632019-04-16 16:54:54 +0200624 break;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200625 case LY_OUT_CALLBACK: {
626 ssize_t r;
Michal Vasko26bbb272022-08-02 14:54:33 +0200627
Radek Krejci1deb5be2020-08-26 16:43:36 +0200628 r = out->method.clb.func(out->method.clb.arg, buf, len);
629 if (r < 0) {
630 ret = LY_ESYS;
631 } else {
632 written = (size_t)r;
633 }
Radek Krejcid3ca0632019-04-16 16:54:54 +0200634 break;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200635 }
Radek Krejci241f6b52020-05-21 18:13:49 +0200636 case LY_OUT_ERROR:
Radek Krejcia5bba312020-01-09 15:41:20 +0100637 LOGINT(NULL);
Michal Vasko5233e962020-08-14 14:26:20 +0200638 return LY_EINT;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200639 }
640
Radek Krejci1deb5be2020-08-26 16:43:36 +0200641 if (ret) {
Michal Vasko69730152020-10-09 16:30:07 +0200642 if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
Radek Krejci1deb5be2020-08-26 16:43:36 +0200643 ret = LY_SUCCESS;
Radek Krejci897ad2e2019-04-29 16:43:07 +0200644 goto repeat;
645 }
Michal Vasko5233e962020-08-14 14:26:20 +0200646 LOGERR(NULL, LY_ESYS, "%s: writing data failed (%s).", __func__, strerror(errno));
647 written = 0;
Michal Vasko7b3a00e2023-08-09 11:58:03 +0200648 } else if (written != len) {
649 LOGERR(NULL, LY_ESYS, "%s: writing data failed (unable to write %" PRIu32 " from %" PRIu32 " data).", __func__,
650 (uint32_t)(len - written), (uint32_t)len);
Michal Vasko5233e962020-08-14 14:26:20 +0200651 ret = LY_ESYS;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200652 } else {
Radek Krejci241f6b52020-05-21 18:13:49 +0200653 if (out->type == LY_OUT_FDSTREAM) {
Radek Krejcia5bba312020-01-09 15:41:20 +0100654 /* move the original file descriptor to the end of the output file */
655 lseek(out->method.fdstream.fd, 0, SEEK_END);
656 }
Michal Vasko5233e962020-08-14 14:26:20 +0200657 ret = LY_SUCCESS;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200658 }
Michal Vasko5233e962020-08-14 14:26:20 +0200659
660 out->printed += written;
661 out->func_printed += written;
662 return ret;
663}
664
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100665LIBYANG_API_DEF LY_ERR
Michal Vasko5233e962020-08-14 14:26:20 +0200666ly_write(struct ly_out *out, const char *buf, size_t len)
667{
668 out->func_printed = 0;
669
670 return ly_write_(out, buf, len);
Radek Krejcid3ca0632019-04-16 16:54:54 +0200671}
672
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100673LIBYANG_API_DEF size_t
Michal Vasko63f3d842020-07-08 10:10:14 +0200674ly_out_printed(const struct ly_out *out)
675{
676 return out->func_printed;
677}
678
Michal Vasko5233e962020-08-14 14:26:20 +0200679LY_ERR
Radek Krejci241f6b52020-05-21 18:13:49 +0200680ly_write_skip(struct ly_out *out, size_t count, size_t *position)
Radek Krejcid3ca0632019-04-16 16:54:54 +0200681{
682 switch (out->type) {
Radek Krejci241f6b52020-05-21 18:13:49 +0200683 case LY_OUT_MEMORY:
Radek Krejcid3ca0632019-04-16 16:54:54 +0200684 if (out->method.mem.len + count > out->method.mem.size) {
Radek Krejcia5bba312020-01-09 15:41:20 +0100685 *out->method.mem.buf = ly_realloc(*out->method.mem.buf, out->method.mem.len + count);
686 if (!(*out->method.mem.buf)) {
Radek Krejcid3ca0632019-04-16 16:54:54 +0200687 out->method.mem.len = 0;
688 out->method.mem.size = 0;
Michal Vasko5233e962020-08-14 14:26:20 +0200689 LOGMEM(NULL);
690 return LY_EMEM;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200691 }
692 out->method.mem.size = out->method.mem.len + count;
693 }
694
695 /* save the current position */
696 *position = out->method.mem.len;
697
698 /* skip the memory */
699 out->method.mem.len += count;
700 break;
Radek Krejci241f6b52020-05-21 18:13:49 +0200701 case LY_OUT_FD:
702 case LY_OUT_FDSTREAM:
703 case LY_OUT_FILEPATH:
704 case LY_OUT_FILE:
705 case LY_OUT_CALLBACK:
Radek Krejcid3ca0632019-04-16 16:54:54 +0200706 /* buffer the hole */
707 if (out->buf_len + count > out->buf_size) {
708 out->buffered = ly_realloc(out->buffered, out->buf_len + count);
709 if (!out->buffered) {
710 out->buf_len = 0;
711 out->buf_size = 0;
Radek Krejcibaeb8382020-05-27 16:44:53 +0200712 LOGMEM(NULL);
Michal Vasko5233e962020-08-14 14:26:20 +0200713 return LY_EMEM;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200714 }
715 out->buf_size = out->buf_len + count;
716 }
717
718 /* save the current position */
719 *position = out->buf_len;
720
721 /* skip the memory */
722 out->buf_len += count;
723
724 /* increase hole counter */
725 ++out->hole_count;
Radek Krejcia5bba312020-01-09 15:41:20 +0100726 break;
Radek Krejci241f6b52020-05-21 18:13:49 +0200727 case LY_OUT_ERROR:
Radek Krejcia5bba312020-01-09 15:41:20 +0100728 LOGINT(NULL);
Michal Vasko5233e962020-08-14 14:26:20 +0200729 return LY_EINT;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200730 }
731
Michal Vasko5233e962020-08-14 14:26:20 +0200732 /* update printed bytes counter despite we actually printed just a hole */
733 out->printed += count;
734 out->func_printed += count;
735 return LY_SUCCESS;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200736}
737
Michal Vasko66d99972020-06-29 13:37:42 +0200738LY_ERR
Radek Krejci241f6b52020-05-21 18:13:49 +0200739ly_write_skipped(struct ly_out *out, size_t position, const char *buf, size_t count)
Radek Krejcid3ca0632019-04-16 16:54:54 +0200740{
Michal Vasko66d99972020-06-29 13:37:42 +0200741 LY_ERR ret = LY_SUCCESS;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200742
Michal Vasko08e9b112021-06-11 15:41:17 +0200743 assert(count);
744
Radek Krejcid3ca0632019-04-16 16:54:54 +0200745 switch (out->type) {
Radek Krejci241f6b52020-05-21 18:13:49 +0200746 case LY_OUT_MEMORY:
Radek Krejcid3ca0632019-04-16 16:54:54 +0200747 /* write */
Radek Krejcia5bba312020-01-09 15:41:20 +0100748 memcpy(&(*out->method.mem.buf)[position], buf, count);
Radek Krejcid3ca0632019-04-16 16:54:54 +0200749 break;
Radek Krejci241f6b52020-05-21 18:13:49 +0200750 case LY_OUT_FD:
751 case LY_OUT_FDSTREAM:
752 case LY_OUT_FILEPATH:
753 case LY_OUT_FILE:
754 case LY_OUT_CALLBACK:
Radek Krejcid3ca0632019-04-16 16:54:54 +0200755 if (out->buf_len < position + count) {
Michal Vasko5233e962020-08-14 14:26:20 +0200756 LOGMEM(NULL);
757 return LY_EMEM;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200758 }
759
760 /* write into the hole */
761 memcpy(&out->buffered[position], buf, count);
762
763 /* decrease hole counter */
764 --out->hole_count;
765
766 if (!out->hole_count) {
Radek Krejci897ad2e2019-04-29 16:43:07 +0200767 /* all holes filled, we can write the buffer,
Michal Vasko5233e962020-08-14 14:26:20 +0200768 * printed bytes counter is updated by ly_write_() */
769 ret = ly_write_(out, out->buffered, out->buf_len);
Radek Krejcid3ca0632019-04-16 16:54:54 +0200770 out->buf_len = 0;
771 }
772 break;
Radek Krejci241f6b52020-05-21 18:13:49 +0200773 case LY_OUT_ERROR:
Michal Vasko5233e962020-08-14 14:26:20 +0200774 LOGINT(NULL);
775 return LY_EINT;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200776 }
777
Radek Krejci241f6b52020-05-21 18:13:49 +0200778 if (out->type == LY_OUT_FILEPATH) {
Radek Krejcia5bba312020-01-09 15:41:20 +0100779 /* move the original file descriptor to the end of the output file */
780 lseek(out->method.fdstream.fd, 0, SEEK_END);
781 }
Michal Vasko66d99972020-06-29 13:37:42 +0200782 return ret;
Radek Krejcid3ca0632019-04-16 16:54:54 +0200783}