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