8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / ndmpd / ndmp / ndmpd_log.c
blob0447e1c792747c10b0ad6b85abc265db8ceeac74
1 /*
2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
6 /*
7 * BSD 3 Clause License
9 * Copyright (c) 2007, The Storage Networking Industry Association.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * - Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
17 * - Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in
19 * the documentation and/or other materials provided with the
20 * distribution.
22 * - Neither the name of The Storage Networking Industry Association (SNIA)
23 * nor the names of its contributors may be used to endorse or promote
24 * products derived from this software without specific prior written
25 * permission.
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
39 /* Copyright (c) 2007, The Storage Networking Industry Association. */
40 /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
42 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
45 #include <errno.h>
46 #include <limits.h>
47 #include <stdarg.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <syslog.h>
51 #include <time.h>
52 #include <string.h>
53 #include <sys/stat.h>
54 #include <unistd.h>
55 #include <libgen.h>
56 #include <pthread.h>
57 #include <errno.h>
58 #include "ndmpd_log.h"
59 #include "ndmpd.h"
60 #include "ndmpd_common.h"
62 #define LOG_PATH "/var/log/ndmp"
63 #define LOG_FNAME "ndmplog.%d"
64 #define LOG_FILE_CNT 5
65 #define LOG_FILE_SIZE 4 * 1024 * 1024
66 #define LOG_SIZE_INT 256
68 static boolean_t debug = B_FALSE;
69 static boolean_t log_to_stderr = B_FALSE;
70 static FILE *logfp;
71 static int ndmp_synclog = 1;
75 * Since we use buffered file I/O for log file, the thread may lose CPU.
76 * At this time, another thread can destroy the contents of the buffer
77 * that must be written to the log file. The following mutex is used
78 * to allow only one thread to write into the log file.
80 static mutex_t log_lock;
82 static char *priority_str[] = {
83 "EMERGENCY",
84 "ALERT",
85 "CRITICAL",
86 "ERROR",
87 "WARNING",
88 "NOTICE",
89 "INFO",
90 "DEBUG",
95 * mk_pathname
97 * Append the NDMP working directory path to the specified file
99 static char *
100 mk_pathname(char *fname, char *path, int idx)
102 static char buf[PATH_MAX];
103 static char name[NAME_MAX];
104 char *fmt;
105 int len;
107 len = strnlen(path, PATH_MAX);
108 fmt = (path[len - 1] == '/') ? "%s%s" : "%s/%s";
110 /* LINTED variable format specifier */
111 (void) snprintf(name, NAME_MAX, fname, idx);
113 /* LINTED variable format specifier */
114 (void) snprintf(buf, PATH_MAX, fmt, path, name);
115 return (buf);
120 * openlogfile
122 * Open the NDMP log file
124 static int
125 openlogfile(char *fname, char *mode)
127 assert(fname != NULL && *fname != '\0' &&
128 mode != NULL && *mode != '\0');
130 if ((logfp = fopen(fname, mode)) == NULL) {
131 perror("Error opening logfile");
132 return (-1);
134 (void) mutex_init(&log_lock, 0, NULL);
136 return (0);
141 * log_write_cur_time
143 * Add the current time for each log entry
145 static void
146 log_write_cur_time(void)
148 struct tm tm;
149 time_t secs;
151 secs = time(NULL);
152 (void) localtime_r(&secs, &tm);
153 (void) fprintf(logfp, "%2d/%02d %2d:%02d:%02d ",
154 tm.tm_mon + 1, tm.tm_mday,
155 tm.tm_hour, tm.tm_min, tm.tm_sec);
160 * add_newline
162 * The new line at the end of each log
164 static void
165 add_newline(char *fmt)
167 if (fmt[strlen(fmt) - 1] != '\n')
168 (void) fputc('\n', logfp);
173 * log_append
175 * Append the message to the end of the log
177 static void
178 log_append(char *msg)
180 log_write_cur_time();
181 (void) fwrite(msg, 1, strlen(msg), logfp);
182 add_newline(msg);
183 if (ndmp_synclog)
184 (void) fflush(logfp);
189 * ndmp_log_openfile
191 * Open the log file either for append or write mode. This function should
192 * be called while ndmpd is still running single-threaded and in foreground.
195 ndmp_log_open_file(boolean_t to_stderr, boolean_t override_debug)
197 char *fname, *mode, *lpath;
198 char oldfname[PATH_MAX];
199 struct stat64 st;
200 int i;
202 log_to_stderr = to_stderr;
204 /* read debug property if it isn't overriden by cmd line option */
205 if (override_debug)
206 debug = B_TRUE;
207 else
208 debug = ndmpd_get_prop_yorn(NDMP_DEBUG_MODE) ? B_TRUE : B_FALSE;
210 /* Create the debug path if it doesn't exist */
211 lpath = ndmpd_get_prop(NDMP_DEBUG_PATH);
212 if ((lpath == NULL) || (*lpath == NULL))
213 lpath = LOG_PATH;
215 if (stat64(lpath, &st) < 0) {
216 if (mkdirp(lpath, 0755) < 0) {
217 (void) fprintf(stderr,
218 "Could not create log path %s: %s\n",
219 lpath, strerror(errno));
220 lpath = "/var";
225 * NDMP log file name will be {logfilename}.0 to {logfilename}.5, where
226 * {logfilename}.0 will always be the latest and the {logfilename}.5
227 * will be the oldest available file on the system. We keep maximum of 5
228 * log files. With the new session the files are shifted to next number
229 * and if the last file {logfilename}.5 exist, it will be overwritten
230 * with {logfilename}.4.
232 if (debug) {
233 i = LOG_FILE_CNT - 1;
234 while (i >= 0) {
235 fname = mk_pathname(LOG_FNAME, lpath, i);
236 (void) strncpy(oldfname, fname, PATH_MAX);
237 if (stat64(oldfname, &st) == -1) {
238 i--;
239 continue;
242 fname = mk_pathname(LOG_FNAME, lpath, i + 1);
243 if (rename(oldfname, fname))
244 (void) fprintf(stderr,
245 "Could not rename %s to %s: %s\n",
246 oldfname, fname, strerror(errno));
247 i--;
251 fname = mk_pathname(LOG_FNAME, lpath, 0);
254 * Append only if debug is not enable.
256 if (debug)
257 mode = "w";
258 else
259 mode = "a";
261 return (openlogfile(fname, mode));
265 * ndmp_log_close_file
267 * Close the log file
269 void
270 ndmp_log_close_file(void)
272 if (logfp != NULL) {
273 (void) fclose(logfp);
274 logfp = NULL;
276 (void) mutex_destroy(&log_lock);
279 void
280 ndmp_log(ulong_t priority, char *ndmp_log_info, char *fmt, ...)
282 int c;
283 va_list args;
284 char *f, *b;
285 char ndmp_log_buf[PATH_MAX+KILOBYTE];
286 char ndmp_syslog_buf[PATH_MAX+KILOBYTE];
287 char buf[PATH_MAX+KILOBYTE];
288 char *errstr;
290 if ((priority == LOG_DEBUG) && !debug)
291 return;
293 (void) mutex_lock(&log_lock);
295 if (priority > 7)
296 priority = LOG_ERR;
298 va_start(args, fmt);
299 /* Replace text error messages if fmt contains %m */
300 b = buf;
301 f = fmt;
302 while (((c = *f++) != '\0') && (c != '\n') &&
303 (b < &buf[PATH_MAX+KILOBYTE])) {
304 if (c != '%') {
305 *b++ = c;
306 continue;
308 if ((c = *f++) != 'm') {
309 *b++ = '%';
310 *b++ = c;
311 continue;
314 if ((errstr = strerror(errno)) == NULL) {
315 (void) snprintf(b, &buf[PATH_MAX+KILOBYTE] - b,
316 "error %d", errno);
317 } else {
318 while ((*errstr != '\0') &&
319 (b < &buf[PATH_MAX+KILOBYTE])) {
320 if (*errstr == '%') {
321 (void) strncpy(b, "%%", 2);
322 b += 2;
323 } else {
324 *b++ = *errstr;
326 errstr++;
328 *b = '\0';
330 b += strlen(b);
332 *b = '\0';
334 /* LINTED variable format specifier */
335 (void) vsnprintf(ndmp_syslog_buf, sizeof (ndmp_syslog_buf), buf, args);
336 va_end(args);
338 /* Send all logs other than debug, to syslog log file. */
339 if (priority != LOG_DEBUG)
340 syslog(priority, "%s", ndmp_syslog_buf);
342 /* ndmp_log_buf will have priority string and log info also */
343 (void) snprintf(ndmp_log_buf, sizeof (ndmp_log_buf), "%s: %s:%s",
344 priority_str[priority], ndmp_log_info, ndmp_syslog_buf);
346 if (logfp != NULL)
347 log_append(ndmp_log_buf);
349 /* if ndmpd is running in foreground print log message to stderr */
350 if (log_to_stderr)
351 (void) fprintf(stderr, "%s\n", ndmp_log_buf);
353 (void) mutex_unlock(&log_lock);