2
2
3
3
Copyright (C)
4
4
2005 - 2015 Arnaud Quette <http://arnaud.quette.free.fr/contact.html>
5
+ 2014 - 2023 Jim Klimov <jimklimov+nut@gmail.com>
5
6
6
7
This program is free software; you can redistribute it and/or modify
7
8
it under the terms of the GNU General Public License as published by
47
48
#include "dummy-ups.h"
48
49
49
50
#define DRIVER_NAME "Device simulation and repeater driver"
50
- #define DRIVER_VERSION "0.16 "
51
+ #define DRIVER_VERSION "0.17 "
51
52
52
53
/* driver description structure */
53
54
upsdrv_info_t upsdrv_info =
@@ -98,7 +99,7 @@ static struct stat datafile_stat;
98
99
99
100
static int setvar (const char * varname , const char * val );
100
101
static int instcmd (const char * cmdname , const char * extra );
101
- static int parse_data_file (TYPE_FD upsfd );
102
+ static int parse_data_file (TYPE_FD arg_upsfd );
102
103
static dummy_info_t * find_info (const char * varname );
103
104
static int is_valid_data (const char * varname );
104
105
static int is_valid_value (const char * varname , const char * value );
@@ -207,6 +208,36 @@ void upsdrv_initinfo(void)
207
208
dstate_addcmd ("load.off" );
208
209
}
209
210
211
+ static int prepare_filepath (char * fn , size_t buflen )
212
+ {
213
+ /* Note: device_path is a global variable,
214
+ * the "port=..." value parsed in main.c */
215
+ if (device_path [0 ] == '/'
216
+ #ifdef WIN32
217
+ || device_path [1 ] == ':' /* "C:\..." */
218
+ #endif
219
+ ) {
220
+ /* absolute path */
221
+ return snprintf (fn , buflen , "%s" , device_path );
222
+ } else if (device_path [0 ] == '.' ) {
223
+ /* "./" or "../" e.g. via CLI, relative to current working
224
+ * directory of the driver process... at this moment */
225
+ if (getcwd (fn , buflen )) {
226
+ return snprintf (fn + strlen (fn ), buflen - strlen (fn ), "/%s" , device_path );
227
+ } else {
228
+ return snprintf (fn , buflen , "%s" , device_path );
229
+ }
230
+ } else {
231
+ /* assumed to be a filename in NUT config file path
232
+ * (possibly under, with direct use of dirname without dots)
233
+ * Note that we do not fiddle with file-path separator,
234
+ * modern Windows (at least via MinGW/MSYS2) supports
235
+ * the POSIX slash.
236
+ */
237
+ return snprintf (fn , buflen , "%s/%s" , confpath (), device_path );
238
+ }
239
+ }
240
+
210
241
void upsdrv_updateinfo (void )
211
242
{
212
243
upsdebugx (1 , "upsdrv_updateinfo..." );
@@ -227,42 +258,35 @@ void upsdrv_updateinfo(void)
227
258
struct stat fs ;
228
259
char fn [SMALLBUF ];
229
260
230
- if (device_path [0 ] == '/'
231
- #ifdef WIN32
232
- || device_path [1 ] == ':' /* "C:\..." */
233
- #endif
234
- )
235
- snprintf (fn , sizeof (fn ), "%s" , device_path );
236
- else if (device_path [0 ] == '.' ) {
237
- /* "./" or "../" e.g. via CLI */
238
- if (getcwd (fn , sizeof (fn ))) {
239
- snprintf (fn + strlen (fn ), sizeof (fn ) - strlen (fn ), "/%s" , device_path );
240
- } else
241
- snprintf (fn , sizeof (fn ), "%s" , device_path );
242
- } else
243
- snprintf (fn , sizeof (fn ), "%s/%s" , confpath (), device_path );
261
+ prepare_filepath (fn , sizeof (fn ));
244
262
245
263
/* Determine if file modification timestamp has changed
246
264
* since last use (so we would want to re-read it) */
247
265
#ifndef WIN32
248
- /* Either successful stat is OK to fill the "fs" struct */
249
- if (0 != fstat (upsfd , & fs ) && 0 != stat (fn , & fs ))
266
+ /* Either successful stat (zero return) is OK to
267
+ * fill the "fs" struct. Note that currently
268
+ * "upsfd" is a no-op for files, they are re-opened
269
+ * and re-parsed every time so callers can modify
270
+ * the data without complications.
271
+ */
272
+ if ( (INVALID_FD (upsfd ) || 0 != fstat (upsfd , & fs )) && 0 != stat (fn , & fs ))
250
273
#else
251
274
/* Consider GetFileAttributesEx() for WIN32_FILE_ATTRIBUTE_DATA?
252
275
* https://stackoverflow.com/questions/8991192/check-the-file-size-without-opening-file-in-c/8991228#8991228
253
276
*/
254
277
if (0 != stat (fn , & fs ))
255
278
#endif
256
279
{
257
- upsdebugx (2 , "Can't open %s currently" , fn );
280
+ upsdebugx (2 , "%s: MODE_DUMMY_ONCE: Can't stat %s currently" , __func__ , fn );
258
281
/* retry ASAP until we get a file */
259
282
memset (& datafile_stat , 0 , sizeof (struct stat ));
260
283
next_update = 1 ;
261
284
} else {
262
285
if (datafile_stat .st_mtime != fs .st_mtime ) {
263
286
upsdebugx (2 ,
264
- "upsdrv_updateinfo: input file was already read once "
265
- "to the end, but changed later - re-reading: %s" , fn );
287
+ "%s: MODE_DUMMY_ONCE: input file was already read once "
288
+ "to the end, but changed later - re-reading: %s" ,
289
+ __func__ , fn );
266
290
/* updated file => retry ASAP */
267
291
next_update = 1 ;
268
292
datafile_stat = fs ;
@@ -271,7 +295,7 @@ void upsdrv_updateinfo(void)
271
295
}
272
296
273
297
if (ctx == NULL && next_update == -1 ) {
274
- upsdebugx (2 , "upsdrv_updateinfo: NO-OP: input file was already read once to the end" );
298
+ upsdebugx (2 , "%s: MODE_DUMMY_ONCE: NO-OP: input file was already read once to the end" , __func__ );
275
299
dstate_dataok ();
276
300
} else {
277
301
/* initial parsing interrupted by e.g. TIMER line */
@@ -474,33 +498,25 @@ void upsdrv_initups(void)
474
498
#endif
475
499
}
476
500
477
- if (device_path [0 ] == '/'
478
- #ifdef WIN32
479
- || device_path [1 ] == ':' /* "C:\..." */
480
- #endif
481
- )
482
- snprintf (fn , sizeof (fn ), "%s" , device_path );
483
- else if (device_path [0 ] == '.' ) {
484
- /* "./" or "../" e.g. via CLI */
485
- if (getcwd (fn , sizeof (fn ))) {
486
- snprintf (fn + strlen (fn ), sizeof (fn ) - strlen (fn ), "/%s" , device_path );
487
- } else
488
- snprintf (fn , sizeof (fn ), "%s" , device_path );
489
- } else
490
- snprintf (fn , sizeof (fn ), "%s/%s" , confpath (), device_path );
501
+ prepare_filepath (fn , sizeof (fn ));
491
502
492
503
/* Update file modification timestamp (and other data) */
493
504
#ifndef WIN32
494
- /* Either successful stat is OK to fill the "datafile_stat" struct */
495
- if (0 != fstat (upsfd , & datafile_stat ) && 0 != stat (device_path , & datafile_stat ))
505
+ /* Either successful stat (zero return) is OK to fill the
506
+ * "datafile_stat" struct. Note that currently "upsfd" is
507
+ * a no-op for files, they are re-opened and re-parsed
508
+ * every time so callers can modify the data without
509
+ * complications.
510
+ */
511
+ if ( (INVALID_FD (upsfd ) || 0 != fstat (upsfd , & datafile_stat )) && 0 != stat (fn , & datafile_stat ))
496
512
#else
497
513
/* Consider GetFileAttributesEx() for WIN32_FILE_ATTRIBUTE_DATA?
498
514
* https://stackoverflow.com/questions/8991192/check-the-file-size-without-opening-file-in-c/8991228#8991228
499
515
*/
500
- if (0 != stat (device_path , & datafile_stat ))
516
+ if (0 != stat (fn , & datafile_stat ))
501
517
#endif
502
518
{
503
- upsdebugx (2 , "Can't open %s (%s) currently" , device_path , fn );
519
+ upsdebugx (2 , "%s: Can't stat %s (%s) currently" , __func__ , device_path , fn );
504
520
} else {
505
521
upsdebugx (2 , "Located %s for device simulation data: %s" , device_path , fn );
506
522
}
@@ -642,7 +658,7 @@ static dummy_info_t *find_info(const char *varname)
642
658
return item ;
643
659
}
644
660
645
- upsdebugx (2 , "find_info: unknown variable: %s\n " , varname );
661
+ upsdebugx (2 , "find_info: unknown variable: %s" , varname );
646
662
647
663
return NULL ;
648
664
}
@@ -719,21 +735,7 @@ static int parse_data_file(TYPE_FD arg_upsfd)
719
735
{
720
736
ctx = (PCONF_CTX_t * )xmalloc (sizeof (PCONF_CTX_t ));
721
737
722
- if (device_path [0 ] == '/'
723
- #ifdef WIN32
724
- || device_path [1 ] == ':' /* "C:\..." */
725
- #endif
726
- )
727
- snprintf (fn , sizeof (fn ), "%s" , device_path );
728
- else if (device_path [0 ] == '.' ) {
729
- /* "./" or "../" e.g. via CLI */
730
- if (getcwd (fn , sizeof (fn ))) {
731
- snprintf (fn + strlen (fn ), sizeof (fn ) - strlen (fn ), "/%s" , device_path );
732
- } else
733
- snprintf (fn , sizeof (fn ), "%s" , device_path );
734
- } else
735
- snprintf (fn , sizeof (fn ), "%s/%s" , confpath (), device_path );
736
-
738
+ prepare_filepath (fn , sizeof (fn ));
737
739
pconf_init (ctx , upsconf_err );
738
740
739
741
if (!pconf_file_begin (ctx , fn ))
0 commit comments