4 * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
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>
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)
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.
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
29 * - Samsung RnD Institute Russia
37 #include <sys/types.h>
44 /********************************************************************
45 * RESOURCE PROBE MACRO
48 * SeqNumber`,ApiName`,Time`,Pid`,Tid`,InputParm`,Return`,PCAddr`,Error`,
49 * Size`,FDValue`,FDType`,FDApiType`, \n
50 * callstack_start`,callstack`,callstack_end
53 * FD_TYPE_FILE, FD_TYPE_SOCKET
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
60 ************************************************************************/
62 // ===================================================================
63 // macro for file probe
64 // ===================================================================
66 #define GET_FD_FROM_FILEP(FILEP) \
68 _fd = (FILEP != NULL) ? fileno(FILEP) : -1; \
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
79 // =================================================================
80 // POST_PROBEBLOCK_MIDDLE for file
81 // =================================================================
83 #define POST_PACK_PROBEBLOCK_MIDDLE_FD(SIZE, FD, APITYPE) \
85 PACK_RESOURCE(SIZE, FD, APITYPE, \
86 (_fstatret == 0 ? _statbuf.st_size : 0), _filepath); \
90 #define POST_PACK_PROBEBLOCK_MIDDLE_NOFD(SIZE, APITYPE) \
92 PACK_RESOURCE(SIZE, 0, APITYPE, 0, _filepath); \
96 // ==================================================================
97 // BEFORE_ORIGINAL macro for file
98 // ==================================================================
100 #define BEFORE_ORIGINAL_FILE(FUNCNAME, LIBNAME) \
101 DECLARE_VARIABLE_FD; \
102 GET_REAL_FUNC(FUNCNAME, LIBNAME); \
105 #define BEFORE_ORIGINAL_FILE_NOFILTER(FUNCNAME, LIBNAME) \
106 DECLARE_VARIABLE_FD; \
107 GET_REAL_FUNC(FUNCNAME, LIBNAME); \
108 bfiltering = false; \
111 // ==================================================================
112 // macro for filesize
113 // ==================================================================
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;
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
124 #define AFTER_PACK_ORIGINAL_FD(API_ID, RTYPE, RVAL, SIZE, FD, APITYPE, INPUTFORMAT, ...) \
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); \
134 POST_PACK_PROBEBLOCK_END(); \
137 #define AFTER_PACK_ORIGINAL_FD_MIDDLE(API_ID, RTYPE, RVAL, SIZE, FD, APITYPE, INPUTFORMAT, ...) \
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); \
147 POST_PACK_PROBEBLOCK_ADD_END(); \
150 #define AFTER_PACK_ORIGINAL_NOFD(API_ID, RTYPE, RVAL, SIZE, APITYPE, INPUTFORMAT, ...) \
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(); \
160 #define AFTER_PACK_ORIGINAL_FILEP(API_ID, RTYPE, RVAL, SIZE, FILEP, APITYPE, INPUTFORMAT, ...) \
162 POST_PACK_PROBEBLOCK_BEGIN(); \
163 GET_FD_FROM_FILEP(FILEP); \
165 _fstatret = fstat(_fd, &_statbuf); \
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(); \
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.
180 static inline bool stat_regular_or_socket_p(struct stat *buf)
182 return S_ISREG(buf->st_mode) || S_ISSOCK(buf->st_mode);
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); \
197 PRE_PROBEBLOCK_END(); \
199 #define AFTER_ORIGINAL_START_END_FD(API_ID, RTYPE, RVAL, SIZE, FD, APITYPE, INPUTFORMAT, ...) \
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); \
211 POST_PACK_PROBEBLOCK_END(); \
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); \
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); \
233 _fstatret = fstat(_fd, &_statbuf); \
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); \
241 #define AFTER_ORIGINAL_START_END_NOFD(API_ID, RTYPE, RVAL, SIZE, APITYPE, INPUTFORMAT, ...) \
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(); \
252 #define AFTER_ORIGINAL_START_END_FILEP(API_ID, RTYPE, RVAL, SIZE, FILEP, APITYPE, INPUTFORMAT, ...) \
254 POST_PACK_PROBEBLOCK_BEGIN(); \
255 setProbePoint(&probeInfo); \
256 GET_FD_FROM_FILEP(FILEP); \
258 _fstatret = fstat(_fd, &_statbuf); \
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(); \
268 static inline ssize_t get_fd_filesize(int fd)
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.
276 int err = fstat(fd, &buf);
279 return buf.st_size ?: 0;
282 static inline int checked_fileno(FILE *fp)
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");
293 #endif // __DA_IO_H__