tizen 2.3 release
[framework/system/swap-probe.git] / probe_file / da_io.h
1 /*
2  *  DA probe
3  *
4  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  *
8  * Jaewon Lim <jaewon81.lim@samsung.com>
9  * Woojin Jung <woojin2.jung@samsung.com>
10  * Juyoung Kim <j0.kim@samsung.com>
11  * Anastasia Lyupa <a.lyupa@samsung.com>
12  *
13  * This library is free software; you can redistribute it and/or modify it under
14  * the terms of the GNU Lesser General Public License as published by the
15  * Free Software Foundation; either version 2.1 of the License, or (at your option)
16  * any later version.
17  *
18  * This library is distributed in the hope that it will be useful, but WITHOUT ANY
19  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
21  * License for more details.
22  *
23  * You should have received a copy of the GNU Lesser General Public License
24  * along with this library; if not, write to the Free Software Foundation, Inc., 51
25  * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26  *
27  * Contributors:
28  * - S-Core Co., Ltd
29  * - Samsung RnD Institute Russia
30  *
31  */
32
33 #ifndef __DA_IO_H__
34 #define __DA_IO_H__
35
36 #include <stdio.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <unistd.h>
40 #include <assert.h>
41
42 #include "daprobe.h"
43
44 /********************************************************************
45  * RESOURCE PROBE MACRO
46  *
47  * log format
48  *              SeqNumber`,ApiName`,Time`,Pid`,Tid`,InputParm`,Return`,PCAddr`,Error`,
49  *              Size`,FDValue`,FDType`,FDApiType`,                                      \n
50  *              callstack_start`,callstack`,callstack_end
51  *
52  * fd type
53  *              FD_TYPE_FILE, FD_TYPE_SOCKET
54  *
55  * fd api type
56  *              FD_API_TYPE_OPEN, FD_API_TYPE_CLOSE, FD_API_TYPE_READ, FD_API_TYPE_WRITE,
57  *              FD_API_TYPE_DIRECTORY, FD_API_TYPE_PERMISSION, FD_API_TYPE_OTHER,
58  *              FD_API_TYPE_SEND, FD_API_TYPE_RECEIVE, FD_API_TYPE_OPTION, FD_API_TYPE_MANAGE
59  *
60  ************************************************************************/
61
62 // ===================================================================
63 // macro for file probe
64 // ===================================================================
65
66 #define GET_FD_FROM_FILEP(FILEP)                                \
67         do {                                                    \
68                 _fd = (FILEP != NULL) ? fileno(FILEP) : -1;     \
69         } while (0);
70
71 #define DECLARE_VARIABLE_FD                                     \
72                 DECLARE_VARIABLE_STANDARD;                      \
73                 const char *_filepath = "";                     \
74                 int __attribute((unused)) _fd = -1;             \
75                 ssize_t __attribute((unused)) _filesize = 0;    \
76                 int __attribute((unused)) _fstatret = -1;       \
77                 struct stat __attribute((unused)) _statbuf
78
79 // =================================================================
80 // POST_PROBEBLOCK_MIDDLE for file
81 // =================================================================
82
83 #define POST_PACK_PROBEBLOCK_MIDDLE_FD(SIZE, FD, APITYPE)                               \
84         do {                                                                            \
85                 PACK_RESOURCE(SIZE, FD, APITYPE,                                        \
86                               (_fstatret == 0 ? _statbuf.st_size : 0), _filepath);      \
87                 FLUSH_LOCAL_BUF();                                                      \
88         } while (0)
89
90 #define POST_PACK_PROBEBLOCK_MIDDLE_NOFD(SIZE, APITYPE)         \
91         do {                                                    \
92                 PACK_RESOURCE(SIZE, 0, APITYPE, 0, _filepath);  \
93                 FLUSH_LOCAL_BUF();                              \
94         } while (0)
95
96 // ==================================================================
97 // BEFORE_ORIGINAL macro for file
98 // ==================================================================
99
100 #define BEFORE_ORIGINAL_FILE(FUNCNAME, LIBNAME)         \
101         DECLARE_VARIABLE_FD;                            \
102         GET_REAL_FUNC(FUNCNAME, LIBNAME);               \
103         PRE_PROBEBLOCK();
104
105 #define BEFORE_ORIGINAL_FILE_NOFILTER(FUNCNAME, LIBNAME)        \
106         DECLARE_VARIABLE_FD;                                    \
107         GET_REAL_FUNC(FUNCNAME, LIBNAME);                       \
108         bfiltering = false;                                     \
109         PRE_PROBEBLOCK()
110
111 // ==================================================================
112 // macro for filesize
113 // ==================================================================
114
115 #define DEFINE_FILESIZE_FD(fd) _fd = (fd); _filesize = get_fd_filesize(_fd);
116 #define DEFINE_FILESIZE_FP(fp) _fd = checked_fileno(fp); _filesize = get_fd_filesize(_fd);
117 #define DEFINE_FILESIZE_0() _fd = _filesize = 0;
118
119 /*!
120  * Macro AFTER_PACK_ORIGINAL_FD is used in and only in functions, which should report
121  * only about regular files or sockets, so this logic implemented in macro.
122  * Watch out when reusing it somewhere else
123  */
124 #define AFTER_PACK_ORIGINAL_FD(API_ID, RTYPE, RVAL, SIZE, FD, APITYPE, INPUTFORMAT, ...)        \
125 do {                                                                                            \
126         POST_PACK_PROBEBLOCK_BEGIN();                                                           \
127         _fstatret = fstat(FD, &_statbuf);                                                       \
128         if (stat_regular_or_socket_p(&_statbuf)) {                                              \
129                 PREPARE_LOCAL_BUF();                                                            \
130                 PACK_COMMON_BEGIN(MSG_PROBE_RESOURCE, API_ID, INPUTFORMAT, __VA_ARGS__);        \
131                 PACK_COMMON_END(RTYPE, RVAL, newerrno, blockresult);                            \
132                 POST_PACK_PROBEBLOCK_MIDDLE_FD(SIZE, FD, APITYPE);                              \
133         }                                                                                       \
134         POST_PACK_PROBEBLOCK_END();                                                             \
135 } while(0)
136
137 #define AFTER_PACK_ORIGINAL_FD_MIDDLE(API_ID, RTYPE, RVAL, SIZE, FD, APITYPE, INPUTFORMAT, ...) \
138 do {                                                                                            \
139         POST_PACK_PROBEBLOCK_BEGIN();                                                           \
140         _fstatret = fstat(FD, &_statbuf);                                                       \
141         if (stat_regular_or_socket_p(&_statbuf)) {                                              \
142                 PREPARE_LOCAL_BUF();                                                            \
143                 PACK_COMMON_BEGIN(MSG_PROBE_RESOURCE, API_ID, INPUTFORMAT, __VA_ARGS__);        \
144                 PACK_COMMON_END(RTYPE, RVAL, newerrno, blockresult);                            \
145                 POST_PACK_PROBEBLOCK_MIDDLE_FD(SIZE, FD, APITYPE);                              \
146         }                                                                                       \
147         POST_PACK_PROBEBLOCK_ADD_END();                                                         \
148 } while(0)
149
150 #define AFTER_PACK_ORIGINAL_NOFD(API_ID, RTYPE, RVAL, SIZE, APITYPE, INPUTFORMAT, ...)  \
151 do {                                                                                    \
152         POST_PACK_PROBEBLOCK_BEGIN();                                                   \
153         PREPARE_LOCAL_BUF();                                                            \
154         PACK_COMMON_BEGIN(MSG_PROBE_RESOURCE, API_ID, INPUTFORMAT, __VA_ARGS__);        \
155         PACK_COMMON_END(RTYPE, RVAL, newerrno, blockresult);                            \
156         POST_PACK_PROBEBLOCK_MIDDLE_NOFD(SIZE, APITYPE);                                \
157         POST_PACK_PROBEBLOCK_END();                                                     \
158 } while(0)
159
160 #define AFTER_PACK_ORIGINAL_FILEP(API_ID, RTYPE, RVAL, SIZE, FILEP, APITYPE, INPUTFORMAT, ...) \
161 do {                                                                                    \
162         POST_PACK_PROBEBLOCK_BEGIN();                                                   \
163         GET_FD_FROM_FILEP(FILEP);                                                       \
164         if(_fd != -1) {                                                                 \
165                 _fstatret = fstat(_fd, &_statbuf);                                      \
166         }                                                                               \
167         PREPARE_LOCAL_BUF();                                                            \
168         PACK_COMMON_BEGIN(MSG_PROBE_RESOURCE, API_ID, INPUTFORMAT, __VA_ARGS__);        \
169         PACK_COMMON_END(RTYPE, RVAL, newerrno, blockresult);                            \
170         POST_PACK_PROBEBLOCK_MIDDLE_FD(SIZE, _fd, APITYPE);                             \
171         POST_PACK_PROBEBLOCK_END();                                                     \
172 } while(0)
173
174 /*!
175  * Macros {BEFORE,AFTER}_ORIGINAL_START_END_FD only used in {p,v,}{read,write}
176  * in which we should log only about files and sockets. Given this lucky
177  * coincidence we can implement this login in macros. As such, they should not
178  * be used in functions for which this logic do not apply.
179  */
180 static inline bool stat_regular_or_socket_p(struct stat *buf)
181 {
182   return S_ISREG(buf->st_mode) || S_ISSOCK(buf->st_mode);
183 }
184 #define BEFORE_ORIGINAL_START_END_FD(API_ID, RTYPE, FUNCNAME, LIBNAME, FD, APITYPE, INPUTFORMAT, ...)   \
185         DECLARE_VARIABLE_FD;                                                                    \
186         GET_REAL_FUNC(FUNCNAME, LIBNAME);                                                       \
187         PRE_PROBEBLOCK_BEGIN();                                                                 \
188         _fstatret = fstat(FD, &_statbuf);                                                       \
189         if (stat_regular_or_socket_p(&_statbuf)) {                                              \
190                 DEFINE_FILESIZE_FD(fd);                                                         \
191                 PREPARE_LOCAL_BUF();                                                            \
192                 PACK_COMMON_BEGIN(MSG_PROBE_RESOURCE, API_ID, INPUTFORMAT, __VA_ARGS__);        \
193                 PACK_COMMON_END(RTYPE, 0, 0, blockresult);                                      \
194                 PACK_RESOURCE(0, FD, APITYPE, _filesize, _filepath);                            \
195                 FLUSH_LOCAL_BUF();                                                              \
196         }                                                               \
197         PRE_PROBEBLOCK_END();                                                           \
198
199 #define AFTER_ORIGINAL_START_END_FD(API_ID, RTYPE, RVAL, SIZE, FD, APITYPE, INPUTFORMAT, ...)           \
200 do {                                                                    \
201         POST_PACK_PROBEBLOCK_BEGIN();                                   \
202         setProbePoint(&probeInfo);                                      \
203         _fstatret = fstat(FD, &_statbuf);                               \
204         if (stat_regular_or_socket_p(&_statbuf)) {                      \
205                 PREPARE_LOCAL_BUF();                                                            \
206                 PACK_COMMON_BEGIN(MSG_PROBE_RESOURCE, API_ID, INPUTFORMAT, __VA_ARGS__); \
207                 PACK_COMMON_END(RTYPE, RVAL, newerrno, blockresult);            \
208                 PACK_RESOURCE(SIZE, FD, APITYPE, _filesize, _filepath); \
209                 FLUSH_LOCAL_BUF();                                                              \
210         }                                                               \
211         POST_PACK_PROBEBLOCK_END();                                                             \
212 } while(0)
213
214
215
216 #define BEFORE_ORIGINAL_START_END_NOFD(API_ID, RTYPE, FUNCNAME, LIBNAME, APITYPE, INPUTFORMAT, ...)     \
217         DECLARE_VARIABLE_FD;                                                            \
218         GET_REAL_FUNC(FUNCNAME, LIBNAME);                                               \
219         PRE_PROBEBLOCK_BEGIN();                                                         \
220         DEFINE_FILESIZE_0();                                                            \
221         PREPARE_LOCAL_BUF();                                                            \
222         PACK_COMMON_BEGIN(MSG_PROBE_RESOURCE, API_ID, INPUTFORMAT, __VA_ARGS__);        \
223         PACK_COMMON_END(RTYPE, 0, 0, blockresult);                                      \
224         POST_PACK_PROBEBLOCK_MIDDLE_NOFD(0, APITYPE);                                   \
225         PRE_PROBEBLOCK_END()
226
227 #define BEFORE_ORIGINAL_START_END_FILEP(API_ID, RTYPE, FUNCNAME, LIBNAME, FILEP, APITYPE, INPUTFORMAT, ...)     \
228         DECLARE_VARIABLE_FD;                                                                    \
229         GET_REAL_FUNC(FUNCNAME, LIBNAME);                                                       \
230         PRE_PROBEBLOCK_BEGIN();                                                                 \
231         GET_FD_FROM_FILEP(FILEP);                                                               \
232         if(_fd != -1) {                                                                         \
233                 _fstatret = fstat(_fd, &_statbuf);                                              \
234         }                                                                                       \
235         PREPARE_LOCAL_BUF();                                                                    \
236         PACK_COMMON_BEGIN(MSG_PROBE_RESOURCE, API_ID, INPUTFORMAT, __VA_ARGS__);                \
237         PACK_COMMON_END(RTYPE, 0, 0, blockresult);                                              \
238         POST_PACK_PROBEBLOCK_MIDDLE_FD(0, _fd, APITYPE);                                        \
239         PRE_PROBEBLOCK_END()
240
241 #define AFTER_ORIGINAL_START_END_NOFD(API_ID, RTYPE, RVAL, SIZE, APITYPE, INPUTFORMAT, ...)     \
242 do {                                                                                            \
243         POST_PACK_PROBEBLOCK_BEGIN();                                                           \
244         setProbePoint(&probeInfo);                                                              \
245         PREPARE_LOCAL_BUF();                                                                    \
246         PACK_COMMON_BEGIN(MSG_PROBE_RESOURCE, API_ID, INPUTFORMAT, __VA_ARGS__);                \
247         PACK_COMMON_END(RTYPE, RVAL, newerrno, blockresult);                                    \
248         POST_PACK_PROBEBLOCK_MIDDLE_NOFD(SIZE, APITYPE);                                        \
249         POST_PACK_PROBEBLOCK_END();                                                             \
250 } while(0)
251
252 #define AFTER_ORIGINAL_START_END_FILEP(API_ID, RTYPE, RVAL, SIZE, FILEP, APITYPE, INPUTFORMAT, ...)     \
253 do {                                                                                            \
254         POST_PACK_PROBEBLOCK_BEGIN();                                                           \
255         setProbePoint(&probeInfo);                                                              \
256         GET_FD_FROM_FILEP(FILEP);                                                               \
257         if(_fd != -1) {                                                                         \
258                 _fstatret = fstat(_fd, &_statbuf);                                              \
259         }                                                                                       \
260         PREPARE_LOCAL_BUF();                                                                    \
261         PACK_COMMON_BEGIN(MSG_PROBE_RESOURCE, API_ID, INPUTFORMAT, __VA_ARGS__);                \
262         PACK_COMMON_END(RTYPE, RVAL, newerrno, blockresult);                                    \
263         POST_PACK_PROBEBLOCK_MIDDLE_FD(SIZE, _fd, APITYPE);                                     \
264         POST_PACK_PROBEBLOCK_END();                                                             \
265 } while(0)
266
267
268 static inline ssize_t get_fd_filesize(int fd)
269 {
270         /**
271          * Calling library function on invalid file descriptiors is okay,
272          * for such cases we assume size == 0
273          * FIXME: Separate empty files and invalid descriptors.
274          **/
275         struct stat buf;
276         int err = fstat(fd, &buf);
277         if (err)
278                 return 0;
279         return buf.st_size ?: 0;
280 }
281
282 static inline int checked_fileno(FILE *fp)
283 {
284         assert((fp != NULL) &&
285                "This function (checked_fileno) is only called from probes\n"
286                "on library functions. Passing NULL instead of file pointer\n"
287                "to standart C functions is undefined behavior\n"
288                "and as such fatal error.\n");
289         return fileno(fp);
290 }
291
292
293 #endif  // __DA_IO_H__