/src/rtpproxy/modules/acct_csv/rtpp_acct_csv.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2006-2016 Sippy Software, Inc., http://www.sippysoft.com |
3 | | * All rights reserved. |
4 | | * |
5 | | * Redistribution and use in source and binary forms, with or without |
6 | | * modification, are permitted provided that the following conditions |
7 | | * are met: |
8 | | * 1. Redistributions of source code must retain the above copyright |
9 | | * notice, this list of conditions and the following disclaimer. |
10 | | * 2. Redistributions in binary form must reproduce the above copyright |
11 | | * notice, this list of conditions and the following disclaimer in the |
12 | | * documentation and/or other materials provided with the distribution. |
13 | | * |
14 | | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
15 | | * 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 AUTHOR OR CONTRIBUTORS BE LIABLE |
18 | | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
19 | | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
20 | | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
21 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
22 | | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
23 | | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
24 | | * SUCH DAMAGE. |
25 | | * |
26 | | */ |
27 | | |
28 | | #include <sys/param.h> |
29 | | #include <sys/stat.h> |
30 | | #include <sys/types.h> |
31 | | #include <errno.h> |
32 | | #include <inttypes.h> |
33 | | #include <fcntl.h> |
34 | | #include <limits.h> |
35 | | #include <stdint.h> |
36 | | #include <stdio.h> |
37 | | #include <stdlib.h> |
38 | | #include <string.h> |
39 | | #include <unistd.h> |
40 | | |
41 | | #include "config_pp.h" |
42 | | |
43 | | #include "rtpp_ssrc.h" |
44 | | #include "rtpa_stats.h" |
45 | | #include "rtpp_types.h" |
46 | | #include "rtpp_analyzer.h" |
47 | | #include "rtpp_pcount.h" |
48 | | #include "rtpp_time.h" |
49 | | #include "rtpp_pcnt_strm.h" |
50 | | #include "rtpp_pcnts_strm.h" |
51 | | #include "rtpp_acct_pipe.h" |
52 | | #include "rtpp_acct.h" |
53 | | #include "rtpp_module.h" |
54 | | #include "rtpp_module_acct.h" |
55 | | #include "rtpp_netaddr.h" |
56 | | #include "rtpp_network.h" |
57 | | #include "rtpp_util.h" |
58 | | #include "rtpp_cfg.h" |
59 | | #include "rtpp_log.h" |
60 | | #include "rtpp_log_obj.h" |
61 | | #include "rtpp_linker_set.h" |
62 | | #include "rtpp_str.h" |
63 | | #include "rtpp_sbuf.h" |
64 | | |
65 | | #define SSRC_STRLEN 11 |
66 | | |
67 | | struct rtpp_mod_acct_face { |
68 | | char rtp_adr[MAX_AP_STRBUF]; |
69 | | char rtcp_adr[MAX_AP_STRBUF]; |
70 | | char ssrc[SSRC_STRLEN]; |
71 | | }; |
72 | | |
73 | | struct rtpp_module_priv { |
74 | | int fd; |
75 | | pid_t pid; |
76 | | struct stat stt; |
77 | | char fname[MAXPATHLEN + 1]; |
78 | | double next_hupd_ts; |
79 | | char node_id[_POSIX_HOST_NAME_MAX + 1]; |
80 | | struct rtpp_mod_acct_face o; |
81 | | struct rtpp_mod_acct_face a; |
82 | | struct rtpp_sbuf *sbuf; |
83 | | struct rtpp_minfo *mself; |
84 | | }; |
85 | | |
86 | | /* Bump this when some changes are made */ |
87 | 59.7k | #define RTPP_METRICS_VERSION "1.2" |
88 | | |
89 | 9 | #define HNAME_REFRESH_IVAL 1.0 |
90 | | |
91 | | static struct rtpp_module_priv *rtpp_acct_csv_ctor(const struct rtpp_cfg *, |
92 | | struct rtpp_minfo *); |
93 | | static void rtpp_acct_csv_dtor(struct rtpp_module_priv *); |
94 | | static void rtpp_acct_csv_do(struct rtpp_module_priv *, struct rtpp_acct *); |
95 | | static off_t rtpp_acct_csv_lockf(int); |
96 | | static void rtpp_acct_csv_unlockf(int, off_t); |
97 | | |
98 | | #ifdef RTPP_CHECK_LEAKS |
99 | | #include "rtpp_memdeb_internal.h" |
100 | | |
101 | | RTPP_MEMDEB_APP_STATIC; |
102 | | #endif |
103 | | |
104 | | static const struct rtpp_acct_handlers acct_csv_aapi = { |
105 | | .on_session_end = AAPI_FUNC(rtpp_acct_csv_do, rtpp_acct_OSIZE()) |
106 | | }; |
107 | | |
108 | | const struct rtpp_minfo RTPP_MOD_SELF = { |
109 | | .descr.name = "acct_csv", |
110 | | .descr.ver = MI_VER_INIT(), |
111 | | .descr.module_id = 1, |
112 | | .proc.ctor = rtpp_acct_csv_ctor, |
113 | | .proc.dtor = rtpp_acct_csv_dtor, |
114 | | #ifdef RTPP_CHECK_LEAKS |
115 | | .memdeb_p = &MEMDEB_SYM, |
116 | | #endif |
117 | | .aapi = &acct_csv_aapi, |
118 | | .fn = &(struct rtpp_minfo_fset){0}, |
119 | | }; |
120 | | #if defined(LIBRTPPROXY) |
121 | | DATA_SET(rtpp_modules, RTPP_MOD_SELF); |
122 | | #endif |
123 | | |
124 | | static const char * |
125 | | rtpp_acct_get_nid(struct rtpp_module_priv *pvt, struct rtpp_acct *ap) |
126 | 59.7k | { |
127 | | |
128 | 59.7k | if (pvt->next_hupd_ts == 0.0 || pvt->next_hupd_ts < ap->destroy_ts->mono) { |
129 | 9 | if (gethostname(pvt->node_id, sizeof(pvt->node_id)) == 0) { |
130 | 9 | pvt->next_hupd_ts = ap->destroy_ts->mono + HNAME_REFRESH_IVAL; |
131 | 9 | } |
132 | 9 | } |
133 | 59.7k | return (pvt->node_id); |
134 | 59.7k | } |
135 | | |
136 | | #define SFX_INO "_ino" |
137 | | #define SFX_INA "_ina" |
138 | | |
139 | | #define SFX_O "_o" |
140 | | #define SFX_A "_a" |
141 | | |
142 | | #define PFX_GEN "rtpp_" |
143 | | |
144 | | |
145 | | #define RVER_NM "rec_ver" |
146 | | #define NID_NM PFX_GEN "node_id" |
147 | | #define PID_NM PFX_GEN "pid" |
148 | | #define SID_NM "sess_uid" |
149 | | #define CID_NM "call_id" |
150 | | #define PT_NAME "rtpa_pt_last" |
151 | | #define PT_NM_O PT_NAME SFX_INO |
152 | | #define PT_NM_A PT_NAME SFX_INA |
153 | | #define PFX_RTP "rtp_" |
154 | | #define PFX_RTCP "rtcp_" |
155 | | #define RM_IP_NM "rmt_ip" |
156 | | #define RM_PT_NM "rmt_pt" |
157 | | #define R_RM_NM_O PFX_GEN PFX_RTP RM_IP_NM SFX_O |
158 | | #define R_RM_NM_A PFX_GEN PFX_RTP RM_IP_NM SFX_A |
159 | | #define C_RM_NM_O PFX_GEN PFX_RTCP RM_IP_NM SFX_O |
160 | | #define C_RM_NM_A PFX_GEN PFX_RTCP RM_IP_NM SFX_A |
161 | | #define R_RM_PT_NM_O PFX_GEN PFX_RTP RM_PT_NM SFX_O |
162 | | #define R_RM_PT_NM_A PFX_GEN PFX_RTP RM_PT_NM SFX_A |
163 | | #define C_RM_PT_NM_O PFX_GEN PFX_RTCP RM_PT_NM SFX_O |
164 | | #define C_RM_PT_NM_A PFX_GEN PFX_RTCP RM_PT_NM SFX_A |
165 | | |
166 | | #define HLD_CNT_NM "hld_cnt" |
167 | | #define HLD_STS_NM "hld_sts" |
168 | | #define HLD_CNT_NM_O PFX_GEN HLD_CNT_NM SFX_O |
169 | | #define HLD_CNT_NM_A PFX_GEN HLD_CNT_NM SFX_A |
170 | | #define HLD_STS_NM_O PFX_GEN HLD_STS_NM SFX_O |
171 | | #define HLD_STS_NM_A PFX_GEN HLD_STS_NM SFX_A |
172 | | |
173 | 59.7k | #define RVER_FMT "%s" |
174 | | #define NID_FMT "%s" |
175 | | #define PID_FMT "%d" |
176 | | #define SID_FMT "%" PRId64 |
177 | | #define PT_FMT "%d" |
178 | | #define LSSRC_FMT "%s" |
179 | | #define SNCHG_FMT "%lu" |
180 | | #define RM_FMT "%s" |
181 | | #define SEP "," |
182 | | #define HLD_STS_FMT "%s" |
183 | | #define HLD_CNT_FMT "%d" |
184 | | |
185 | | #define STR_INIT(str) ((const struct rtpp_str_fixed){.s = (str), .len = sizeof(str) - 1}) |
186 | | |
187 | | static const struct rtpp_str_fixed head = STR_INIT(RVER_NM SEP NID_NM SEP PID_NM SEP SID_NM |
188 | | SEP CID_NM SEP |
189 | | "from_tag,setup_ts,teardown_ts,first_rtp_ts_ino,last_rtp_ts_ino," |
190 | | "first_rtp_ts_ina,last_rtp_ts_ina,rtp_npkts_ina,rtp_npkts_ino," |
191 | | "rtp_nrelayed,rtp_ndropped,rtcp_npkts_ina,rtcp_npkts_ino," |
192 | | "rtcp_nrelayed,rtcp_ndropped,rtpa_nsent_ino,rtpa_nrcvd_ino," |
193 | | "rtpa_ndups_ino,rtpa_nlost_ino,rtpa_perrs_ino," |
194 | | "rtpa_ssrc_last_ino,rtpa_ssrc_cnt_ino" SEP PT_NM_O SEP |
195 | | "rtpa_nsent_ina,rtpa_nrcvd_ina,rtpa_ndups_ina,rtpa_nlost_ina," |
196 | | "rtpa_perrs_ina,rtpa_ssrc_last_ina,rtpa_ssrc_cnt_ina" SEP PT_NM_A SEP |
197 | | "rtpa_jitter_last_ino,rtpa_jitter_max_ino,rtpa_jitter_avg_ino," |
198 | | "rtpa_jitter_last_ina,rtpa_jitter_max_ina,rtpa_jitter_avg_ina" SEP |
199 | | R_RM_NM_O SEP R_RM_PT_NM_O SEP R_RM_NM_A SEP R_RM_PT_NM_A SEP |
200 | | C_RM_NM_O SEP C_RM_PT_NM_O SEP C_RM_NM_A SEP C_RM_PT_NM_A SEP |
201 | | HLD_STS_NM_O SEP HLD_STS_NM_A SEP HLD_CNT_NM_O SEP HLD_CNT_NM_A "\n"); |
202 | | |
203 | | static int |
204 | | rtpp_acct_csv_open(struct rtpp_module_priv *pvt) |
205 | 4 | { |
206 | 4 | int pos; |
207 | 4 | int r = 0; |
208 | | |
209 | 4 | if (pvt->fd != -1) { |
210 | 0 | close(pvt->fd); |
211 | 0 | } |
212 | 4 | pvt->fd = open(pvt->fname, O_WRONLY | O_APPEND | O_CREAT, DEFFILEMODE); |
213 | 4 | if (pvt->fd == -1) { |
214 | 0 | RTPP_ELOG(pvt->mself->log, RTPP_LOG_ERR, "can't open '%s' for writing", |
215 | 0 | pvt->fname); |
216 | 0 | goto e0; |
217 | 0 | } |
218 | 4 | pos = rtpp_acct_csv_lockf(pvt->fd); |
219 | 4 | if (pos < 0) { |
220 | 0 | RTPP_ELOG(pvt->mself->log, RTPP_LOG_ERR, "can't lock '%s'", pvt->fname); |
221 | 0 | goto e1; |
222 | 0 | } |
223 | 4 | if (fstat(pvt->fd, &pvt->stt) < 0) { |
224 | 0 | RTPP_ELOG(pvt->mself->log, RTPP_LOG_ERR, "can't get stats for '%s'", |
225 | 0 | pvt->fname); |
226 | 0 | goto e2; |
227 | 0 | } |
228 | 4 | if (pvt->stt.st_size == 0) { |
229 | 1 | do { |
230 | 1 | r = write(pvt->fd, head.s, head.len); |
231 | 1 | } while (r < 0 && errno == EINTR); |
232 | 1 | if (r > 0 && r < head.len) |
233 | 0 | r = -1; |
234 | 1 | } |
235 | 4 | rtpp_acct_csv_unlockf(pvt->fd, pos); |
236 | 4 | return (r); |
237 | | |
238 | 0 | e2: |
239 | 0 | rtpp_acct_csv_unlockf(pvt->fd, pos); |
240 | 0 | e1: |
241 | 0 | close(pvt->fd); |
242 | 0 | e0: |
243 | 0 | return (-1); |
244 | 0 | } |
245 | | |
246 | | static struct rtpp_module_priv * |
247 | | rtpp_acct_csv_ctor(const struct rtpp_cfg *cfsp, struct rtpp_minfo *mself) |
248 | 4 | { |
249 | 4 | struct rtpp_module_priv *pvt; |
250 | | |
251 | 4 | pvt = mod_zmalloc(sizeof(struct rtpp_module_priv)); |
252 | 4 | if (pvt == NULL) { |
253 | 0 | goto e0; |
254 | 0 | } |
255 | 4 | pvt->sbuf = rtpp_sbuf_ctor(head.len * 2); |
256 | 4 | if (pvt->sbuf == NULL) { |
257 | 0 | goto e1; |
258 | 0 | } |
259 | 4 | pvt->pid = getpid(); |
260 | 4 | if (cfsp->cwd_orig == NULL) { |
261 | 4 | snprintf(pvt->fname, sizeof(pvt->fname), "%s", "rtpproxy_acct.csv"); |
262 | 4 | } else { |
263 | 0 | snprintf(pvt->fname, sizeof(pvt->fname), "%s/%s", cfsp->cwd_orig, |
264 | 0 | "rtpproxy_acct.csv"); |
265 | 0 | } |
266 | 4 | if (gethostname(pvt->node_id, sizeof(pvt->node_id)) != 0) { |
267 | 0 | strcpy(pvt->node_id, "UNKNOWN"); |
268 | 0 | } |
269 | 4 | pvt->fd = -1; |
270 | 4 | pvt->mself = mself; |
271 | 4 | if (rtpp_acct_csv_open(pvt) == -1) { |
272 | 0 | goto e2; |
273 | 0 | } |
274 | 4 | return (pvt); |
275 | | |
276 | 0 | e2: |
277 | 0 | rtpp_sbuf_dtor(pvt->sbuf); |
278 | 0 | e1: |
279 | 0 | mod_free(pvt); |
280 | 0 | e0: |
281 | 0 | return (NULL); |
282 | 0 | } |
283 | | |
284 | | static void |
285 | | rtpp_acct_csv_dtor(struct rtpp_module_priv *pvt) |
286 | 4 | { |
287 | | |
288 | 4 | close(pvt->fd); |
289 | 4 | rtpp_sbuf_dtor(pvt->sbuf); |
290 | 4 | mod_free(pvt); |
291 | 4 | return; |
292 | 4 | } |
293 | | |
294 | 119k | #define ES_IF_NULL(s) ((s) == NULL ? "" : s) |
295 | 358k | #define TS2RT(ts) ((ts).wall) |
296 | | |
297 | | static void |
298 | | format_ssrc(struct rtpp_ssrc *sp, char *sbuf, size_t sblen) |
299 | 119k | { |
300 | | |
301 | 119k | if (sp->inited) { |
302 | 4.57k | snprintf(sbuf, sblen, SSRC_FMT, sp->val); |
303 | 114k | } else { |
304 | 114k | sbuf[0] = '\0'; |
305 | 114k | } |
306 | 119k | } |
307 | | |
308 | | static void |
309 | | format_netaddr(struct rtpp_netaddr *nap_rtp, struct rtpp_netaddr *nap_rtcp, |
310 | | struct rtpp_mod_acct_face *afp) |
311 | 119k | { |
312 | | |
313 | 119k | if (CALL_SMETHOD(nap_rtp, isempty)) { |
314 | 79.8k | sprintf(afp->rtp_adr, ","); |
315 | 79.8k | } else { |
316 | 39.7k | CALL_SMETHOD(nap_rtp, sip_print, afp->rtp_adr, sizeof(afp->rtp_adr), |
317 | 39.7k | ','); |
318 | 39.7k | } |
319 | 119k | if (CALL_SMETHOD(nap_rtcp, isempty)) { |
320 | 79.8k | sprintf(afp->rtcp_adr, ","); |
321 | 79.8k | } else { |
322 | 39.7k | CALL_SMETHOD(nap_rtcp, sip_print, afp->rtcp_adr, sizeof(afp->rtcp_adr), |
323 | 39.7k | ','); |
324 | 39.7k | } |
325 | 119k | } |
326 | | |
327 | 119k | #define FMT_BOOL(x) ((x == 0) ? "f" : "t") |
328 | | |
329 | | static void |
330 | | rtpp_acct_csv_do(struct rtpp_module_priv *pvt, struct rtpp_acct *acct) |
331 | 59.7k | { |
332 | 59.7k | int pos, rval; |
333 | 59.7k | struct stat stt; |
334 | | |
335 | 59.7k | rval = stat(pvt->fname, &stt); |
336 | 59.7k | if (rval != -1) { |
337 | 59.7k | if (stt.st_dev != pvt->stt.st_dev || stt.st_ino != pvt->stt.st_ino) { |
338 | 0 | if (rtpp_acct_csv_open(pvt) < 0) |
339 | 0 | return; |
340 | 0 | } |
341 | 59.7k | } else if (rval == -1 && errno == ENOENT) { |
342 | 0 | if (rtpp_acct_csv_open(pvt) < 0) |
343 | 0 | return; |
344 | 0 | } |
345 | 59.7k | pos = rtpp_acct_csv_lockf(pvt->fd); |
346 | 59.7k | if (pos < 0) { |
347 | 0 | return; |
348 | 0 | } |
349 | | |
350 | 59.7k | format_ssrc(&acct->rasta->last_ssrc, pvt->a.ssrc, sizeof(pvt->a.ssrc)); |
351 | 59.7k | format_ssrc(&acct->rasto->last_ssrc, pvt->o.ssrc, sizeof(pvt->o.ssrc)); |
352 | 59.7k | format_netaddr(acct->rtp.a.rem_addr, acct->rtcp.a.rem_addr, &pvt->a); |
353 | 59.7k | format_netaddr(acct->rtp.o.rem_addr, acct->rtcp.o.rem_addr, &pvt->o); |
354 | 59.7k | do { |
355 | 59.7k | int res = rtpp_sbuf_write(pvt->sbuf, RVER_FMT SEP NID_FMT SEP PID_FMT SEP SID_FMT SEP |
356 | 59.7k | "%s,%s,%f,%f,%f,%f,%f,%f,%lu,%lu," |
357 | 59.7k | "%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu" SEP LSSRC_FMT SEP SNCHG_FMT SEP |
358 | 59.7k | PT_FMT SEP "%lu,%lu,%lu,%lu,%lu" SEP LSSRC_FMT SEP SNCHG_FMT SEP PT_FMT SEP |
359 | 59.7k | "%f,%f,%f,%f,%f,%f" SEP RM_FMT SEP RM_FMT SEP RM_FMT SEP RM_FMT SEP |
360 | 59.7k | HLD_STS_FMT SEP HLD_STS_FMT SEP HLD_CNT_FMT SEP HLD_CNT_FMT "\n", |
361 | 59.7k | RTPP_METRICS_VERSION, rtpp_acct_get_nid(pvt, acct), |
362 | 59.7k | pvt->pid, acct->seuid, ES_IF_NULL(acct->call_id), ES_IF_NULL(acct->from_tag), |
363 | 59.7k | TS2RT(*acct->init_ts), TS2RT(*acct->destroy_ts), TS2RT(acct->rtp.o.ps->first_pkt_rcv), |
364 | 59.7k | TS2RT(acct->rtp.o.ps->last_pkt_rcv), TS2RT(acct->rtp.a.ps->first_pkt_rcv), |
365 | 59.7k | TS2RT(acct->rtp.a.ps->last_pkt_rcv), acct->rtp.a.ps->npkts_in, acct->rtp.o.ps->npkts_in, |
366 | 59.7k | acct->rtp.pcnts->nrelayed, acct->rtp.pcnts->ndropped, acct->rtcp.a.ps->npkts_in, |
367 | 59.7k | acct->rtcp.o.ps->npkts_in, acct->rtcp.pcnts->nrelayed, acct->rtcp.pcnts->ndropped, |
368 | 59.7k | acct->rasto->psent, acct->rasto->precvd, acct->rasto->pdups, acct->rasto->plost, |
369 | 59.7k | acct->rasto->pecount, pvt->o.ssrc, acct->rasto->ssrc_changes, acct->rasto->last_pt, |
370 | 59.7k | acct->rasta->psent, acct->rasta->precvd, acct->rasta->pdups, acct->rasta->plost, |
371 | 59.7k | acct->rasta->pecount, pvt->a.ssrc, acct->rasta->ssrc_changes, acct->rasta->last_pt, |
372 | 59.7k | acct->jrasto->jlast, acct->jrasto->jmax, acct->jrasto->javg, |
373 | 59.7k | acct->jrasta->jlast, acct->jrasta->jmax, acct->jrasta->javg, |
374 | 59.7k | pvt->o.rtp_adr, pvt->a.rtp_adr, pvt->o.rtcp_adr, pvt->a.rtcp_adr, |
375 | 59.7k | FMT_BOOL(acct->rtp.o.hld_stat.status), FMT_BOOL(acct->rtp.a.hld_stat.status), |
376 | 59.7k | acct->rtp.o.hld_stat.cnt, acct->rtp.a.hld_stat.cnt); |
377 | 59.7k | if (res == SBW_OK) |
378 | 59.7k | break; |
379 | 2 | if (res == SBW_SHRT) { |
380 | 2 | if (rtpp_sbuf_extend(pvt->sbuf, pvt->sbuf->alen * 2) != 0) |
381 | 0 | goto out; |
382 | 2 | continue; |
383 | 2 | } |
384 | 0 | goto out; |
385 | 2 | } while (1); |
386 | 59.7k | write(pvt->fd, pvt->sbuf->bp, RS_ULEN(pvt->sbuf)); |
387 | 59.7k | rtpp_sbuf_reset(pvt->sbuf); |
388 | 59.7k | out: |
389 | 59.7k | rtpp_acct_csv_unlockf(pvt->fd, pos); |
390 | 59.7k | } |
391 | | |
392 | | static off_t |
393 | | rtpp_acct_csv_lockf(int fd) |
394 | 59.7k | { |
395 | 59.7k | struct flock l; |
396 | 59.7k | int rval; |
397 | | |
398 | 59.7k | memset(&l, '\0', sizeof(l)); |
399 | 59.7k | l.l_whence = SEEK_CUR; |
400 | 59.7k | l.l_type = F_WRLCK; |
401 | 59.7k | do { |
402 | 59.7k | rval = fcntl(fd, F_SETLKW, &l); |
403 | 59.7k | } while (rval == -1 && errno == EINTR); |
404 | 59.7k | if (rval == -1) { |
405 | 0 | return (-1); |
406 | 0 | } |
407 | 59.7k | return lseek(fd, 0, SEEK_CUR); |
408 | 59.7k | } |
409 | | |
410 | | static void |
411 | | rtpp_acct_csv_unlockf(int fd, off_t offset) |
412 | 59.7k | { |
413 | 59.7k | struct flock l; |
414 | 59.7k | int rval; |
415 | | |
416 | 59.7k | memset(&l, '\0', sizeof(l)); |
417 | 59.7k | l.l_whence = SEEK_SET; |
418 | 59.7k | l.l_start = offset; |
419 | 59.7k | l.l_type = F_UNLCK; |
420 | 59.7k | do { |
421 | 59.7k | rval = fcntl(fd, F_SETLKW, &l); |
422 | 59.7k | } while (rval == -1 && errno == EINTR); |
423 | 59.7k | } |