mirror of
https://github.com/wanderleihuttel/vchanger.git
synced 2025-04-19 08:55:14 +00:00
Add vchanger 1.0.3 code
This commit is contained in:
parent
7490e52578
commit
d7a0e39e91
3
AUTHORS
3
AUTHORS
@ -7,3 +7,6 @@ Principle Authors:
|
|||||||
Josh Fisher
|
Josh Fisher
|
||||||
|
|
||||||
Contributors:
|
Contributors:
|
||||||
|
Bill Arlofski
|
||||||
|
Wanderlei Hüttel
|
||||||
|
Steven A. Falco
|
2
COPYING
2
COPYING
@ -1,5 +1,5 @@
|
|||||||
COPYRIGHTS:
|
COPYRIGHTS:
|
||||||
Vchanger is Copyright (C) 2008-2015 Josh Fisher.
|
Vchanger is Copyright (C) 2008-2020 Josh Fisher.
|
||||||
|
|
||||||
LICENSE:
|
LICENSE:
|
||||||
Vchanger is licensed under the GNU GPL version 2, the full text
|
Vchanger is licensed under the GNU GPL version 2, the full text
|
||||||
|
21
ChangeLog
21
ChangeLog
@ -1,5 +1,26 @@
|
|||||||
vchanger ChangeLog
|
vchanger ChangeLog
|
||||||
|
|
||||||
|
1.0.3 (2020-05-06)
|
||||||
|
- Redesign locking mechanism for multiple instances using POSIX
|
||||||
|
semaphores.
|
||||||
|
- Use at, rather than nohup, in scripts invoked by udev rules to fix
|
||||||
|
nohup not working as expected on some platforms.
|
||||||
|
(Patch from Steven A. Falco)
|
||||||
|
- Add spec file for Fedora 29 (Provided by Steven A. Falco)
|
||||||
|
- Correct number of slots reported by SIZE command (Fixes bug 17)
|
||||||
|
- Rename logging variables that conflict with cmath's log function (Fixes bug 18)
|
||||||
|
1.0.2 (2018-06-14)
|
||||||
|
- Use named mutex to prevent instances of vchanger invoked by Bacula during
|
||||||
|
a bconsole call from initiating further bconsole calls. Prevents a race
|
||||||
|
condition caused by the need for Bacula to invoke additional instances of
|
||||||
|
vchanger when vchanger invokes bconsole to issue 'update slots' and
|
||||||
|
'label barcodes' commands. (Fixes bug 15)
|
||||||
|
- Prevent load command from loading the same virtual slot into more than
|
||||||
|
one virtual drive. (Fixes bug 13)
|
||||||
|
- Fix bconsole update slots command needs drive to be specified. [Patch
|
||||||
|
from Bill Arlofski] (Fixes bug 14)
|
||||||
|
- Improve generated volume label format. [Patch from Wanderlei Huttel]
|
||||||
|
- Additional logging to help debug udev/UUID assignment problems
|
||||||
1.0.1 (2015-06-09)
|
1.0.1 (2015-06-09)
|
||||||
- When looking up the mountpoint of a magazine by UUID with libudev,
|
- When looking up the mountpoint of a magazine by UUID with libudev,
|
||||||
also look for mountpoint of device alias names in DEVLINKS in addition
|
also look for mountpoint of device alias names in DEVLINKS in addition
|
||||||
|
34
ReleaseNotes
34
ReleaseNotes
@ -1,4 +1,34 @@
|
|||||||
Release Notes for vchanger 1.0.1 2015-06-09
|
Release Notes for vchanger 1.0.3 2020-05-07
|
||||||
|
|
||||||
|
Release 1.0.3
|
||||||
|
|
||||||
|
This is mostly a bug fix release, correcting the number of slots
|
||||||
|
reported by SIZE/LIST commands, a compilation error on FreeBSD,
|
||||||
|
and failure of the launch scripts invoked by udev on some platforms.
|
||||||
|
|
||||||
|
The locking mechanism to allow multiple instances and automatically
|
||||||
|
issuing 'update slots' and other commands to bconsole has been
|
||||||
|
redesigned to use POSIX semaphores.
|
||||||
|
|
||||||
|
Bugs Fixed:
|
||||||
|
17 SIZE/LIST commands return wrong number of slots
|
||||||
|
18 Compilation fails on FreeBSD 13 (head)
|
||||||
|
|
||||||
|
==================================================================
|
||||||
|
|
||||||
|
Release 1.0.2
|
||||||
|
|
||||||
|
This is a bug fix release, fixing three issues found in version 1.0.1
|
||||||
|
and improving volume label formatting for CREATEVOLS command and logging
|
||||||
|
of udev/UUID mountpoint discovery.
|
||||||
|
|
||||||
|
Bugs Fixed:
|
||||||
|
|
||||||
|
13 LOAD command allows loading slot into multiple drives
|
||||||
|
14 Hang when bconsole called to update slots
|
||||||
|
15 Race condition in bconsole call may hang vchanger
|
||||||
|
|
||||||
|
==================================================================
|
||||||
|
|
||||||
Release 1.0.1
|
Release 1.0.1
|
||||||
|
|
||||||
@ -6,7 +36,7 @@
|
|||||||
Additionally, the Windows installer was fixed to correctly install on
|
Additionally, the Windows installer was fixed to correctly install on
|
||||||
64-bit Windows and create Start Menu items.
|
64-bit Windows and create Start Menu items.
|
||||||
|
|
||||||
Bugs Fixed:
|
Bugs Fixed:
|
||||||
|
|
||||||
9 Vchanger may hang when issuing commands to Bacula
|
9 Vchanger may hang when issuing commands to Bacula
|
||||||
10 uuidlookup.c compilation failure on FreeBSD 9.3
|
10 uuidlookup.c compilation failure on FreeBSD 9.3
|
||||||
|
11
config.h.in
11
config.h.in
@ -15,6 +15,9 @@
|
|||||||
/* Define to 1 if you have the <ctype.h> header file. */
|
/* Define to 1 if you have the <ctype.h> header file. */
|
||||||
#undef HAVE_CTYPE_H
|
#undef HAVE_CTYPE_H
|
||||||
|
|
||||||
|
/* have header direct.h */
|
||||||
|
#undef HAVE_DIRECT_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <dirent.h> header file. */
|
/* Define to 1 if you have the <dirent.h> header file. */
|
||||||
#undef HAVE_DIRENT_H
|
#undef HAVE_DIRENT_H
|
||||||
|
|
||||||
@ -69,7 +72,7 @@
|
|||||||
/* Define to 1 if you have the <locale.h> header file. */
|
/* Define to 1 if you have the <locale.h> header file. */
|
||||||
#undef HAVE_LOCALE_H
|
#undef HAVE_LOCALE_H
|
||||||
|
|
||||||
/* Define to 1 if you have the `localtime_r' function. */
|
/* have function localtime_r */
|
||||||
#undef HAVE_LOCALTIME_R
|
#undef HAVE_LOCALTIME_R
|
||||||
|
|
||||||
/* Define to 1 if you have the <memory.h> header file. */
|
/* Define to 1 if you have the <memory.h> header file. */
|
||||||
@ -96,6 +99,9 @@
|
|||||||
/* Define to 1 if you have the `readlink' function. */
|
/* Define to 1 if you have the `readlink' function. */
|
||||||
#undef HAVE_READLINK
|
#undef HAVE_READLINK
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <semaphore.h> header file. */
|
||||||
|
#undef HAVE_SEMAPHORE_H
|
||||||
|
|
||||||
/* Define to 1 if you have the `setlocale' function. */
|
/* Define to 1 if you have the `setlocale' function. */
|
||||||
#undef HAVE_SETLOCALE
|
#undef HAVE_SETLOCALE
|
||||||
|
|
||||||
@ -148,6 +154,9 @@
|
|||||||
*/
|
*/
|
||||||
#undef HAVE_SYS_DIR_H
|
#undef HAVE_SYS_DIR_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/mman.h> header file. */
|
||||||
|
#undef HAVE_SYS_MMAN_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/mount.h> header file. */
|
/* Define to 1 if you have the <sys/mount.h> header file. */
|
||||||
#undef HAVE_SYS_MOUNT_H
|
#undef HAVE_SYS_MOUNT_H
|
||||||
|
|
||||||
|
316
config.h.in~
Normal file
316
config.h.in~
Normal file
@ -0,0 +1,316 @@
|
|||||||
|
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||||
|
|
||||||
|
/* Copyright notice */
|
||||||
|
#undef COPYRIGHT_NOTICE
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <alloca.h> header file. */
|
||||||
|
#undef HAVE_ALLOCA_H
|
||||||
|
|
||||||
|
/* Have blkid_evaluate_tag function */
|
||||||
|
#undef HAVE_BLKID_EVALUATE_TAG
|
||||||
|
|
||||||
|
/* Have blkid_get_devname function */
|
||||||
|
#undef HAVE_BLKID_GET_DEVNAME
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <ctype.h> header file. */
|
||||||
|
#undef HAVE_CTYPE_H
|
||||||
|
|
||||||
|
/* have header direct.h */
|
||||||
|
#undef HAVE_DIRECT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <dirent.h> header file. */
|
||||||
|
#undef HAVE_DIRENT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
|
||||||
|
#undef HAVE_DOPRNT
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <errno.h> header file. */
|
||||||
|
#undef HAVE_ERRNO_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||||
|
#undef HAVE_FCNTL_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getfsstat' function. */
|
||||||
|
#undef HAVE_GETFSSTAT
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getline' function. */
|
||||||
|
#undef HAVE_GETLINE
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getmntent' function. */
|
||||||
|
#undef HAVE_GETMNTENT
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getmntent_r' function. */
|
||||||
|
#undef HAVE_GETMNTENT_R
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <getopt.h> header file. */
|
||||||
|
#undef HAVE_GETOPT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `gettimeofday' function. */
|
||||||
|
#undef HAVE_GETTIMEOFDAY
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `getuid' function. */
|
||||||
|
#undef HAVE_GETUID
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <grp.h> header file. */
|
||||||
|
#undef HAVE_GRP_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||||
|
#undef HAVE_INTTYPES_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <io.h> header file. */
|
||||||
|
#undef HAVE_IO_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <libgen.h> header file. */
|
||||||
|
#undef HAVE_LIBGEN_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <libudev.h> header file. */
|
||||||
|
#undef HAVE_LIBUDEV_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <limits.h> header file. */
|
||||||
|
#undef HAVE_LIMITS_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <locale.h> header file. */
|
||||||
|
#undef HAVE_LOCALE_H
|
||||||
|
|
||||||
|
/* have function localtime_r */
|
||||||
|
#undef HAVE_LOCALTIME_R
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <memory.h> header file. */
|
||||||
|
#undef HAVE_MEMORY_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <mntent.h> header file. */
|
||||||
|
#undef HAVE_MNTENT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
|
||||||
|
#undef HAVE_NDIR_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <optarg.h> header file. */
|
||||||
|
#undef HAVE_OPTARG_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `pipe' function. */
|
||||||
|
#undef HAVE_PIPE
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <pthread.h> header file. */
|
||||||
|
#undef HAVE_PTHREAD_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <pwd.h> header file. */
|
||||||
|
#undef HAVE_PWD_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `readlink' function. */
|
||||||
|
#undef HAVE_READLINK
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `setlocale' function. */
|
||||||
|
#undef HAVE_SETLOCALE
|
||||||
|
|
||||||
|
/* have header shlobj.h */
|
||||||
|
#undef HAVE_SHLOBJ_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <signal.h> header file. */
|
||||||
|
#undef HAVE_SIGNAL_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `sleep' function. */
|
||||||
|
#undef HAVE_SLEEP
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdarg.h> header file. */
|
||||||
|
#undef HAVE_STDARG_H
|
||||||
|
|
||||||
|
/* Define to 1 if stdbool.h conforms to C99. */
|
||||||
|
#undef HAVE_STDBOOL_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stddef.h> header file. */
|
||||||
|
#undef HAVE_STDDEF_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdint.h> header file. */
|
||||||
|
#undef HAVE_STDINT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdio.h> header file. */
|
||||||
|
#undef HAVE_STDIO_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||||
|
#undef HAVE_STDLIB_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <strings.h> header file. */
|
||||||
|
#undef HAVE_STRINGS_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <string.h> header file. */
|
||||||
|
#undef HAVE_STRING_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `symlink' function. */
|
||||||
|
#undef HAVE_SYMLINK
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `syslog' function. */
|
||||||
|
#undef HAVE_SYSLOG
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <syslog.h> header file. */
|
||||||
|
#undef HAVE_SYSLOG_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/bitypes.h> header file. */
|
||||||
|
#undef HAVE_SYS_BITYPES_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
|
||||||
|
*/
|
||||||
|
#undef HAVE_SYS_DIR_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/mman.h> header file. */
|
||||||
|
#undef HAVE_SYS_MMAN_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/mount.h> header file. */
|
||||||
|
#undef HAVE_SYS_MOUNT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
|
||||||
|
*/
|
||||||
|
#undef HAVE_SYS_NDIR_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||||
|
#undef HAVE_SYS_PARAM_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/select.h> header file. */
|
||||||
|
#undef HAVE_SYS_SELECT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||||
|
#undef HAVE_SYS_STAT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/timespec.h> header file. */
|
||||||
|
#undef HAVE_SYS_TIMESPEC_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||||
|
#undef HAVE_SYS_TIME_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||||
|
#undef HAVE_SYS_TYPES_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/ucred.h> header file. */
|
||||||
|
#undef HAVE_SYS_UCRED_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/wait.h> header file. */
|
||||||
|
#undef HAVE_SYS_WAIT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <time.h> header file. */
|
||||||
|
#undef HAVE_TIME_H
|
||||||
|
|
||||||
|
/* Define to 1 if typeof works with your compiler. */
|
||||||
|
#undef HAVE_TYPEOF
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <unistd.h> header file. */
|
||||||
|
#undef HAVE_UNISTD_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <utime.h> header file. */
|
||||||
|
#undef HAVE_UTIME_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <varargs.h> header file. */
|
||||||
|
#undef HAVE_VARARGS_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `vprintf' function. */
|
||||||
|
#undef HAVE_VPRINTF
|
||||||
|
|
||||||
|
/* have header windows.h */
|
||||||
|
#undef HAVE_WINDOWS_H
|
||||||
|
|
||||||
|
/* have header winioctl.h */
|
||||||
|
#undef HAVE_WINIOCTL_H
|
||||||
|
|
||||||
|
/* have header winreg.h */
|
||||||
|
#undef HAVE_WINREG_H
|
||||||
|
|
||||||
|
/* have header winsock.h */
|
||||||
|
#undef HAVE_WINSOCK_H
|
||||||
|
|
||||||
|
/* Define to 1 if the system has the type `_Bool'. */
|
||||||
|
#undef HAVE__BOOL
|
||||||
|
|
||||||
|
/* Name of package */
|
||||||
|
#undef PACKAGE
|
||||||
|
|
||||||
|
/* Define to the address where bug reports for this package should be sent. */
|
||||||
|
#undef PACKAGE_BUGREPORT
|
||||||
|
|
||||||
|
/* Define to the full name of this package. */
|
||||||
|
#undef PACKAGE_NAME
|
||||||
|
|
||||||
|
/* Define to the full name and version of this package. */
|
||||||
|
#undef PACKAGE_STRING
|
||||||
|
|
||||||
|
/* Define to the one symbol short name of this package. */
|
||||||
|
#undef PACKAGE_TARNAME
|
||||||
|
|
||||||
|
/* Define to the home page for this package. */
|
||||||
|
#undef PACKAGE_URL
|
||||||
|
|
||||||
|
/* Define to the version of this package. */
|
||||||
|
#undef PACKAGE_VERSION
|
||||||
|
|
||||||
|
/* Define to 1 if you have the ANSI C header files. */
|
||||||
|
#undef STDC_HEADERS
|
||||||
|
|
||||||
|
/* Version number of package */
|
||||||
|
#undef VERSION
|
||||||
|
|
||||||
|
/* Enable large inode numbers on Mac OS X 10.5. */
|
||||||
|
#ifndef _DARWIN_USE_64_BIT_INODE
|
||||||
|
# define _DARWIN_USE_64_BIT_INODE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||||
|
#undef _FILE_OFFSET_BITS
|
||||||
|
|
||||||
|
/* Define for large files, on AIX-style hosts. */
|
||||||
|
#undef _LARGE_FILES
|
||||||
|
|
||||||
|
/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
|
||||||
|
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
|
||||||
|
#define below would cause a syntax error. */
|
||||||
|
#undef _UINT32_T
|
||||||
|
|
||||||
|
/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
|
||||||
|
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
|
||||||
|
#define below would cause a syntax error. */
|
||||||
|
#undef _UINT64_T
|
||||||
|
|
||||||
|
/* Define to empty if `const' does not conform to ANSI C. */
|
||||||
|
#undef const
|
||||||
|
|
||||||
|
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||||
|
#undef gid_t
|
||||||
|
|
||||||
|
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||||
|
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#undef inline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define to the type of a signed integer type of width exactly 32 bits if
|
||||||
|
such a type exists and the standard includes do not define it. */
|
||||||
|
#undef int32_t
|
||||||
|
|
||||||
|
/* Define to the type of a signed integer type of width exactly 64 bits if
|
||||||
|
such a type exists and the standard includes do not define it. */
|
||||||
|
#undef int64_t
|
||||||
|
|
||||||
|
/* Define to `int' if <sys/types.h> does not define. */
|
||||||
|
#undef mode_t
|
||||||
|
|
||||||
|
/* Define to `long int' if <sys/types.h> does not define. */
|
||||||
|
#undef off_t
|
||||||
|
|
||||||
|
/* Define to `int' if <sys/types.h> does not define. */
|
||||||
|
#undef pid_t
|
||||||
|
|
||||||
|
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||||
|
#undef size_t
|
||||||
|
|
||||||
|
/* Define to `int' if <sys/types.h> does not define. */
|
||||||
|
#undef ssize_t
|
||||||
|
|
||||||
|
/* Define to __typeof__ if your compiler spells it that way. */
|
||||||
|
#undef typeof
|
||||||
|
|
||||||
|
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||||
|
#undef uid_t
|
||||||
|
|
||||||
|
/* Define to the type of an unsigned integer type of width exactly 32 bits if
|
||||||
|
such a type exists and the standard includes do not define it. */
|
||||||
|
#undef uint32_t
|
||||||
|
|
||||||
|
/* Define to the type of an unsigned integer type of width exactly 64 bits if
|
||||||
|
such a type exists and the standard includes do not define it. */
|
||||||
|
#undef uint64_t
|
216
configure
vendored
216
configure
vendored
@ -1,6 +1,6 @@
|
|||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Guess values for system-dependent variables and create Makefiles.
|
# Guess values for system-dependent variables and create Makefiles.
|
||||||
# Generated by GNU Autoconf 2.69 for vchanger 1.0.1.
|
# Generated by GNU Autoconf 2.69 for vchanger 1.0.3.
|
||||||
#
|
#
|
||||||
# Report bugs to <jfisher@jaybus.com>.
|
# Report bugs to <jfisher@jaybus.com>.
|
||||||
#
|
#
|
||||||
@ -580,8 +580,8 @@ MAKEFLAGS=
|
|||||||
# Identity of this package.
|
# Identity of this package.
|
||||||
PACKAGE_NAME='vchanger'
|
PACKAGE_NAME='vchanger'
|
||||||
PACKAGE_TARNAME='vchanger'
|
PACKAGE_TARNAME='vchanger'
|
||||||
PACKAGE_VERSION='1.0.1'
|
PACKAGE_VERSION='1.0.3'
|
||||||
PACKAGE_STRING='vchanger 1.0.1'
|
PACKAGE_STRING='vchanger 1.0.3'
|
||||||
PACKAGE_BUGREPORT='jfisher@jaybus.com'
|
PACKAGE_BUGREPORT='jfisher@jaybus.com'
|
||||||
PACKAGE_URL=''
|
PACKAGE_URL=''
|
||||||
|
|
||||||
@ -1279,7 +1279,7 @@ if test "$ac_init_help" = "long"; then
|
|||||||
# Omit some internal or obsolete options to make the list less imposing.
|
# Omit some internal or obsolete options to make the list less imposing.
|
||||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||||
cat <<_ACEOF
|
cat <<_ACEOF
|
||||||
\`configure' configures vchanger 1.0.1 to adapt to many kinds of systems.
|
\`configure' configures vchanger 1.0.3 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
@ -1345,7 +1345,7 @@ fi
|
|||||||
|
|
||||||
if test -n "$ac_init_help"; then
|
if test -n "$ac_init_help"; then
|
||||||
case $ac_init_help in
|
case $ac_init_help in
|
||||||
short | recursive ) echo "Configuration of vchanger 1.0.1:";;
|
short | recursive ) echo "Configuration of vchanger 1.0.3:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
@ -1439,7 +1439,7 @@ fi
|
|||||||
test -n "$ac_init_help" && exit $ac_status
|
test -n "$ac_init_help" && exit $ac_status
|
||||||
if $ac_init_version; then
|
if $ac_init_version; then
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
vchanger configure 1.0.1
|
vchanger configure 1.0.3
|
||||||
generated by GNU Autoconf 2.69
|
generated by GNU Autoconf 2.69
|
||||||
|
|
||||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||||
@ -2026,11 +2026,57 @@ $as_echo "$ac_res" >&6; }
|
|||||||
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
|
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
|
||||||
|
|
||||||
} # ac_fn_c_check_func
|
} # ac_fn_c_check_func
|
||||||
|
|
||||||
|
# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
|
||||||
|
# ---------------------------------------------
|
||||||
|
# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
|
||||||
|
# accordingly.
|
||||||
|
ac_fn_c_check_decl ()
|
||||||
|
{
|
||||||
|
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
|
||||||
|
as_decl_name=`echo $2|sed 's/ *(.*//'`
|
||||||
|
as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
|
||||||
|
$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
|
||||||
|
if eval \${$3+:} false; then :
|
||||||
|
$as_echo_n "(cached) " >&6
|
||||||
|
else
|
||||||
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
|
/* end confdefs.h. */
|
||||||
|
$4
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
#ifndef $as_decl_name
|
||||||
|
#ifdef __cplusplus
|
||||||
|
(void) $as_decl_use;
|
||||||
|
#else
|
||||||
|
(void) $as_decl_name;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_ACEOF
|
||||||
|
if ac_fn_c_try_compile "$LINENO"; then :
|
||||||
|
eval "$3=yes"
|
||||||
|
else
|
||||||
|
eval "$3=no"
|
||||||
|
fi
|
||||||
|
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||||
|
fi
|
||||||
|
eval ac_res=\$$3
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
|
||||||
|
$as_echo "$ac_res" >&6; }
|
||||||
|
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
|
||||||
|
|
||||||
|
} # ac_fn_c_check_decl
|
||||||
cat >config.log <<_ACEOF
|
cat >config.log <<_ACEOF
|
||||||
This file contains any messages produced by compilers while
|
This file contains any messages produced by compilers while
|
||||||
running configure, to aid debugging if configure makes a mistake.
|
running configure, to aid debugging if configure makes a mistake.
|
||||||
|
|
||||||
It was created by vchanger $as_me 1.0.1, which was
|
It was created by vchanger $as_me 1.0.3, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
$ $0 $@
|
$ $0 $@
|
||||||
@ -2342,12 +2388,14 @@ as_fn_append ac_header_list " grp.h"
|
|||||||
as_fn_append ac_header_list " pwd.h"
|
as_fn_append ac_header_list " pwd.h"
|
||||||
as_fn_append ac_header_list " dirent.h"
|
as_fn_append ac_header_list " dirent.h"
|
||||||
as_fn_append ac_header_list " fcntl.h"
|
as_fn_append ac_header_list " fcntl.h"
|
||||||
|
as_fn_append ac_header_list " sys/mman.h"
|
||||||
as_fn_append ac_header_list " sys/select.h"
|
as_fn_append ac_header_list " sys/select.h"
|
||||||
as_fn_append ac_header_list " optarg.h"
|
as_fn_append ac_header_list " optarg.h"
|
||||||
as_fn_append ac_header_list " pthread.h"
|
as_fn_append ac_header_list " pthread.h"
|
||||||
as_fn_append ac_header_list " libgen.h"
|
as_fn_append ac_header_list " libgen.h"
|
||||||
as_fn_append ac_header_list " io.h"
|
as_fn_append ac_header_list " io.h"
|
||||||
as_fn_append ac_header_list " signal.h"
|
as_fn_append ac_header_list " signal.h"
|
||||||
|
as_fn_append ac_header_list " semaphore.h"
|
||||||
# Check that the precious variables saved in the cache have kept the same
|
# Check that the precious variables saved in the cache have kept the same
|
||||||
# value.
|
# value.
|
||||||
ac_cache_corrupted=false
|
ac_cache_corrupted=false
|
||||||
@ -2417,7 +2465,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
$as_echo "#define COPYRIGHT_NOTICE \"vchanger Copyright (c) 2006-2015 Josh Fisher\"" >>confdefs.h
|
$as_echo "#define COPYRIGHT_NOTICE \"vchanger Copyright (c) 2006-2020 Josh Fisher\"" >>confdefs.h
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -2938,7 +2986,7 @@ fi
|
|||||||
|
|
||||||
# Define the identity of the package.
|
# Define the identity of the package.
|
||||||
PACKAGE='vchanger'
|
PACKAGE='vchanger'
|
||||||
VERSION='1.0.1'
|
VERSION='1.0.3'
|
||||||
|
|
||||||
|
|
||||||
cat >>confdefs.h <<_ACEOF
|
cat >>confdefs.h <<_ACEOF
|
||||||
@ -5514,6 +5562,70 @@ else
|
|||||||
as_fn_error $? "\"could not find libpthread\"" "$LINENO" 5
|
as_fn_error $? "\"could not find libpthread\"" "$LINENO" 5
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
ac_fn_c_check_header_mongrel "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h" "$ac_includes_default"
|
||||||
|
if test "x$ac_cv_header_sys_mman_h" = xyes; then :
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing shm_open" >&5
|
||||||
|
$as_echo_n "checking for library containing shm_open... " >&6; }
|
||||||
|
if ${ac_cv_search_shm_open+:} false; then :
|
||||||
|
$as_echo_n "(cached) " >&6
|
||||||
|
else
|
||||||
|
ac_func_search_save_LIBS=$LIBS
|
||||||
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
|
/* end confdefs.h. */
|
||||||
|
|
||||||
|
/* Override any GCC internal prototype to avoid an error.
|
||||||
|
Use char because int might match the return type of a GCC
|
||||||
|
builtin and then its argument prototype would still apply. */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
#endif
|
||||||
|
char shm_open ();
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
return shm_open ();
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_ACEOF
|
||||||
|
for ac_lib in '' rt; do
|
||||||
|
if test -z "$ac_lib"; then
|
||||||
|
ac_res="none required"
|
||||||
|
else
|
||||||
|
ac_res=-l$ac_lib
|
||||||
|
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
|
||||||
|
fi
|
||||||
|
if ac_fn_c_try_link "$LINENO"; then :
|
||||||
|
ac_cv_search_shm_open=$ac_res
|
||||||
|
fi
|
||||||
|
rm -f core conftest.err conftest.$ac_objext \
|
||||||
|
conftest$ac_exeext
|
||||||
|
if ${ac_cv_search_shm_open+:} false; then :
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if ${ac_cv_search_shm_open+:} false; then :
|
||||||
|
|
||||||
|
else
|
||||||
|
ac_cv_search_shm_open=no
|
||||||
|
fi
|
||||||
|
rm conftest.$ac_ext
|
||||||
|
LIBS=$ac_func_search_save_LIBS
|
||||||
|
fi
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_shm_open" >&5
|
||||||
|
$as_echo "$ac_cv_search_shm_open" >&6; }
|
||||||
|
ac_res=$ac_cv_search_shm_open
|
||||||
|
if test "$ac_res" != no; then :
|
||||||
|
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
|
||||||
|
|
||||||
|
else
|
||||||
|
as_fn_error $? "shm_open() not found" "$LINENO" 5
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
# Support using libudev or libblkid for UUID lookup
|
# Support using libudev or libblkid for UUID lookup
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing udev_new" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing udev_new" >&5
|
||||||
$as_echo_n "checking for library containing udev_new... " >&6; }
|
$as_echo_n "checking for library containing udev_new... " >&6; }
|
||||||
@ -5960,6 +6072,10 @@ done
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -6011,6 +6127,15 @@ $as_echo "#define HAVE_SHLOBJ_H /**/" >>confdefs.h
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
ac_fn_c_check_header_compile "$LINENO" "direct.h" "ac_cv_header_direct_h" "#include <windows.h>
|
||||||
|
"
|
||||||
|
if test "x$ac_cv_header_direct_h" = xyes; then :
|
||||||
|
|
||||||
|
$as_echo "#define HAVE_DIRECT_H /**/" >>confdefs.h
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
# Checks for functions.
|
# Checks for functions.
|
||||||
for ac_func in vprintf
|
for ac_func in vprintf
|
||||||
do :
|
do :
|
||||||
@ -6031,32 +6156,18 @@ fi
|
|||||||
done
|
done
|
||||||
|
|
||||||
|
|
||||||
for ac_func in setlocale getmntent getmntent_r getfsstat
|
|
||||||
do :
|
ac_fn_c_check_decl "$LINENO" "localtime_r" "ac_cv_have_decl_localtime_r" "$ac_includes_default
|
||||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
#include <pthread.h>
|
||||||
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
#include <time.h>
|
||||||
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
|
"
|
||||||
cat >>confdefs.h <<_ACEOF
|
if test "x$ac_cv_have_decl_localtime_r" = xyes; then :
|
||||||
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
|
|
||||||
_ACEOF
|
$as_echo "#define HAVE_LOCALTIME_R /**/" >>confdefs.h
|
||||||
|
|
||||||
fi
|
fi
|
||||||
done
|
|
||||||
|
|
||||||
|
|
||||||
ac_fn_c_check_func "$LINENO" "getline" "ac_cv_func_getline"
|
|
||||||
if test "x$ac_cv_func_getline" = xyes; then :
|
|
||||||
$as_echo "#define HAVE_GETLINE 1" >>confdefs.h
|
|
||||||
|
|
||||||
else
|
|
||||||
case " $LIBOBJS " in
|
|
||||||
*" getline.$ac_objext "* ) ;;
|
|
||||||
*) LIBOBJS="$LIBOBJS getline.$ac_objext"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday"
|
ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday"
|
||||||
if test "x$ac_cv_func_gettimeofday" = xyes; then :
|
if test "x$ac_cv_func_gettimeofday" = xyes; then :
|
||||||
$as_echo "#define HAVE_GETTIMEOFDAY 1" >>confdefs.h
|
$as_echo "#define HAVE_GETTIMEOFDAY 1" >>confdefs.h
|
||||||
@ -6070,6 +6181,19 @@ esac
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
ac_fn_c_check_func "$LINENO" "getline" "ac_cv_func_getline"
|
||||||
|
if test "x$ac_cv_func_getline" = xyes; then :
|
||||||
|
$as_echo "#define HAVE_GETLINE 1" >>confdefs.h
|
||||||
|
|
||||||
|
else
|
||||||
|
case " $LIBOBJS " in
|
||||||
|
*" getline.$ac_objext "* ) ;;
|
||||||
|
*) LIBOBJS="$LIBOBJS getline.$ac_objext"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
ac_fn_c_check_func "$LINENO" "getuid" "ac_cv_func_getuid"
|
ac_fn_c_check_func "$LINENO" "getuid" "ac_cv_func_getuid"
|
||||||
if test "x$ac_cv_func_getuid" = xyes; then :
|
if test "x$ac_cv_func_getuid" = xyes; then :
|
||||||
$as_echo "#define HAVE_GETUID 1" >>confdefs.h
|
$as_echo "#define HAVE_GETUID 1" >>confdefs.h
|
||||||
@ -6083,19 +6207,6 @@ esac
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ac_fn_c_check_func "$LINENO" "localtime_r" "ac_cv_func_localtime_r"
|
|
||||||
if test "x$ac_cv_func_localtime_r" = xyes; then :
|
|
||||||
$as_echo "#define HAVE_LOCALTIME_R 1" >>confdefs.h
|
|
||||||
|
|
||||||
else
|
|
||||||
case " $LIBOBJS " in
|
|
||||||
*" localtime_r.$ac_objext "* ) ;;
|
|
||||||
*) LIBOBJS="$LIBOBJS localtime_r.$ac_objext"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
ac_fn_c_check_func "$LINENO" "pipe" "ac_cv_func_pipe"
|
ac_fn_c_check_func "$LINENO" "pipe" "ac_cv_func_pipe"
|
||||||
if test "x$ac_cv_func_pipe" = xyes; then :
|
if test "x$ac_cv_func_pipe" = xyes; then :
|
||||||
$as_echo "#define HAVE_PIPE 1" >>confdefs.h
|
$as_echo "#define HAVE_PIPE 1" >>confdefs.h
|
||||||
@ -6163,6 +6274,19 @@ fi
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for ac_func in setlocale getmntent getmntent_r getfsstat
|
||||||
|
do :
|
||||||
|
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||||
|
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
||||||
|
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
|
||||||
|
cat >>confdefs.h <<_ACEOF
|
||||||
|
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
|
||||||
|
_ACEOF
|
||||||
|
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
ac_config_files="$ac_config_files Makefile src/Makefile doc/Makefile scripts/Makefile"
|
ac_config_files="$ac_config_files Makefile src/Makefile doc/Makefile scripts/Makefile"
|
||||||
|
|
||||||
|
|
||||||
@ -6700,7 +6824,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
|||||||
# report actual input values of CONFIG_FILES etc. instead of their
|
# report actual input values of CONFIG_FILES etc. instead of their
|
||||||
# values after options handling.
|
# values after options handling.
|
||||||
ac_log="
|
ac_log="
|
||||||
This file was extended by vchanger $as_me 1.0.1, which was
|
This file was extended by vchanger $as_me 1.0.3, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
CONFIG_FILES = $CONFIG_FILES
|
CONFIG_FILES = $CONFIG_FILES
|
||||||
@ -6766,7 +6890,7 @@ _ACEOF
|
|||||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||||
ac_cs_version="\\
|
ac_cs_version="\\
|
||||||
vchanger config.status 1.0.1
|
vchanger config.status 1.0.3
|
||||||
configured by $0, generated by GNU Autoconf 2.69,
|
configured by $0, generated by GNU Autoconf 2.69,
|
||||||
with options \\"\$ac_cs_config\\"
|
with options \\"\$ac_cs_config\\"
|
||||||
|
|
||||||
|
27
configure.ac
27
configure.ac
@ -1,9 +1,9 @@
|
|||||||
# -*- Autoconf -*-
|
# -*- Autoconf -*-
|
||||||
# Process this file with autoconf to produce a configure script.
|
# Process this file with autoconf to produce a configure script.
|
||||||
|
|
||||||
AC_PREREQ([2.63])
|
AC_PREREQ([2.69])
|
||||||
AC_INIT([vchanger], [1.0.1], [jfisher@jaybus.com])
|
AC_INIT([vchanger], [1.0.3], [jfisher@jaybus.com])
|
||||||
AC_DEFINE([COPYRIGHT_NOTICE],["AC_PACKAGE_NAME Copyright (c) 2006-2015 Josh Fisher"],[Copyright notice])
|
AC_DEFINE([COPYRIGHT_NOTICE],["AC_PACKAGE_NAME Copyright (c) 2006-2020 Josh Fisher"],[Copyright notice])
|
||||||
AC_CONFIG_SRCDIR([src])
|
AC_CONFIG_SRCDIR([src])
|
||||||
AC_CONFIG_LIBOBJ_DIR([src/compat])
|
AC_CONFIG_LIBOBJ_DIR([src/compat])
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
@ -34,6 +34,9 @@ AC_SYS_LARGEFILE
|
|||||||
|
|
||||||
# Use multithreading
|
# Use multithreading
|
||||||
AC_SEARCH_LIBS([pthread_create], [pthread], [], [AC_MSG_ERROR(["could not find libpthread"])])
|
AC_SEARCH_LIBS([pthread_create], [pthread], [], [AC_MSG_ERROR(["could not find libpthread"])])
|
||||||
|
AC_CHECK_HEADER([sys/mman.h],
|
||||||
|
[ AC_SEARCH_LIBS([shm_open],[rt],[],[AC_MSG_ERROR([shm_open() not found])])
|
||||||
|
])
|
||||||
# Support using libudev or libblkid for UUID lookup
|
# Support using libudev or libblkid for UUID lookup
|
||||||
AC_SEARCH_LIBS([udev_new],[udev],[AC_CHECK_HEADERS([libudev.h])])
|
AC_SEARCH_LIBS([udev_new],[udev],[AC_CHECK_HEADERS([libudev.h])])
|
||||||
AC_CHECK_HEADER([blkid/blkid.h],
|
AC_CHECK_HEADER([blkid/blkid.h],
|
||||||
@ -50,21 +53,27 @@ AC_CHECK_HEADERS_ONCE([stdio.h stdlib.h string.h stdarg.h stddef.h])
|
|||||||
AC_CHECK_HEADERS_ONCE([time.h sys/time.h sys/timespec.h sys/wait.h limits.h locale.h syslog.h])
|
AC_CHECK_HEADERS_ONCE([time.h sys/time.h sys/timespec.h sys/wait.h limits.h locale.h syslog.h])
|
||||||
AC_CHECK_HEADERS_ONCE([sys/types.h strings.h alloca.h sys/bitypes.h getopt.h utime.h sys/stat.h])
|
AC_CHECK_HEADERS_ONCE([sys/types.h strings.h alloca.h sys/bitypes.h getopt.h utime.h sys/stat.h])
|
||||||
AC_CHECK_HEADERS_ONCE([inttypes.h ctype.h errno.h unistd.h varargs.h mntent.h])
|
AC_CHECK_HEADERS_ONCE([inttypes.h ctype.h errno.h unistd.h varargs.h mntent.h])
|
||||||
AC_CHECK_HEADERS_ONCE([sys/param.h sys/mount.h sys/ucred.h grp.h pwd.h dirent.h fcntl.h])
|
AC_CHECK_HEADERS_ONCE([sys/param.h sys/mount.h sys/ucred.h grp.h pwd.h dirent.h fcntl.h sys/mman.h])
|
||||||
AC_CHECK_HEADERS_ONCE([sys/select.h optarg.h pthread.h libgen.h io.h signal.h])
|
AC_CHECK_HEADERS_ONCE([sys/select.h optarg.h pthread.h libgen.h io.h signal.h semaphore.h])
|
||||||
AC_CHECK_HEADER([windows.h],
|
AC_CHECK_HEADER([windows.h], [AC_DEFINE([HAVE_WINDOWS_H],,[have header windows.h])
|
||||||
[AC_DEFINE([HAVE_WINDOWS_H],,[have header windows.h])
|
|
||||||
WINLDADD=-static])
|
WINLDADD=-static])
|
||||||
AC_SUBST(WINLDADD)
|
AC_SUBST(WINLDADD)
|
||||||
AC_CHECK_HEADER([winioctl.h], [AC_DEFINE([HAVE_WINIOCTL_H],,[have header winioctl.h])], [], [#include <windows.h>])
|
AC_CHECK_HEADER([winioctl.h], [AC_DEFINE([HAVE_WINIOCTL_H],,[have header winioctl.h])], [], [#include <windows.h>])
|
||||||
AC_CHECK_HEADER([winsock.h], [AC_DEFINE([HAVE_WINSOCK_H],,[have header winsock.h])], [], [#include <windows.h>])
|
AC_CHECK_HEADER([winsock.h], [AC_DEFINE([HAVE_WINSOCK_H],,[have header winsock.h])], [], [#include <windows.h>])
|
||||||
AC_CHECK_HEADER([winreg.h], [AC_DEFINE([HAVE_WINREG_H],,[have header winreg.h])], [], [#include <windows.h>])
|
AC_CHECK_HEADER([winreg.h], [AC_DEFINE([HAVE_WINREG_H],,[have header winreg.h])], [], [#include <windows.h>])
|
||||||
AC_CHECK_HEADER([shlobj.h], [AC_DEFINE([HAVE_SHLOBJ_H],,[have header shlobj.h])], [], [#include <windows.h>])
|
AC_CHECK_HEADER([shlobj.h], [AC_DEFINE([HAVE_SHLOBJ_H],,[have header shlobj.h])], [], [#include <windows.h>])
|
||||||
|
AC_CHECK_HEADER([direct.h], [AC_DEFINE([HAVE_DIRECT_H],,[have header direct.h])], [], [#include <windows.h>])
|
||||||
# Checks for functions.
|
# Checks for functions.
|
||||||
AC_FUNC_VPRINTF
|
AC_FUNC_VPRINTF
|
||||||
AC_CHECK_FUNCS([setlocale getmntent getmntent_r getfsstat])
|
|
||||||
|
|
||||||
AC_REPLACE_FUNCS([getline gettimeofday getuid localtime_r pipe readlink sleep symlink syslog])
|
AC_CHECK_DECL([localtime_r], [AC_DEFINE([HAVE_LOCALTIME_R],,[have function localtime_r])], [],
|
||||||
|
[AC_INCLUDES_DEFAULT
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <time.h>])
|
||||||
|
|
||||||
|
AC_REPLACE_FUNCS([gettimeofday getline getuid pipe readlink sleep symlink syslog])
|
||||||
|
|
||||||
|
AC_CHECK_FUNCS([setlocale getmntent getmntent_r getfsstat])
|
||||||
|
|
||||||
AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile scripts/Makefile])
|
AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile scripts/Makefile])
|
||||||
|
|
||||||
|
5
contrib/vchanger.logrotate
Normal file
5
contrib/vchanger.logrotate
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
/var/log/vchanger/*.log {
|
||||||
|
missingok
|
||||||
|
notifempty
|
||||||
|
sharedscripts
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
# This file contains udev rules for automounting drives assigned to vchanger
|
# This file contains example udev rules for automounting filesystems assigned to vchanger
|
||||||
|
# See vchangerHowto.html for details on generating udev rules for vchanger magazines.
|
||||||
#
|
#
|
||||||
# Rules for magazine 0 (uuid:7b4526c4-d8e9-48ba-b227-f67f855a0dc7)
|
# Rules for magazine 0 (uuid:7b4526c4-d8e9-48ba-b227-f67f855a0dc7)
|
||||||
ACTION=="add",SUBSYSTEM=="block", ENV{ID_FS_UUID}=="7b4526c4-d8e9-48ba-b227-f67f855a0dc7", RUN+="/usr/libexec/vchanger/vchanger-launch-mount.sh 7b4526c4-d8e9-48ba-b227-f67f855a0dc7"
|
ACTION=="add",SUBSYSTEM=="block", ENV{ID_FS_UUID}=="7b4526c4-d8e9-48ba-b227-f67f855a0dc7", RUN+="/usr/libexec/vchanger/vchanger-launch-mount.sh 7b4526c4-d8e9-48ba-b227-f67f855a0dc7"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Example vchanger 1.0.0 config file
|
# Example vchanger 1.0.2 config file
|
||||||
|
|
||||||
#
|
#
|
||||||
# Storage Resource Name of the Storage resource defined in bacula-dir.conf
|
# Storage Resource Name of the Storage resource defined in bacula-dir.conf
|
||||||
@ -10,27 +10,27 @@
|
|||||||
# User User to run as when invoked by root. This must be the
|
# User User to run as when invoked by root. This must be the
|
||||||
# owner of the volume files controlled by this changer, and
|
# owner of the volume files controlled by this changer, and
|
||||||
# so will need to be the same user that bacula-sd runs as.
|
# so will need to be the same user that bacula-sd runs as.
|
||||||
# [Default: none ]
|
# [Default: bacula ]
|
||||||
User = bacula
|
#User = bacula
|
||||||
|
|
||||||
#
|
#
|
||||||
# Group Group to run as when invoked by root. This should be the
|
# Group Group to run as when invoked by root. This should be the
|
||||||
# owner group of the volume files controlled by this changer,
|
# owner group of the volume files controlled by this changer,
|
||||||
# and should also be the default group pf the user that
|
# and should also be the default group of the user that
|
||||||
# bacula-sd runs as.
|
# bacula-sd runs as.
|
||||||
# [Default: none ]
|
# [Default: tape ]
|
||||||
group = tape
|
#group = tape
|
||||||
|
|
||||||
#
|
#
|
||||||
# Work Dir Directory where virtual drive and magazine state information
|
# Work Dir Directory where virtual drive and magazine state information
|
||||||
# and symlinks for this changer are stored.
|
# and symlinks for this changer are stored.
|
||||||
# [Default: /var/spool/vchanger/[StorageResource] ]
|
# [Default: /var/spool/vchanger/{StorageResource} ]
|
||||||
#work dir = "/var/spool/vchanger/vcahnger"
|
#work dir = "/var/spool/vchanger/vcahnger"
|
||||||
|
|
||||||
#
|
#
|
||||||
# Logfile Path to log file for this changer.
|
# Logfile Path to log file for this changer.
|
||||||
# [Default: /var/log/vchanger/[StorageResource].log ]
|
# [Default: {WorkDir}/{StorageResource}.log ]
|
||||||
#logfile = "/var/log/vchanger/vchanger.log"
|
#logfile = "/var/spool/vchanger/vchanger.log"
|
||||||
|
|
||||||
#
|
#
|
||||||
# Log Level Sets the level of detail being logged. An integer value from
|
# Log Level Sets the level of detail being logged. An integer value from
|
||||||
@ -50,7 +50,8 @@ group = tape
|
|||||||
#
|
#
|
||||||
# bconsole config Path to the config file bconsole will use when vchanger
|
# bconsole config Path to the config file bconsole will use when vchanger
|
||||||
# invokes bconsole. By default, bconsole will be invoked
|
# invokes bconsole. By default, bconsole will be invoked
|
||||||
# without the -c flag.
|
# without the -c flag. The file must be readable by the user
|
||||||
|
# vchanger is run as.
|
||||||
# [Default: none ]
|
# [Default: none ]
|
||||||
#bconsole config = /etc/bacula/bconsole.conf
|
#bconsole config = /etc/bacula/bconsole.conf
|
||||||
|
|
||||||
@ -69,7 +70,9 @@ group = tape
|
|||||||
# by prefixing the string "UUID:" to the filesystem's UUID.
|
# by prefixing the string "UUID:" to the filesystem's UUID.
|
||||||
# For magazines specified by UUID, the mountpoint of the
|
# For magazines specified by UUID, the mountpoint of the
|
||||||
# filesystem will be queried from the system. Note that vchanger
|
# filesystem will be queried from the system. Note that vchanger
|
||||||
# does not attempt to mount the filesystem.
|
# does not attempt to mount the magazines that are specified
|
||||||
|
# by filesystem UUID. Vchanger utilizes all magazines that are
|
||||||
|
# already mounted at the time it is invoked.
|
||||||
# [Default: none ]
|
# [Default: none ]
|
||||||
#magazine = "uuid:4fcb1422-f15c-4d7a-8a32-a4dcc0af5e00"
|
#magazine = "uuid:4fcb1422-f15c-4d7a-8a32-a4dcc0af5e00"
|
||||||
#Magazine = "/mnt/backup2"
|
#Magazine = "/mnt/backup2"
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
.\" Title: vchanger
|
.\" Title: vchanger
|
||||||
.\" Author: Josh Fisher <jfisher@jaybus.com>
|
.\" Author: Josh Fisher <jfisher@jaybus.com>
|
||||||
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
|
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
|
||||||
.\" Date: 06/03/2015
|
.\" Date: 05/11/2020
|
||||||
.\" Manual: vchanger Manual
|
.\" Manual: vchanger Manual
|
||||||
.\" Source: vchanger 1.0.1
|
.\" Source: vchanger 1.0.3
|
||||||
.\" Language: English
|
.\" Language: English
|
||||||
.\"
|
.\"
|
||||||
.TH "VCHANGER" "8" "06/03/2015" "vchanger 1\&.0\&.1" "vchanger Manual"
|
.TH "VCHANGER" "8" "05/11/2020" "vchanger 1\&.0\&.3" "vchanger Manual"
|
||||||
.\" -----------------------------------------------------------------
|
.\" -----------------------------------------------------------------
|
||||||
.\" * Define some portability stuff
|
.\" * Define some portability stuff
|
||||||
.\" -----------------------------------------------------------------
|
.\" -----------------------------------------------------------------
|
||||||
@ -40,7 +40,7 @@ vchanger \- Virtual disk\-based autochanger for Bacula network backup system
|
|||||||
\fBvchanger\fR [\fIOptions\fR] config REFRESH
|
\fBvchanger\fR [\fIOptions\fR] config REFRESH
|
||||||
.SH "DESCRIPTION"
|
.SH "DESCRIPTION"
|
||||||
.sp
|
.sp
|
||||||
The \fBvchanger(8)\fR utility is used to emulate and control a virtual autochanger within the Bacula network backup system environment\&. Backup volumes stored on multiple disk filesystems are mapped to a single set of virtual slots, allowing an unlimited number of virtual drives for concurrent backup jobs and easy, unlimited scaling to any size by simply adding additional disks/filesystems,
|
The \fBvchanger(8)\fR utility is used to emulate and control a virtual autochanger within the Bacula network backup system environment\&. Backup volumes stored on multiple disk filesystems are mapped to a single set of virtual slots\&. This allows an unlimited number of virtual drives and an unlimited number of virtual slots spread across an unlimited number of physical disk drives to be assigned to a single autochanger\&. This allows unlimited scaling of the cirtual autochanger simply by adding additional disk drives\&.
|
||||||
.sp
|
.sp
|
||||||
Vchanger is primarily deigned for use with removable disk drives\&. Its ability to interact with Bacula and determine removable drive mount points through udev allow for plug\-n\-play operation when attaching and detaching removable disk drives\&.
|
Vchanger is primarily deigned for use with removable disk drives\&. Its ability to interact with Bacula and determine removable drive mount points through udev allow for plug\-n\-play operation when attaching and detaching removable disk drives\&.
|
||||||
.sp
|
.sp
|
||||||
@ -142,9 +142,9 @@ command to Bacula if required\&.
|
|||||||
.sp
|
.sp
|
||||||
\fBBacula Interaction\fR
|
\fBBacula Interaction\fR
|
||||||
.sp
|
.sp
|
||||||
By default, vcahgner will invoke bconsole and issue commands to Bacula when certain operator actions are needed\&. When anything happens that changes the current set of volume files being used, vchanger will invoke bconsole and issue an \fIupdate slots\fR command\&. For example, when the operator attaches a removable drive defined as one of the changer\(cqs magazines, the volume files on the removable drive must be mapped to virtual slots\&. Since the volume\-to\-slot mapping will have changed, Bacula will need to be informed of the change via the \fIupdate slots\fR command\&. The \fBREFRESH\fR command can be invoked to force vchanger to update state info and trigger \fIupdate slots\fR if needed\&.
|
By default, vcahgner will invoke bconsole and issue commands to Bacula when certain operator actions are needed\&. When anything happens that changes the current set of volume files being used, (the virtual slot to volume file mapping), vchanger will invoke bconsole and issue an \fIupdate slots\fR command\&. For example, when the operator attaches a removable drive defined as one of the changer\(cqs magazines, the volume files on the removable drive must be mapped to virtual slots\&. Since the slot\-to\-volume mapping will have changed, Bacula will need to be informed of the change via the \fIupdate slots\fR command\&. The \fBREFRESH\fR command can be invoked to force vchanger to update state info and trigger \fIupdate slots\fR if needed\&.
|
||||||
.sp
|
.sp
|
||||||
Additionally, when new volumes are created with the \fBCREATEVOLS\fR command, vchanger will invoke bconsole and issue a \fIlabel barcodes\fR command to write volume labels on the newly created volume files\&.
|
Additionally, when new volumes are created with the \fBCREATEVOLS\fR command, vchanger will invoke bconsole and issue a \fIlabel barcodes\fR command to allow Bacula to write volume labels on the newly created volume files\&.
|
||||||
.SH "COMMAND LINE OPTIONS"
|
.SH "COMMAND LINE OPTIONS"
|
||||||
.PP
|
.PP
|
||||||
\fB\-u, \-\-user\fR=\fIuid\fR
|
\fB\-u, \-\-user\fR=\fIuid\fR
|
||||||
@ -195,7 +195,7 @@ See the vchangerHowto\&.html file included in the doc directory of the source di
|
|||||||
\fBvchanger\&.conf(5)\fR
|
\fBvchanger\&.conf(5)\fR
|
||||||
.SH "COPYRIGHT"
|
.SH "COPYRIGHT"
|
||||||
.sp
|
.sp
|
||||||
Copyright 2006\-2015 Josh Fisher
|
Copyright 2006\-2020 Josh Fisher
|
||||||
.sp
|
.sp
|
||||||
This is free software; See the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&.
|
This is free software; See the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&.
|
||||||
.SH "AUTHOR"
|
.SH "AUTHOR"
|
||||||
|
@ -3,7 +3,7 @@ VCHANGER(8)
|
|||||||
Josh Fisher <jfisher@jaybus.com>
|
Josh Fisher <jfisher@jaybus.com>
|
||||||
:doctype: manpage
|
:doctype: manpage
|
||||||
:man source: vchanger
|
:man source: vchanger
|
||||||
:man version: 1.0.1
|
:man version: 1.0.3
|
||||||
:man manual: vchanger Manual
|
:man manual: vchanger Manual
|
||||||
|
|
||||||
NAME
|
NAME
|
||||||
@ -27,9 +27,11 @@ DESCRIPTION
|
|||||||
The *vchanger(8)* utility is used to emulate and control a virtual
|
The *vchanger(8)* utility is used to emulate and control a virtual
|
||||||
autochanger within the Bacula network backup system environment.
|
autochanger within the Bacula network backup system environment.
|
||||||
Backup volumes stored on multiple disk filesystems are mapped to a
|
Backup volumes stored on multiple disk filesystems are mapped to a
|
||||||
single set of virtual slots, allowing an unlimited number of virtual
|
single set of virtual slots. This allows an unlimited number of
|
||||||
drives for concurrent backup jobs and easy, unlimited scaling to any
|
virtual drives and an unlimited number of virtual slots spread
|
||||||
size by simply adding additional disks/filesystems,
|
across an unlimited number of physical disk drives to be assigned
|
||||||
|
to a single autochanger. This allows unlimited scaling of the cirtual
|
||||||
|
autochanger simply by adding additional disk drives.
|
||||||
|
|
||||||
Vchanger is primarily deigned for use with removable disk drives. Its
|
Vchanger is primarily deigned for use with removable disk drives. Its
|
||||||
ability to interact with Bacula and determine removable drive mount
|
ability to interact with Bacula and determine removable drive mount
|
||||||
@ -115,18 +117,19 @@ Additionally, the following extended commands are supported.
|
|||||||
|
|
||||||
By default, vcahgner will invoke bconsole and issue commands to Bacula
|
By default, vcahgner will invoke bconsole and issue commands to Bacula
|
||||||
when certain operator actions are needed. When anything happens that
|
when certain operator actions are needed. When anything happens that
|
||||||
changes the current set of volume files being used, vchanger will
|
changes the current set of volume files being used, (the virtual slot
|
||||||
invoke bconsole and issue an 'update slots' command. For example,
|
to volume file mapping), vchanger will invoke bconsole and issue an
|
||||||
when the operator attaches a removable drive defined as one of the
|
'update slots' command. For example, when the operator attaches a
|
||||||
changer's magazines, the volume files on the removable drive must be
|
removable drive defined as one of the changer's magazines, the volume
|
||||||
mapped to virtual slots. Since the volume-to-slot mapping will have
|
files on the removable drive must be mapped to virtual slots. Since
|
||||||
changed, Bacula will need to be informed of the change via the
|
the slot-to-volume mapping will have changed, Bacula will need to be
|
||||||
'update slots' command. The *REFRESH* command can be invoked to force
|
informed of the change via the 'update slots' command. The *REFRESH*
|
||||||
vchanger to update state info and trigger 'update slots' if needed.
|
command can be invoked to force vchanger to update state info and
|
||||||
|
trigger 'update slots' if needed.
|
||||||
|
|
||||||
Additionally, when new volumes are created with the *CREATEVOLS* command,
|
Additionally, when new volumes are created with the *CREATEVOLS* command,
|
||||||
vchanger will invoke bconsole and issue a 'label barcodes' command to
|
vchanger will invoke bconsole and issue a 'label barcodes' command to
|
||||||
write volume labels on the newly created volume files.
|
allow Bacula to write volume labels on the newly created volume files.
|
||||||
|
|
||||||
COMMAND LINE OPTIONS
|
COMMAND LINE OPTIONS
|
||||||
--------------------
|
--------------------
|
||||||
@ -172,7 +175,7 @@ SEE ALSO
|
|||||||
|
|
||||||
COPYRIGHT
|
COPYRIGHT
|
||||||
---------
|
---------
|
||||||
Copyright 2006-2015 Josh Fisher
|
Copyright 2006-2020 Josh Fisher
|
||||||
|
|
||||||
This is free software;
|
This is free software;
|
||||||
See the source for copying conditions.
|
See the source for copying conditions.
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
.\" Title: vchanger.conf
|
.\" Title: vchanger.conf
|
||||||
.\" Author: Josh Fisher <jfisher@jaybus.com>
|
.\" Author: Josh Fisher <jfisher@jaybus.com>
|
||||||
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
|
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
|
||||||
.\" Date: 06/03/2015
|
.\" Date: 05/11/2020
|
||||||
.\" Manual: vchanger Manual
|
.\" Manual: vchanger Manual
|
||||||
.\" Source: vchanger.conf 1.0.1
|
.\" Source: vchanger.conf 1.0.3
|
||||||
.\" Language: English
|
.\" Language: English
|
||||||
.\"
|
.\"
|
||||||
.TH "VCHANGER\&.CONF" "5" "06/03/2015" "vchanger\&.conf 1\&.0\&.1" "vchanger Manual"
|
.TH "VCHANGER\&.CONF" "5" "05/11/2020" "vchanger\&.conf 1\&.0\&.3" "vchanger Manual"
|
||||||
.\" -----------------------------------------------------------------
|
.\" -----------------------------------------------------------------
|
||||||
.\" * Define some portability stuff
|
.\" * Define some portability stuff
|
||||||
.\" -----------------------------------------------------------------
|
.\" -----------------------------------------------------------------
|
||||||
@ -134,7 +134,7 @@ See the vchangerHowto\&.html file included in the doc directory of the source di
|
|||||||
\fBvchanger(8)\fR
|
\fBvchanger(8)\fR
|
||||||
.SH "COPYRIGHT"
|
.SH "COPYRIGHT"
|
||||||
.sp
|
.sp
|
||||||
Copyright 2006\-2015 Josh Fisher
|
Copyright 2006\-2020 Josh Fisher
|
||||||
.sp
|
.sp
|
||||||
This is free software; See the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&.
|
This is free software; See the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&.
|
||||||
.SH "AUTHOR"
|
.SH "AUTHOR"
|
||||||
|
@ -3,7 +3,7 @@ VCHANGER.CONF(5)
|
|||||||
Josh Fisher <jfisher@jaybus.com>
|
Josh Fisher <jfisher@jaybus.com>
|
||||||
:doctype: manpage
|
:doctype: manpage
|
||||||
:man source: vchanger.conf
|
:man source: vchanger.conf
|
||||||
:man version: 1.0.1
|
:man version: 1.0.3
|
||||||
:man manual: vchanger Manual
|
:man manual: vchanger Manual
|
||||||
|
|
||||||
NAME
|
NAME
|
||||||
@ -112,7 +112,7 @@ SEE ALSO
|
|||||||
|
|
||||||
COPYRIGHT
|
COPYRIGHT
|
||||||
---------
|
---------
|
||||||
Copyright 2006-2015 Josh Fisher
|
Copyright 2006-2020 Josh Fisher
|
||||||
|
|
||||||
This is free software;
|
This is free software;
|
||||||
See the source for copying conditions.
|
See the source for copying conditions.
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -3,8 +3,8 @@
|
|||||||
#
|
#
|
||||||
Summary: A virtual autochanger for Bacula
|
Summary: A virtual autochanger for Bacula
|
||||||
Name: vchanger
|
Name: vchanger
|
||||||
Version: 1.0.1
|
Version: 1.0.3
|
||||||
Release: 1.el6
|
Release: 1%{dist}
|
||||||
License: GPLv2
|
License: GPLv2
|
||||||
Group: System Environment/Daemons
|
Group: System Environment/Daemons
|
||||||
Source: http://sourceforge.net/projects/vchanger/files/vchanger/%{version}/vchanger-%{version}.tar.gz
|
Source: http://sourceforge.net/projects/vchanger/files/vchanger/%{version}/vchanger-%{version}.tar.gz
|
||||||
@ -35,6 +35,7 @@ make
|
|||||||
rm -rf $RPM_BUILD_ROOT
|
rm -rf $RPM_BUILD_ROOT
|
||||||
mkdir -p ${RPM_BUILD_ROOT}%{_bindir}
|
mkdir -p ${RPM_BUILD_ROOT}%{_bindir}
|
||||||
mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig
|
mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig
|
||||||
|
mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d
|
||||||
mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}
|
mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}
|
||||||
mkdir -p ${RPM_BUILD_ROOT}%{_libexecdir}/%{name}
|
mkdir -p ${RPM_BUILD_ROOT}%{_libexecdir}/%{name}
|
||||||
mkdir -p ${RPM_BUILD_ROOT}%{_mandir}/man5
|
mkdir -p ${RPM_BUILD_ROOT}%{_mandir}/man5
|
||||||
@ -44,6 +45,7 @@ mkdir -m 0770 -p ${RPM_BUILD_ROOT}%{_localstatedir}/spool/%{name}
|
|||||||
mkdir -m 0755 -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}
|
mkdir -m 0755 -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}
|
||||||
make DESTDIR=${RPM_BUILD_ROOT} install-strip
|
make DESTDIR=${RPM_BUILD_ROOT} install-strip
|
||||||
install -m 0644 scripts/vchanger.default ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig/vchanger
|
install -m 0644 scripts/vchanger.default ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig/vchanger
|
||||||
|
install -m 0644 contrib/vchanger.logrotate ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/vchanger
|
||||||
|
|
||||||
%clean
|
%clean
|
||||||
rm -rf $RPM_BUILD_ROOT
|
rm -rf $RPM_BUILD_ROOT
|
||||||
@ -52,6 +54,7 @@ rm -rf $RPM_BUILD_ROOT
|
|||||||
%defattr(-,root,root,-)
|
%defattr(-,root,root,-)
|
||||||
%{_bindir}/*
|
%{_bindir}/*
|
||||||
%{_libexecdir}/%{name}/*
|
%{_libexecdir}/%{name}/*
|
||||||
|
%{_sysconfdir}/logrotate.d/*
|
||||||
%doc %{_docdir}/%{name}-%{version}/AUTHORS
|
%doc %{_docdir}/%{name}-%{version}/AUTHORS
|
||||||
%doc %{_docdir}/%{name}-%{version}/ChangeLog
|
%doc %{_docdir}/%{name}-%{version}/ChangeLog
|
||||||
%doc %{_docdir}/%{name}-%{version}/COPYING
|
%doc %{_docdir}/%{name}-%{version}/COPYING
|
||||||
@ -85,6 +88,10 @@ if [ $1 -eq 1 ] ; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu May 6 2020 Josh Fisher <jfisher@jaybus.com>
|
||||||
|
- Updated to release 1.0.2
|
||||||
|
* Thu Jun 14 2018 Josh Fisher <jfisher@jaybus.com>
|
||||||
|
- Updated to release 1.0.2
|
||||||
* Wed Jun 3 2015 Josh Fisher <jfisher@jaybus.com>
|
* Wed Jun 3 2015 Josh Fisher <jfisher@jaybus.com>
|
||||||
- Updated to release 1.0.1
|
- Updated to release 1.0.1
|
||||||
* Fri Apr 3 2015 Josh Fisher <jfisher@jaybus.com>
|
* Fri Apr 3 2015 Josh Fisher <jfisher@jaybus.com>
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
#
|
#
|
||||||
Summary: A virtual autochanger for Bacula
|
Summary: A virtual autochanger for Bacula
|
||||||
Name: vchanger
|
Name: vchanger
|
||||||
Version: 1.0.1
|
Version: 1.0.3
|
||||||
Release: 1.el7
|
Release: 1%{dist}
|
||||||
License: GPLv2
|
License: GPLv2
|
||||||
Group: System Environment/Daemons
|
Group: System Environment/Daemons
|
||||||
Source: http://sourceforge.net/projects/vchanger/files/vchanger/%{version}/vchanger-%{version}.tar.gz
|
Source: http://sourceforge.net/projects/vchanger/files/vchanger/%{version}/vchanger-%{version}.tar.gz
|
||||||
@ -14,6 +14,9 @@ Packager: Josh Fisher <jfisher@jaybus.com>
|
|||||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||||
Requires(post): /bin/mkdir, /bin/chown, /usr/bin/getent, /usr/sbin/useradd, /usr/sbin/groupadd
|
Requires(post): /bin/mkdir, /bin/chown, /usr/bin/getent, /usr/sbin/useradd, /usr/sbin/groupadd
|
||||||
|
|
||||||
|
# For libudev support
|
||||||
|
BuildRequires: systemd-devel
|
||||||
|
|
||||||
%description
|
%description
|
||||||
Vchanger implements a virtual autochanger for use with the Bacula open source
|
Vchanger implements a virtual autochanger for use with the Bacula open source
|
||||||
network backup system. Vchanger emulates a magazine-based tape autoloader
|
network backup system. Vchanger emulates a magazine-based tape autoloader
|
||||||
@ -35,6 +38,7 @@ make
|
|||||||
rm -rf $RPM_BUILD_ROOT
|
rm -rf $RPM_BUILD_ROOT
|
||||||
mkdir -p ${RPM_BUILD_ROOT}%{_bindir}
|
mkdir -p ${RPM_BUILD_ROOT}%{_bindir}
|
||||||
mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig
|
mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig
|
||||||
|
mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d
|
||||||
mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}
|
mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}
|
||||||
mkdir -p ${RPM_BUILD_ROOT}%{_libexecdir}/%{name}
|
mkdir -p ${RPM_BUILD_ROOT}%{_libexecdir}/%{name}
|
||||||
mkdir -p ${RPM_BUILD_ROOT}%{_mandir}/man5
|
mkdir -p ${RPM_BUILD_ROOT}%{_mandir}/man5
|
||||||
@ -44,6 +48,7 @@ mkdir -m 0770 -p ${RPM_BUILD_ROOT}%{_localstatedir}/spool/%{name}
|
|||||||
mkdir -m 0755 -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}
|
mkdir -m 0755 -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}
|
||||||
make DESTDIR=${RPM_BUILD_ROOT} install-strip
|
make DESTDIR=${RPM_BUILD_ROOT} install-strip
|
||||||
install -m 0644 scripts/vchanger.default ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig/vchanger
|
install -m 0644 scripts/vchanger.default ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig/vchanger
|
||||||
|
install -m 0644 contrib/vchanger.logrotate ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/vchanger
|
||||||
|
|
||||||
%clean
|
%clean
|
||||||
rm -rf $RPM_BUILD_ROOT
|
rm -rf $RPM_BUILD_ROOT
|
||||||
@ -52,6 +57,7 @@ rm -rf $RPM_BUILD_ROOT
|
|||||||
%defattr(-,root,root,-)
|
%defattr(-,root,root,-)
|
||||||
%{_bindir}/*
|
%{_bindir}/*
|
||||||
%{_libexecdir}/%{name}/*
|
%{_libexecdir}/%{name}/*
|
||||||
|
%{_sysconfdir}/logrotate.d/*
|
||||||
%doc %{_docdir}/%{name}-%{version}/AUTHORS
|
%doc %{_docdir}/%{name}-%{version}/AUTHORS
|
||||||
%doc %{_docdir}/%{name}-%{version}/ChangeLog
|
%doc %{_docdir}/%{name}-%{version}/ChangeLog
|
||||||
%doc %{_docdir}/%{name}-%{version}/COPYING
|
%doc %{_docdir}/%{name}-%{version}/COPYING
|
||||||
@ -85,6 +91,10 @@ if [ $1 -eq 1 ] ; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu May 6 2020 Josh Fisher <jfisher@jaybus.com>
|
||||||
|
- Updated to release 1.0.2
|
||||||
|
* Thu Jun 14 2018 Josh Fisher <jfisher@jaybus.com>
|
||||||
|
- Updated to release 1.0.2
|
||||||
* Wed Jun 3 2015 Josh Fisher <jfisher@jaybus.com>
|
* Wed Jun 3 2015 Josh Fisher <jfisher@jaybus.com>
|
||||||
- Updated to release 1.0.1
|
- Updated to release 1.0.1
|
||||||
* Fri Apr 3 2015 Josh Fisher <jfisher@jaybus.com>
|
* Fri Apr 3 2015 Josh Fisher <jfisher@jaybus.com>
|
||||||
|
106
rpm/vchanger.f29.spec
Normal file
106
rpm/vchanger.f29.spec
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
#
|
||||||
|
# Spec file for vchanger - Fedora 29
|
||||||
|
#
|
||||||
|
|
||||||
|
%global debug_package %{nil}
|
||||||
|
|
||||||
|
Summary: A virtual autochanger for Bacula
|
||||||
|
Name: vchanger
|
||||||
|
Version: 1.0.3
|
||||||
|
Release: 1%{dist}
|
||||||
|
License: GPLv2
|
||||||
|
Group: System Environment/Daemons
|
||||||
|
Source: http://sourceforge.net/projects/vchanger/files/vchanger/%{version}/vchanger-%{version}.tar.gz
|
||||||
|
URL: http://vchanger.sourceforge.net
|
||||||
|
Vendor: Josh Fisher.
|
||||||
|
Packager: Josh Fisher <jfisher@jaybus.com>
|
||||||
|
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||||
|
Requires(post): /usr/bin/mkdir, /usr/bin/chown, /usr/bin/getent, /usr/sbin/useradd, /usr/sbin/groupadd
|
||||||
|
|
||||||
|
# For libudev support
|
||||||
|
BuildRequires: systemd-devel
|
||||||
|
|
||||||
|
%description
|
||||||
|
Vchanger implements a virtual autochanger for use with the Bacula open source
|
||||||
|
network backup system. Vchanger emulates a magazine-based tape autoloader
|
||||||
|
using disk file system mountpoints as virtual magazines and the files in
|
||||||
|
each virtual magazine as virtual tape volumes. Vchanger is primarily
|
||||||
|
designed to use an unlimited number of removable disk drives as an easily
|
||||||
|
scalable virtual autochanger and allow seamless removal of backups for
|
||||||
|
offsite storage.
|
||||||
|
|
||||||
|
%prep
|
||||||
|
%setup -q -n %{name}
|
||||||
|
|
||||||
|
%build
|
||||||
|
CFLAGS="%{optflags} -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE" \
|
||||||
|
%configure
|
||||||
|
make
|
||||||
|
|
||||||
|
%install
|
||||||
|
rm -rf $RPM_BUILD_ROOT
|
||||||
|
mkdir -p ${RPM_BUILD_ROOT}%{_bindir}
|
||||||
|
mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig
|
||||||
|
mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d
|
||||||
|
mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}
|
||||||
|
mkdir -p ${RPM_BUILD_ROOT}%{_libexecdir}/%{name}
|
||||||
|
mkdir -p ${RPM_BUILD_ROOT}%{_mandir}/man5
|
||||||
|
mkdir -p ${RPM_BUILD_ROOT}%{_mandir}/man8
|
||||||
|
mkdir -p ${RPM_BUILD_ROOT}%{_docdir}/%{name}-%{version}
|
||||||
|
mkdir -m 0770 -p ${RPM_BUILD_ROOT}%{_localstatedir}/spool/%{name}
|
||||||
|
mkdir -m 0755 -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}
|
||||||
|
make DESTDIR=${RPM_BUILD_ROOT} install-strip
|
||||||
|
install -m 0644 scripts/vchanger.default ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig/vchanger
|
||||||
|
install -m 0644 contrib/vchanger.logrotate ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/vchanger
|
||||||
|
|
||||||
|
%clean
|
||||||
|
rm -rf $RPM_BUILD_ROOT
|
||||||
|
|
||||||
|
%files
|
||||||
|
%defattr(-,root,root,-)
|
||||||
|
%{_bindir}/*
|
||||||
|
%{_libexecdir}/%{name}/*
|
||||||
|
%{_sysconfdir}/logrotate.d/*
|
||||||
|
%doc %{_docdir}/%{name}-%{version}/AUTHORS
|
||||||
|
%doc %{_docdir}/%{name}-%{version}/ChangeLog
|
||||||
|
%doc %{_docdir}/%{name}-%{version}/COPYING
|
||||||
|
%doc %{_docdir}/%{name}-%{version}/INSTALL
|
||||||
|
%doc %{_docdir}/%{name}-%{version}/NEWS
|
||||||
|
%doc %{_docdir}/%{name}-%{version}/README
|
||||||
|
%doc %{_docdir}/%{name}-%{version}/ReleaseNotes
|
||||||
|
%doc %{_docdir}/%{name}-%{version}/vchanger-example.conf
|
||||||
|
%doc %{_docdir}/%{name}-%{version}/example-vchanger-udev.rules
|
||||||
|
%doc %{_docdir}/%{name}-%{version}/vchangerHowto.html
|
||||||
|
%{_mandir}/man5/*
|
||||||
|
%{_mandir}/man8/*
|
||||||
|
%config(noreplace) %{_sysconfdir}/sysconfig/vchanger
|
||||||
|
|
||||||
|
%post
|
||||||
|
if [ $1 -eq 1 ] ; then
|
||||||
|
/usr/bin/getent group tape &>/dev/null || /usr/sbin/groupadd -r tape
|
||||||
|
/usr/bin/getent group bacula &>/dev/null || /usr/sbin/groupadd -r bacula
|
||||||
|
/usr/bin/getent passwd bacula &>/dev/null || /usr/sbin/useradd -r -g bacula -d %{_localstatedir}/spool/bacula -s /bin/bash bacula
|
||||||
|
if [ ! -d %{_localstatedir}/spool/vchanger ] ; then
|
||||||
|
/bin/mkdir -p -m 0770 %{_localstatedir}/spool/vchanger
|
||||||
|
/bin/chown bacula:tape %{_localstatedir}/spool/vchanger
|
||||||
|
fi
|
||||||
|
if [ ! -d %{_localstatedir}/log/vchanger ] ; then
|
||||||
|
/bin/mkdir -p -m 0755 %{_localstatedir}/log/vchanger
|
||||||
|
/bin/chown bacula:tape %{_localstatedir}/log/vchanger
|
||||||
|
fi
|
||||||
|
if [ ! -d %{_sysconfdir}/vchanger ] ; then
|
||||||
|
/bin/mkdir -p -m 0755 %{_sysconfdir}/vchanger
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
%changelog
|
||||||
|
* Thu May 6 2020 Josh Fisher <jfisher@jaybus.com>
|
||||||
|
- Updated to release 1.0.3
|
||||||
|
* Mon Dec 24 2018 Steven A. Falco <stevenfalco@gmail.com>
|
||||||
|
- Various changes for Fedora 29
|
||||||
|
* Thu Jun 14 2018 Josh Fisher <jfisher@jaybus.com>
|
||||||
|
- Updated to release 1.0.2
|
||||||
|
* Wed Jun 3 2015 Josh Fisher <jfisher@jaybus.com>
|
||||||
|
- Updated to release 1.0.1
|
||||||
|
* Fri Apr 3 2015 Josh Fisher <jfisher@jaybus.com>
|
||||||
|
- Initial spec file
|
@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
#
|
#
|
||||||
# vchanger-genudevrules ( vchanger v.1.0.1 ) 2015-06-03
|
# vchanger-genudevrules ( vchanger v.1.0.3 ) 2020-05-06
|
||||||
#
|
#
|
||||||
# Search all autochanger configuration files for magazines being defined
|
# Search all autochanger configuration files for magazines being defined
|
||||||
# by filesystem UUID and print to stdout the udev rules for launching
|
# by filesystem UUID and print to stdout the udev rules for launching
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
#
|
#
|
||||||
# vchanger-launch-mount.sh ( vchanger v.1.0.1 ) 2015-06-03
|
# vchanger-launch-mount.sh ( vchanger v.1.0.3 ) 2020-05-06
|
||||||
#
|
#
|
||||||
# This script is used to run the vchanger-mount-uuid.sh script in
|
# This script is used to run the vchanger-mount-uuid.sh script as
|
||||||
# another [background] process launched by the at command in order
|
# a detached process and immediately exit. This is to prevent delays
|
||||||
# to prevent delays when invoked by a udev rule.
|
# when invoked by a udev rule.
|
||||||
#
|
#
|
||||||
VCHANGER_MOUNT=/usr/libexec/vchanger/vchanger-mount-uuid.sh
|
VCHANGER_MOUNT=/usr/libexec/vchanger/vchanger-mount-uuid.sh
|
||||||
{
|
|
||||||
$VCHANGER_MOUNT $1
|
# For some reason, nohup doesn't work, but "at now" does. This may have to
|
||||||
} &
|
# do with cgroups.
|
||||||
|
#nohup $VCHANGER_MOUNT $1 </dev/null >/dev/null 2>&1 &
|
||||||
|
echo "$VCHANGER_MOUNT $1 </dev/null >/dev/null 2>&1" | at now
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
#
|
#
|
||||||
# vchanger-launch-umount.sh ( vchanger v.1.0.1 ) 2015-06-03
|
# vchanger-launch-umount.sh ( vchanger v.1.0.3 ) 2020-05-06
|
||||||
#
|
#
|
||||||
# This script is used to run the vchanger-umount-uuid.sh script in
|
# This script is used to run the vchanger-umount-uuid.sh script in
|
||||||
# another [background] process launched by the at command in order
|
# another [background] process launched by the at command in order
|
||||||
# to prevent delays when invoked by a udev rule.
|
# to prevent delays when invoked by a udev rule.
|
||||||
#
|
#
|
||||||
VCHANGER_UMOUNT=/usr/libexec/vchanger/vchanger-umount-uuid.sh
|
VCHANGER_UMOUNT=/usr/libexec/vchanger/vchanger-umount-uuid.sh
|
||||||
{
|
|
||||||
$VCHANGER_UMOUNT $1
|
# For some reason, nohup doesn't work, but "at now" does. This may have to
|
||||||
} &
|
# do with cgroups.
|
||||||
|
#nohup $VCHANGER_UMOUNT $1 </dev/null >/dev/null 2>&1 &
|
||||||
|
echo "$VCHANGER_UMOUNT $1 </dev/null >/dev/null 2>&1" | at now
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
#
|
#
|
||||||
# vchanger-mount-uuid.sh ( vchanger v.1.0.1 ) 2015-06-03
|
# vchanger-mount-uuid.sh ( vchanger v.1.0.3 ) 2020-05-06
|
||||||
#
|
#
|
||||||
# This script is used to mount the filesystem having the
|
# This script is used to mount the filesystem having the
|
||||||
# UUID specified in parameter 1 at a fixed path. The path
|
# UUID specified in parameter 1 at a fixed path. The path
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
#
|
#
|
||||||
# vchanger-umount-uuid.sh ( vchanger v.1.0.1 ) 2015-06-03
|
# vchanger-umount-uuid.sh ( vchanger v.1.0.3 ) 2020-05-06
|
||||||
#
|
#
|
||||||
# This script is used to unmount the filesystem having the
|
# This script is used to unmount the filesystem having the
|
||||||
# UUID specified in parameter 1. The mountpoint path
|
# UUID specified in parameter 1. The mountpoint path
|
||||||
|
@ -4,11 +4,10 @@ AM_CXXFLAGS = -DLOCALSTATEDIR='"${localstatedir}"'
|
|||||||
AM_LDFLAGS = @WINLDADD@
|
AM_LDFLAGS = @WINLDADD@
|
||||||
bin_PROGRAMS = vchanger
|
bin_PROGRAMS = vchanger
|
||||||
vchanger_SOURCES = compat/getline.c compat/gettimeofday.c \
|
vchanger_SOURCES = compat/getline.c compat/gettimeofday.c \
|
||||||
compat/localtime_r.c \
|
compat/readlink.c compat/semaphore.c \
|
||||||
compat/readlink.c \
|
|
||||||
compat/symlink.c compat/sleep.c compat/syslog.c \
|
compat/symlink.c compat/sleep.c compat/syslog.c \
|
||||||
win32_util.c uuidlookup.c bconsole.cpp \
|
win32_util.c uuidlookup.c bconsole.cpp \
|
||||||
tstring.cpp inifile.cpp mypopen.cpp \
|
tstring.cpp inifile.cpp mymutex.cpp mypopen.cpp \
|
||||||
vconf.cpp loghandler.cpp errhandler.cpp \
|
vconf.cpp loghandler.cpp errhandler.cpp \
|
||||||
util.cpp changerstate.cpp diskchanger.cpp \
|
util.cpp changerstate.cpp diskchanger.cpp \
|
||||||
vchanger.cpp
|
vchanger.cpp
|
||||||
|
@ -91,12 +91,12 @@ CONFIG_CLEAN_VPATH_FILES =
|
|||||||
am__installdirs = "$(DESTDIR)$(bindir)"
|
am__installdirs = "$(DESTDIR)$(bindir)"
|
||||||
PROGRAMS = $(bin_PROGRAMS)
|
PROGRAMS = $(bin_PROGRAMS)
|
||||||
am_vchanger_OBJECTS = getline.$(OBJEXT) gettimeofday.$(OBJEXT) \
|
am_vchanger_OBJECTS = getline.$(OBJEXT) gettimeofday.$(OBJEXT) \
|
||||||
localtime_r.$(OBJEXT) readlink.$(OBJEXT) symlink.$(OBJEXT) \
|
readlink.$(OBJEXT) semaphore.$(OBJEXT) symlink.$(OBJEXT) \
|
||||||
sleep.$(OBJEXT) syslog.$(OBJEXT) win32_util.$(OBJEXT) \
|
sleep.$(OBJEXT) syslog.$(OBJEXT) win32_util.$(OBJEXT) \
|
||||||
uuidlookup.$(OBJEXT) bconsole.$(OBJEXT) tstring.$(OBJEXT) \
|
uuidlookup.$(OBJEXT) bconsole.$(OBJEXT) tstring.$(OBJEXT) \
|
||||||
inifile.$(OBJEXT) mypopen.$(OBJEXT) vconf.$(OBJEXT) \
|
inifile.$(OBJEXT) mymutex.$(OBJEXT) mypopen.$(OBJEXT) \
|
||||||
loghandler.$(OBJEXT) errhandler.$(OBJEXT) util.$(OBJEXT) \
|
vconf.$(OBJEXT) loghandler.$(OBJEXT) errhandler.$(OBJEXT) \
|
||||||
changerstate.$(OBJEXT) diskchanger.$(OBJEXT) \
|
util.$(OBJEXT) changerstate.$(OBJEXT) diskchanger.$(OBJEXT) \
|
||||||
vchanger.$(OBJEXT)
|
vchanger.$(OBJEXT)
|
||||||
vchanger_OBJECTS = $(am_vchanger_OBJECTS)
|
vchanger_OBJECTS = $(am_vchanger_OBJECTS)
|
||||||
vchanger_LDADD = $(LDADD)
|
vchanger_LDADD = $(LDADD)
|
||||||
@ -269,11 +269,10 @@ AM_CFLAGS = -DLOCALSTATEDIR='"${localstatedir}"'
|
|||||||
AM_CXXFLAGS = -DLOCALSTATEDIR='"${localstatedir}"'
|
AM_CXXFLAGS = -DLOCALSTATEDIR='"${localstatedir}"'
|
||||||
AM_LDFLAGS = @WINLDADD@
|
AM_LDFLAGS = @WINLDADD@
|
||||||
vchanger_SOURCES = compat/getline.c compat/gettimeofday.c \
|
vchanger_SOURCES = compat/getline.c compat/gettimeofday.c \
|
||||||
compat/localtime_r.c \
|
compat/readlink.c compat/semaphore.c \
|
||||||
compat/readlink.c \
|
|
||||||
compat/symlink.c compat/sleep.c compat/syslog.c \
|
compat/symlink.c compat/sleep.c compat/syslog.c \
|
||||||
win32_util.c uuidlookup.c bconsole.cpp \
|
win32_util.c uuidlookup.c bconsole.cpp \
|
||||||
tstring.cpp inifile.cpp mypopen.cpp \
|
tstring.cpp inifile.cpp mymutex.cpp mypopen.cpp \
|
||||||
vconf.cpp loghandler.cpp errhandler.cpp \
|
vconf.cpp loghandler.cpp errhandler.cpp \
|
||||||
util.cpp changerstate.cpp diskchanger.cpp \
|
util.cpp changerstate.cpp diskchanger.cpp \
|
||||||
vchanger.cpp
|
vchanger.cpp
|
||||||
@ -372,10 +371,11 @@ distclean-compile:
|
|||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getline.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getline.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gettimeofday.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gettimeofday.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inifile.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inifile.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/localtime_r.Po@am__quote@
|
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loghandler.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loghandler.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mymutex.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mypopen.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mypopen.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readlink.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readlink.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/semaphore.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sleep.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sleep.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/symlink.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/symlink.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syslog.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syslog.Po@am__quote@
|
||||||
@ -428,20 +428,6 @@ gettimeofday.obj: compat/gettimeofday.c
|
|||||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gettimeofday.obj `if test -f 'compat/gettimeofday.c'; then $(CYGPATH_W) 'compat/gettimeofday.c'; else $(CYGPATH_W) '$(srcdir)/compat/gettimeofday.c'; fi`
|
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gettimeofday.obj `if test -f 'compat/gettimeofday.c'; then $(CYGPATH_W) 'compat/gettimeofday.c'; else $(CYGPATH_W) '$(srcdir)/compat/gettimeofday.c'; fi`
|
||||||
|
|
||||||
localtime_r.o: compat/localtime_r.c
|
|
||||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT localtime_r.o -MD -MP -MF $(DEPDIR)/localtime_r.Tpo -c -o localtime_r.o `test -f 'compat/localtime_r.c' || echo '$(srcdir)/'`compat/localtime_r.c
|
|
||||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/localtime_r.Tpo $(DEPDIR)/localtime_r.Po
|
|
||||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='compat/localtime_r.c' object='localtime_r.o' libtool=no @AMDEPBACKSLASH@
|
|
||||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
|
||||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o localtime_r.o `test -f 'compat/localtime_r.c' || echo '$(srcdir)/'`compat/localtime_r.c
|
|
||||||
|
|
||||||
localtime_r.obj: compat/localtime_r.c
|
|
||||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT localtime_r.obj -MD -MP -MF $(DEPDIR)/localtime_r.Tpo -c -o localtime_r.obj `if test -f 'compat/localtime_r.c'; then $(CYGPATH_W) 'compat/localtime_r.c'; else $(CYGPATH_W) '$(srcdir)/compat/localtime_r.c'; fi`
|
|
||||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/localtime_r.Tpo $(DEPDIR)/localtime_r.Po
|
|
||||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='compat/localtime_r.c' object='localtime_r.obj' libtool=no @AMDEPBACKSLASH@
|
|
||||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
|
||||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o localtime_r.obj `if test -f 'compat/localtime_r.c'; then $(CYGPATH_W) 'compat/localtime_r.c'; else $(CYGPATH_W) '$(srcdir)/compat/localtime_r.c'; fi`
|
|
||||||
|
|
||||||
readlink.o: compat/readlink.c
|
readlink.o: compat/readlink.c
|
||||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT readlink.o -MD -MP -MF $(DEPDIR)/readlink.Tpo -c -o readlink.o `test -f 'compat/readlink.c' || echo '$(srcdir)/'`compat/readlink.c
|
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT readlink.o -MD -MP -MF $(DEPDIR)/readlink.Tpo -c -o readlink.o `test -f 'compat/readlink.c' || echo '$(srcdir)/'`compat/readlink.c
|
||||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/readlink.Tpo $(DEPDIR)/readlink.Po
|
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/readlink.Tpo $(DEPDIR)/readlink.Po
|
||||||
@ -456,6 +442,20 @@ readlink.obj: compat/readlink.c
|
|||||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o readlink.obj `if test -f 'compat/readlink.c'; then $(CYGPATH_W) 'compat/readlink.c'; else $(CYGPATH_W) '$(srcdir)/compat/readlink.c'; fi`
|
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o readlink.obj `if test -f 'compat/readlink.c'; then $(CYGPATH_W) 'compat/readlink.c'; else $(CYGPATH_W) '$(srcdir)/compat/readlink.c'; fi`
|
||||||
|
|
||||||
|
semaphore.o: compat/semaphore.c
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT semaphore.o -MD -MP -MF $(DEPDIR)/semaphore.Tpo -c -o semaphore.o `test -f 'compat/semaphore.c' || echo '$(srcdir)/'`compat/semaphore.c
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/semaphore.Tpo $(DEPDIR)/semaphore.Po
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='compat/semaphore.c' object='semaphore.o' libtool=no @AMDEPBACKSLASH@
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
|
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o semaphore.o `test -f 'compat/semaphore.c' || echo '$(srcdir)/'`compat/semaphore.c
|
||||||
|
|
||||||
|
semaphore.obj: compat/semaphore.c
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT semaphore.obj -MD -MP -MF $(DEPDIR)/semaphore.Tpo -c -o semaphore.obj `if test -f 'compat/semaphore.c'; then $(CYGPATH_W) 'compat/semaphore.c'; else $(CYGPATH_W) '$(srcdir)/compat/semaphore.c'; fi`
|
||||||
|
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/semaphore.Tpo $(DEPDIR)/semaphore.Po
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='compat/semaphore.c' object='semaphore.obj' libtool=no @AMDEPBACKSLASH@
|
||||||
|
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
|
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o semaphore.obj `if test -f 'compat/semaphore.c'; then $(CYGPATH_W) 'compat/semaphore.c'; else $(CYGPATH_W) '$(srcdir)/compat/semaphore.c'; fi`
|
||||||
|
|
||||||
symlink.o: compat/symlink.c
|
symlink.o: compat/symlink.c
|
||||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT symlink.o -MD -MP -MF $(DEPDIR)/symlink.Tpo -c -o symlink.o `test -f 'compat/symlink.c' || echo '$(srcdir)/'`compat/symlink.c
|
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT symlink.o -MD -MP -MF $(DEPDIR)/symlink.Tpo -c -o symlink.o `test -f 'compat/symlink.c' || echo '$(srcdir)/'`compat/symlink.c
|
||||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/symlink.Tpo $(DEPDIR)/symlink.Po
|
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/symlink.Tpo $(DEPDIR)/symlink.Po
|
||||||
|
137
src/bconsole.cpp
137
src/bconsole.cpp
@ -1,6 +1,6 @@
|
|||||||
/* bconsole.cpp
|
/* bconsole.cpp
|
||||||
*
|
*
|
||||||
* Copyright (C) 2008-2014 Josh Fisher
|
* Copyright (C) 2008-2018 Josh Fisher
|
||||||
*
|
*
|
||||||
* This program is free software. You may redistribute it and/or modify
|
* This program is free software. You may redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License, as published by
|
* it under the terms of the GNU General Public License, as published by
|
||||||
@ -47,18 +47,22 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "compat_defs.h"
|
||||||
|
#include "util.h"
|
||||||
#include "loghandler.h"
|
#include "loghandler.h"
|
||||||
|
#include "mymutex.h"
|
||||||
#include "mypopen.h"
|
#include "mypopen.h"
|
||||||
#include "vconf.h"
|
#include "vconf.h"
|
||||||
#include "bconsole.h"
|
#include "bconsole.h"
|
||||||
|
|
||||||
|
#ifndef HAVE_WINDOWS_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function to issue command in Bacula console.
|
* Function to issue command in Bacula console.
|
||||||
* Returns zero on success, or errno if there was an error running the command
|
* Returns zero on success, or errno if there was an error running the command
|
||||||
* or a timeout occurred.
|
* or a timeout occurred.
|
||||||
*/
|
*/
|
||||||
int issue_bconsole_command(const char *bcmd)
|
static int issue_bconsole_command(const char *bcmd)
|
||||||
{
|
{
|
||||||
int pid, rc, n, len, fno_in = -1, fno_out = -1;
|
int pid, rc, n, len, fno_in = -1, fno_out = -1;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
@ -66,7 +70,6 @@ int issue_bconsole_command(const char *bcmd)
|
|||||||
tString cmd, tmp;
|
tString cmd, tmp;
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
|
|
||||||
#ifndef HAVE_WINDOWS_H
|
|
||||||
/* Build command line */
|
/* Build command line */
|
||||||
cmd = conf.bconsole;
|
cmd = conf.bconsole;
|
||||||
if (cmd.empty()) return 0;
|
if (cmd.empty()) return 0;
|
||||||
@ -76,11 +79,11 @@ int issue_bconsole_command(const char *bcmd)
|
|||||||
}
|
}
|
||||||
cmd += " -n -u 30";
|
cmd += " -n -u 30";
|
||||||
/* Start bconsole process */
|
/* Start bconsole process */
|
||||||
log.Debug("bconsole: running '%s'", bcmd);
|
vlog.Debug("running '%s'", cmd.c_str());
|
||||||
pid = mypopen_raw(cmd.c_str(), &fno_in, &fno_out, NULL);
|
pid = mypopen_raw(cmd.c_str(), &fno_in, &fno_out, NULL);
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
rc = errno;
|
rc = errno;
|
||||||
log.Error("bconsole: run failed errno=%d", rc);
|
vlog.Error("bconsole run failed errno=%d", rc);
|
||||||
errno = rc;
|
errno = rc;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -91,7 +94,7 @@ int issue_bconsole_command(const char *bcmd)
|
|||||||
FD_SET(fno_in, &rfd);
|
FD_SET(fno_in, &rfd);
|
||||||
rc = select(fno_in + 1, NULL, &rfd, NULL, &tv);
|
rc = select(fno_in + 1, NULL, &rfd, NULL, &tv);
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
log.Error("bconsole: timed out waiting to send command");
|
vlog.Error("timeout waiting to send command to bconsole");
|
||||||
close(fno_in);
|
close(fno_in);
|
||||||
close(fno_out);
|
close(fno_out);
|
||||||
errno = ETIMEDOUT;
|
errno = ETIMEDOUT;
|
||||||
@ -99,20 +102,21 @@ int issue_bconsole_command(const char *bcmd)
|
|||||||
}
|
}
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
rc = errno;
|
rc = errno;
|
||||||
log.Error("bconsole: errno=%d waiting to send command", rc);
|
vlog.Error("errno=%d waiting to send command to bconsole", rc);
|
||||||
close(fno_in);
|
close(fno_in);
|
||||||
close(fno_out);
|
close(fno_out);
|
||||||
errno = rc;
|
errno = rc;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
/* Send command to bconsole's stdin */
|
/* Send command to bconsole's stdin */
|
||||||
|
vlog.Debug("sending bconsole command '%s'", bcmd);
|
||||||
len = strlen(bcmd);
|
len = strlen(bcmd);
|
||||||
n = 0;
|
n = 0;
|
||||||
while (n < len) {
|
while (n < len) {
|
||||||
rc = write(fno_in, bcmd + n, len - n);
|
rc = write(fno_in, bcmd + n, len - n);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
rc = errno;
|
rc = errno;
|
||||||
log.Error("bconsole: send to bconsole's stdin failed errno=%d", rc);
|
vlog.Error("send to bconsole's stdin failed errno=%d", rc);
|
||||||
close(fno_in);
|
close(fno_in);
|
||||||
close(fno_out);
|
close(fno_out);
|
||||||
errno = rc;
|
errno = rc;
|
||||||
@ -120,57 +124,90 @@ int issue_bconsole_command(const char *bcmd)
|
|||||||
}
|
}
|
||||||
n += rc;
|
n += rc;
|
||||||
}
|
}
|
||||||
close(fno_in);
|
if (write(fno_in, "\n", 1) != 1) {
|
||||||
|
rc = errno;
|
||||||
/* Read stdout from bconsole */
|
vlog.Error("send to bconsole's stdin failed errno=%d", rc);
|
||||||
memset(buf, 0, sizeof(buf));
|
close(fno_in);
|
||||||
tmp.clear();
|
close(fno_out);
|
||||||
while (true) {
|
errno = rc;
|
||||||
tv.tv_sec = 30;
|
return rc;
|
||||||
tv.tv_usec = 0;
|
|
||||||
FD_ZERO(&rfd);
|
|
||||||
FD_SET(fno_out, &rfd);
|
|
||||||
rc = select(fno_out + 1, &rfd, NULL, NULL, &tv);
|
|
||||||
if (rc == 0) {
|
|
||||||
log.Error("bconsole: timed out waiting for bconsole output");
|
|
||||||
close(fno_out);
|
|
||||||
errno = ETIMEDOUT;
|
|
||||||
return ETIMEDOUT;
|
|
||||||
}
|
|
||||||
if (rc < 0) {
|
|
||||||
rc = errno;
|
|
||||||
log.Error("bconsole: errno=%d waiting for bconsole output", rc);
|
|
||||||
close(fno_out);
|
|
||||||
errno = rc;
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
rc = read(fno_out, buf, 4095);
|
|
||||||
if (rc < 0) {
|
|
||||||
rc = errno;
|
|
||||||
log.Error("bconsole: errno=%d reading bconsole stdout", rc);
|
|
||||||
close(fno_out);
|
|
||||||
errno = rc;
|
|
||||||
return rc;
|
|
||||||
} else if (rc > 0) {
|
|
||||||
buf[rc] = 0;
|
|
||||||
tmp += buf;
|
|
||||||
} else break;
|
|
||||||
}
|
}
|
||||||
close(fno_out);
|
|
||||||
log.Debug("bconsole: output:\n%s", tmp.c_str());
|
|
||||||
|
|
||||||
/* Wait for bconsole process to finish */
|
/* Wait for bconsole process to finish */
|
||||||
|
close(fno_in);
|
||||||
pid = waitpid(pid, &rc, 0);
|
pid = waitpid(pid, &rc, 0);
|
||||||
if (!WIFEXITED(rc)) {
|
if (!WIFEXITED(rc)) {
|
||||||
log.Error("bconsole: abnormal exit of bconsole process");
|
vlog.Error("abnormal exit of bconsole process");
|
||||||
|
close(fno_out);
|
||||||
return EPIPE;
|
return EPIPE;
|
||||||
}
|
}
|
||||||
if (WEXITSTATUS(rc)) {
|
if (WEXITSTATUS(rc)) {
|
||||||
log.Error("bconsole: exited with rc=%d", WEXITSTATUS(rc));
|
vlog.Error("bconsole: exited with rc=%d", WEXITSTATUS(rc));
|
||||||
|
close(fno_out);
|
||||||
return WEXITSTATUS(rc);
|
return WEXITSTATUS(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Read stdout from bconsole */
|
||||||
|
vlog.Debug("bconsole: bconsole terminated normally");
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
tmp.clear();
|
||||||
|
rc = read(fno_out, buf, 4095);
|
||||||
|
while (rc > 0) {
|
||||||
|
buf[rc] = 0;
|
||||||
|
tmp += buf;
|
||||||
|
rc = read(fno_out, buf, 4095);
|
||||||
|
}
|
||||||
|
if (rc < 0) {
|
||||||
|
rc = errno;
|
||||||
|
vlog.Error("errno=%d reading bconsole stdout", rc);
|
||||||
|
close(fno_out);
|
||||||
|
errno = rc;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
close(fno_out);
|
||||||
|
vlog.Debug("bconsole output:\n%s", tmp.c_str());
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
|
||||||
return EINVAL;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function to fork a new process and issue commands in Bacula console to
|
||||||
|
* perform update slots and/or label new volumes using barcodes.
|
||||||
|
*/
|
||||||
|
void IssueBconsoleCommands(bool update_slots, bool label_barcodes)
|
||||||
|
{
|
||||||
|
tString cmd;
|
||||||
|
|
||||||
|
/* Check if update needed */
|
||||||
|
if (!update_slots && !label_barcodes) return; /* Nothing to do */
|
||||||
|
|
||||||
|
/* Perform update slots command in bconsole */
|
||||||
|
if (update_slots) {
|
||||||
|
tFormat(cmd, "update slots storage=\"%s\" drive=\"0\"", conf.storage_name.c_str());
|
||||||
|
if(issue_bconsole_command(cmd.c_str())) {
|
||||||
|
vlog.Error("WARNING! 'update slots' needed in bconsole");
|
||||||
|
}
|
||||||
|
vlog.Info("bconsole update slots command success");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Perform label barcodes command in bconsole */
|
||||||
|
if (label_barcodes) {
|
||||||
|
tFormat(cmd, "label storage=\"%s\" pool=\"%s\" barcodes\nyes\nyes\n", conf.storage_name.c_str(),
|
||||||
|
conf.def_pool.c_str());
|
||||||
|
if (issue_bconsole_command(cmd.c_str())) {
|
||||||
|
vlog.Error("WARNING! 'label barcodes' needed in bconsole");
|
||||||
|
}
|
||||||
|
vlog.Info("bconsole label barcodes command success");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* Bconsole interaction is not currently supported on Windows
|
||||||
|
*/
|
||||||
|
void IssueBconsoleCommands(bool update_slots, bool label_barcodes)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
*
|
*
|
||||||
* This file is part of vchanger by Josh Fisher.
|
* This file is part of vchanger by Josh Fisher.
|
||||||
*
|
*
|
||||||
* vchanger copyright (C) 2008-2014 Josh Fisher
|
* vchanger copyright (C) 2008-2017 Josh Fisher
|
||||||
*
|
*
|
||||||
* vchanger is free software.
|
* vchanger is free software.
|
||||||
* You may redistribute it and/or modify it under the terms of the
|
* You may redistribute it and/or modify it under the terms of the
|
||||||
@ -24,6 +24,6 @@
|
|||||||
#ifndef BCONSOLE_H_
|
#ifndef BCONSOLE_H_
|
||||||
#define BCONSOLE_H_
|
#define BCONSOLE_H_
|
||||||
|
|
||||||
int issue_bconsole_command(const char *bcmd);
|
void IssueBconsoleCommands(bool update_slots, bool label_barcodes);
|
||||||
|
|
||||||
#endif /* BCONSOLE_H_ */
|
#endif /* BCONSOLE_H_ */
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
*
|
*
|
||||||
* This file is part of vchanger by Josh Fisher.
|
* This file is part of vchanger by Josh Fisher.
|
||||||
*
|
*
|
||||||
* vchanger copyright (C) 2008-2015 Josh Fisher
|
* vchanger copyright (C) 2008-2018 Josh Fisher
|
||||||
*
|
*
|
||||||
* vchanger is free software.
|
* vchanger is free software.
|
||||||
* You may redistribute it and/or modify it under the terms of the
|
* You may redistribute it and/or modify it under the terms of the
|
||||||
@ -173,7 +173,7 @@ int MagazineState::save()
|
|||||||
|
|
||||||
if (mag_bay < 0) {
|
if (mag_bay < 0) {
|
||||||
verr.SetErrorWithErrno(EINVAL, "cannot save state of invalid magazine %d", mag_bay);
|
verr.SetErrorWithErrno(EINVAL, "cannot save state of invalid magazine %d", mag_bay);
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
/* Build path to state file */
|
/* Build path to state file */
|
||||||
@ -191,7 +191,7 @@ int MagazineState::save()
|
|||||||
rc = errno;
|
rc = errno;
|
||||||
umask(old_mask);
|
umask(old_mask);
|
||||||
verr.SetErrorWithErrno(rc, "cannot open magazine %d state file for writing", mag_bay);
|
verr.SetErrorWithErrno(rc, "cannot open magazine %d state file for writing", mag_bay);
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
/* Save magazine device (directory or UUID), number of volumes, and start of
|
/* Save magazine device (directory or UUID), number of volumes, and start of
|
||||||
@ -203,12 +203,12 @@ int MagazineState::save()
|
|||||||
unlink(sname);
|
unlink(sname);
|
||||||
umask(old_mask);
|
umask(old_mask);
|
||||||
verr.SetErrorWithErrno(rc, "cannot write to magazine %d state file", mag_bay);
|
verr.SetErrorWithErrno(rc, "cannot write to magazine %d state file", mag_bay);
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
fclose(FS);
|
fclose(FS);
|
||||||
umask(old_mask);
|
umask(old_mask);
|
||||||
log.Notice("saved state of magazine %d", mag_bay);
|
vlog.Notice("saved state of magazine %d", mag_bay);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +230,7 @@ int MagazineState::restore()
|
|||||||
|
|
||||||
if (mag_bay < 0) {
|
if (mag_bay < 0) {
|
||||||
verr.SetErrorWithErrno(EINVAL, "cannot restore state of invalid magazine %d", mag_bay);
|
verr.SetErrorWithErrno(EINVAL, "cannot restore state of invalid magazine %d", mag_bay);
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
clear();
|
clear();
|
||||||
@ -250,7 +250,7 @@ int MagazineState::restore()
|
|||||||
/* No read permission? */
|
/* No read permission? */
|
||||||
rc = errno;
|
rc = errno;
|
||||||
verr.SetErrorWithErrno(rc, "cannot open magazine %d state file for reading", mag_bay);
|
verr.SetErrorWithErrno(rc, "cannot open magazine %d state file for reading", mag_bay);
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
if (tGetLine(line, FS) == NULL) {
|
if (tGetLine(line, FS) == NULL) {
|
||||||
@ -259,7 +259,7 @@ int MagazineState::restore()
|
|||||||
/* error reading bay state file */
|
/* error reading bay state file */
|
||||||
fclose(FS);
|
fclose(FS);
|
||||||
verr.SetErrorWithErrno(rc, "error reading magazine %d state file", mag_bay);
|
verr.SetErrorWithErrno(rc, "error reading magazine %d state file", mag_bay);
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -270,7 +270,7 @@ int MagazineState::restore()
|
|||||||
p = 0;
|
p = 0;
|
||||||
if (tParseCSV(word, line, p) <= 0) {
|
if (tParseCSV(word, line, p) <= 0) {
|
||||||
/* bay state file should not be empty, assume it didn't exist */
|
/* bay state file should not be empty, assume it didn't exist */
|
||||||
log.Warning("WARNING! magazine %d state file was empty, deleting it", mag_bay);
|
vlog.Warning("WARNING! magazine %d state file was empty, deleting it", mag_bay);
|
||||||
unlink(sname);
|
unlink(sname);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -285,7 +285,7 @@ int MagazineState::restore()
|
|||||||
/* Bay state file is corrupt.
|
/* Bay state file is corrupt.
|
||||||
* Treat as if it was not mounted at last invocation */
|
* Treat as if it was not mounted at last invocation */
|
||||||
clear();
|
clear();
|
||||||
log.Warning("WARNING! magazine %d state file corrupt, deleting it", mag_bay);
|
vlog.Warning("WARNING! magazine %d state file corrupt, deleting it", mag_bay);
|
||||||
unlink(sname);
|
unlink(sname);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -293,7 +293,7 @@ int MagazineState::restore()
|
|||||||
/* Corrupt bay state file, assume it doesn't exist */
|
/* Corrupt bay state file, assume it doesn't exist */
|
||||||
clear();
|
clear();
|
||||||
unlink(sname);
|
unlink(sname);
|
||||||
log.Warning("WARNING! magazine %d state file has invalid number of slots field, deleting it", mag_bay);
|
vlog.Warning("WARNING! magazine %d state file has invalid number of slots field, deleting it", mag_bay);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
prev_num_slots = (int)strtol(word.c_str(), NULL, 10);
|
prev_num_slots = (int)strtol(word.c_str(), NULL, 10);
|
||||||
@ -302,7 +302,7 @@ int MagazineState::restore()
|
|||||||
clear();
|
clear();
|
||||||
prev_num_slots = 0;
|
prev_num_slots = 0;
|
||||||
unlink(sname);
|
unlink(sname);
|
||||||
log.Warning("WARNING! magazine %d state file has invalid number of slots field, deleting it", mag_bay);
|
vlog.Warning("WARNING! magazine %d state file has invalid number of slots field, deleting it", mag_bay);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,7 +312,7 @@ int MagazineState::restore()
|
|||||||
* Treat as if it was not mounted at last invocation */
|
* Treat as if it was not mounted at last invocation */
|
||||||
clear();
|
clear();
|
||||||
prev_num_slots = 0;
|
prev_num_slots = 0;
|
||||||
log.Warning("WARNING! magazine %d state file corrupt, deleting it", mag_bay);
|
vlog.Warning("WARNING! magazine %d state file corrupt, deleting it", mag_bay);
|
||||||
unlink(sname);
|
unlink(sname);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -321,7 +321,7 @@ int MagazineState::restore()
|
|||||||
clear();
|
clear();
|
||||||
prev_num_slots = 0;
|
prev_num_slots = 0;
|
||||||
unlink(sname);
|
unlink(sname);
|
||||||
log.Warning("WARNING! magazine %d state file has invalid virtual slot assignment field, deleting it",
|
vlog.Warning("WARNING! magazine %d state file has invalid virtual slot assignment field, deleting it",
|
||||||
mag_bay);
|
mag_bay);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -332,11 +332,11 @@ int MagazineState::restore()
|
|||||||
prev_num_slots = 0;
|
prev_num_slots = 0;
|
||||||
prev_start_slot = 0;
|
prev_start_slot = 0;
|
||||||
unlink(sname);
|
unlink(sname);
|
||||||
log.Warning("WARNING! magazine %d state file has invalid virtual slot assignment field, deleting it",
|
vlog.Warning("WARNING! magazine %d state file has invalid virtual slot assignment field, deleting it",
|
||||||
mag_bay);
|
mag_bay);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
log.Notice("restored state of magazine %d", mag_bay);
|
vlog.Notice("restored state of magazine %d", mag_bay);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,7 +389,7 @@ int MagazineState::UpdateMagazineFormat()
|
|||||||
fs = fopen(lname.c_str(), "r");
|
fs = fopen(lname.c_str(), "r");
|
||||||
if (fs == NULL) {
|
if (fs == NULL) {
|
||||||
verr.SetErrorWithErrno(errno, "failed to find loaded%d file when updating magazine %d", drv, mag_bay);
|
verr.SetErrorWithErrno(errno, "failed to find loaded%d file when updating magazine %d", drv, mag_bay);
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
de = readdir(dir);
|
de = readdir(dir);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -397,7 +397,7 @@ int MagazineState::UpdateMagazineFormat()
|
|||||||
fclose(fs);
|
fclose(fs);
|
||||||
if (str.empty()) {
|
if (str.empty()) {
|
||||||
verr.SetError(-1, "loaded%d file empty when updating magazine %d", drv, mag_bay);
|
verr.SetError(-1, "loaded%d file empty when updating magazine %d", drv, mag_bay);
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
de = readdir(dir);
|
de = readdir(dir);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -406,7 +406,7 @@ int MagazineState::UpdateMagazineFormat()
|
|||||||
if (rename(fname.c_str(), vname.c_str())) {
|
if (rename(fname.c_str(), vname.c_str())) {
|
||||||
verr.SetError(EINVAL, "unable to rename 'drive%d' on magazine %d",
|
verr.SetError(EINVAL, "unable to rename 'drive%d' on magazine %d",
|
||||||
drv, mag_bay);
|
drv, mag_bay);
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
de = readdir(dir);
|
de = readdir(dir);
|
||||||
@ -445,7 +445,7 @@ int MagazineState::UpdateMagazineFormat()
|
|||||||
tFormat(fname, "%s%sindex", mountpoint.c_str(), DIR_DELIM);
|
tFormat(fname, "%s%sindex", mountpoint.c_str(), DIR_DELIM);
|
||||||
unlink(fname.c_str());
|
unlink(fname.c_str());
|
||||||
|
|
||||||
log.Warning("magaine %d updated from old format", mag_bay);
|
vlog.Warning("magaine %d updated from old format", mag_bay);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,7 +494,7 @@ int MagazineState::Mount()
|
|||||||
}
|
}
|
||||||
if (rc) {
|
if (rc) {
|
||||||
verr.SetError(rc, "system error determining mountpoint from UUID");
|
verr.SetError(rc, "system error determining mountpoint from UUID");
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
mountpoint.clear();
|
mountpoint.clear();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -510,7 +510,7 @@ int MagazineState::Mount()
|
|||||||
/* Ensure access to magazine mountpoint */
|
/* Ensure access to magazine mountpoint */
|
||||||
if (access(mountpoint.c_str(), W_OK) != 0) {
|
if (access(mountpoint.c_str(), W_OK) != 0) {
|
||||||
verr.SetError(rc, "no write access to directory %s", mountpoint.c_str());
|
verr.SetError(rc, "no write access to directory %s", mountpoint.c_str());
|
||||||
log.Error("%s", verr.GetErrorMsg());
|
vlog.Error("%s", verr.GetErrorMsg());
|
||||||
mountpoint.clear();
|
mountpoint.clear();
|
||||||
return -5;
|
return -5;
|
||||||
}
|
}
|
||||||
@ -529,7 +529,7 @@ int MagazineState::Mount()
|
|||||||
/* could not open mountpoint dir */
|
/* could not open mountpoint dir */
|
||||||
rc = errno;
|
rc = errno;
|
||||||
verr.SetErrorWithErrno(rc, "cannot open directory '%s'", mountpoint.c_str());
|
verr.SetErrorWithErrno(rc, "cannot open directory '%s'", mountpoint.c_str());
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
mountpoint.clear();
|
mountpoint.clear();
|
||||||
if (rc == ENOTDIR || rc == ENOENT) return -3;
|
if (rc == ENOTDIR || rc == ENOENT) return -3;
|
||||||
if (rc == EACCES) return -5;
|
if (rc == EACCES) return -5;
|
||||||
@ -659,7 +659,7 @@ int MagazineState::CreateVolume(const char *vol_label_in)
|
|||||||
}
|
}
|
||||||
if (rc != ENOENT) {
|
if (rc != ENOENT) {
|
||||||
verr.SetErrorWithErrno(rc, "error %d accessing volumes on magazine %d", rc, mag_bay);
|
verr.SetErrorWithErrno(rc, "error %d accessing volumes on magazine %d", rc, mag_bay);
|
||||||
log.Error("MagazineState::CreateVolume: %s", verr.GetErrorMsg());
|
vlog.Error("MagazineState::CreateVolume: %s", verr.GetErrorMsg());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* Create new volume file on magazine */
|
/* Create new volume file on magazine */
|
||||||
@ -667,7 +667,7 @@ int MagazineState::CreateVolume(const char *vol_label_in)
|
|||||||
if (!fs) {
|
if (!fs) {
|
||||||
rc = errno;
|
rc = errno;
|
||||||
verr.SetErrorWithErrno(rc, "error %d creating volume on magazine %d", rc, mag_bay);
|
verr.SetErrorWithErrno(rc, "error %d creating volume on magazine %d", rc, mag_bay);
|
||||||
log.Error("MagazineState::CreateVolume: %s", verr.GetErrorMsg());
|
vlog.Error("MagazineState::CreateVolume: %s", verr.GetErrorMsg());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
fclose(fs);
|
fclose(fs);
|
||||||
@ -676,7 +676,7 @@ int MagazineState::CreateVolume(const char *vol_label_in)
|
|||||||
new_mslot.label = label;
|
new_mslot.label = label;
|
||||||
mslot.push_back(new_mslot);
|
mslot.push_back(new_mslot);
|
||||||
++num_slots;
|
++num_slots;
|
||||||
log.Notice("created volume '%s' on magazine %d (%s)", label.c_str(), mag_bay, mag_dev.c_str());
|
vlog.Notice("created volume '%s' on magazine %d (%s)", label.c_str(), mag_bay, mag_dev.c_str());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -784,7 +784,7 @@ void DynamicConfig::save()
|
|||||||
/* Unable to open dynamic.conf file for writing */
|
/* Unable to open dynamic.conf file for writing */
|
||||||
rc = errno;
|
rc = errno;
|
||||||
umask(old_mask);
|
umask(old_mask);
|
||||||
log.Error("ERROR! cannot open dynamic.conf file for writing (errno=%d)", rc);
|
vlog.Error("ERROR! cannot open dynamic.conf file for writing (errno=%d)", rc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Save max slot number in use to dynamic configuration */
|
/* Save max slot number in use to dynamic configuration */
|
||||||
@ -794,12 +794,12 @@ void DynamicConfig::save()
|
|||||||
fclose(FS);
|
fclose(FS);
|
||||||
unlink(sname);
|
unlink(sname);
|
||||||
umask(old_mask);
|
umask(old_mask);
|
||||||
log.Error("ERROR! i/o error writing dynamic.conf file (errno=%d)", rc);
|
vlog.Error("ERROR! i/o error writing dynamic.conf file (errno=%d)", rc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fclose(FS);
|
fclose(FS);
|
||||||
umask(old_mask);
|
umask(old_mask);
|
||||||
log.Notice("saved dynamic configuration (max used slot: %d)", max_slot);
|
vlog.Notice("saved dynamic configuration (max used slot: %d)", max_slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -827,7 +827,7 @@ void DynamicConfig::restore()
|
|||||||
if (!FS) {
|
if (!FS) {
|
||||||
/* No read permission? */
|
/* No read permission? */
|
||||||
rc = errno;
|
rc = errno;
|
||||||
log.Error("ERROR! cannot open dynamic.conf file for restore (errno=%d)", rc);
|
vlog.Error("ERROR! cannot open dynamic.conf file for restore (errno=%d)", rc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (tGetLine(line, FS) == NULL) {
|
if (tGetLine(line, FS) == NULL) {
|
||||||
@ -835,7 +835,7 @@ void DynamicConfig::restore()
|
|||||||
if (!feof(FS)) {
|
if (!feof(FS)) {
|
||||||
/* error reading bay state file */
|
/* error reading bay state file */
|
||||||
fclose(FS);
|
fclose(FS);
|
||||||
log.Error("ERROR! i/o error reading dynamic.conf file (errno=%d)", rc);
|
vlog.Error("ERROR! i/o error reading dynamic.conf file (errno=%d)", rc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
197
src/compat/semaphore.c
Normal file
197
src/compat/semaphore.c
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
/* semaphore.c
|
||||||
|
*
|
||||||
|
* This file is part of vchanger by Josh Fisher.
|
||||||
|
*
|
||||||
|
* vchanger copyright (C) 2020 Josh Fisher
|
||||||
|
*
|
||||||
|
* vchanger is free software.
|
||||||
|
* You may redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU General Public License version 2, as published by the Free
|
||||||
|
* Software Foundation.
|
||||||
|
*
|
||||||
|
* vchanger is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with vchanger. See the file "COPYING". If not,
|
||||||
|
* write to: The Free Software Foundation, Inc.,
|
||||||
|
* 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#ifndef HAVE_SEMAPHORE_H
|
||||||
|
|
||||||
|
#ifdef HAVE_WINDOWS_H
|
||||||
|
#include "targetver.h"
|
||||||
|
#include <windows.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include "win32_util.h"
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
#ifdef HAVE_ERRNO_H
|
||||||
|
#include <errno.h>
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
#include "compat/semaphore.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_WINDOWS_H
|
||||||
|
|
||||||
|
/*-------------------------------------------------
|
||||||
|
* Emulate POSIX.1-2001 sem_open() function using win32/win64 CreateSemaphoreW() function.
|
||||||
|
* On success address of semaphore, else NULL on error.
|
||||||
|
*-------------------------------------------------*/
|
||||||
|
sem_t* sem_open(const char *name, int oflag, ...)
|
||||||
|
{
|
||||||
|
DWORD rc;
|
||||||
|
long mode, value;
|
||||||
|
wchar_t *wname = NULL;
|
||||||
|
size_t wname_sz = 0;
|
||||||
|
sem_t *fd;
|
||||||
|
va_list vl;
|
||||||
|
|
||||||
|
va_start(vl, oflag);
|
||||||
|
mode = (long)va_arg(vl, unsigned int);
|
||||||
|
value = (long)va_arg(vl, unsigned int);
|
||||||
|
va_end(vl);
|
||||||
|
|
||||||
|
/* Convert path strings to UTF16 encoding */
|
||||||
|
if (!AnsiToUTF16(name, &wname, &wname_sz)) {
|
||||||
|
rc = ERROR_BAD_PATHNAME;
|
||||||
|
errno = w32errno(rc);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
fd = (sem_t*)CreateSemaphoreW(NULL, value, LONG_MAX, wname);
|
||||||
|
free(wname);
|
||||||
|
if (fd == NULL) {
|
||||||
|
errno = w32errno(GetLastError());
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-------------------------------------------------
|
||||||
|
* Emulate POSIX.1-2001 sem_close() function using win32/win64 CloseHandle() function.
|
||||||
|
* On success returns zero, else negative on error.
|
||||||
|
*-------------------------------------------------*/
|
||||||
|
int sem_close(sem_t *sem)
|
||||||
|
{
|
||||||
|
if (sem == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
CloseHandle((HANDLE)sem);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-------------------------------------------------
|
||||||
|
* Emulate POSIX.1-2001 sem_unnlink() function by doing nothing. Windows will
|
||||||
|
* automatically unlink the object when the last open handle is closed.
|
||||||
|
* Returns zero.
|
||||||
|
*-------------------------------------------------*/
|
||||||
|
int sem_unlink(const char *name)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-------------------------------------------------
|
||||||
|
* Emulate POSIX.1-2001 sem_post() function using win32/win64 ReleaseSemaphore() function.
|
||||||
|
* On success returns zero, else negative on error.
|
||||||
|
*-------------------------------------------------*/
|
||||||
|
int sem_post(sem_t *sem)
|
||||||
|
{
|
||||||
|
if (sem == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ReleaseSemaphore((HANDLE)sem, 1, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-------------------------------------------------
|
||||||
|
* Emulate POSIX.1-2001 sem_wait() function using win32/win64 WaitForSingleObjectEx() function.
|
||||||
|
* On success returns zero, else negative on error.
|
||||||
|
*-------------------------------------------------*/
|
||||||
|
int sem_wait(sem_t *sem)
|
||||||
|
{
|
||||||
|
DWORD reason;
|
||||||
|
if (sem == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
reason = WaitForSingleObjectEx((HANDLE)sem, INFINITE, FALSE);
|
||||||
|
if (reason == 0) return 0;
|
||||||
|
switch (reason) {
|
||||||
|
case WAIT_IO_COMPLETION:
|
||||||
|
errno = EINTR;
|
||||||
|
break;
|
||||||
|
case WAIT_TIMEOUT:
|
||||||
|
errno = ETIMEDOUT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errno = EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-------------------------------------------------
|
||||||
|
* Emulate POSIX.1-2001 sem_timedwait() function using win32/win64 WaitForSingleObjectEx()
|
||||||
|
* function.
|
||||||
|
* On success returns zero, else negative on error.
|
||||||
|
*-------------------------------------------------*/
|
||||||
|
int sem_timedwait(sem_t *sem, const struct timespec *timeout)
|
||||||
|
{
|
||||||
|
DWORD reason, mt;
|
||||||
|
if (sem == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* semaphore.h functions use absolute time and Windows needs a time interval */
|
||||||
|
timeout->tv_sec -= time(NULL);
|
||||||
|
mt = timeout->tv_sec * 1000 + (timeout->tv_nsec / 1000000);
|
||||||
|
reason = WaitForSingleObjectEx((HANDLE)sem, mt, FALSE);
|
||||||
|
if (reason == WAIT_OBJECT_0) return 0;
|
||||||
|
switch (reason) {
|
||||||
|
case WAIT_IO_COMPLETION:
|
||||||
|
errno = EINTR;
|
||||||
|
break;
|
||||||
|
case WAIT_TIMEOUT:
|
||||||
|
errno = ETIMEDOUT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errno = EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-------------------------------------------------
|
||||||
|
* Emulate POSIX.1-2001 sem_trywait() function using win32/win64 WaitForSingleObjectEx()
|
||||||
|
* function.
|
||||||
|
* On success returns zero, else negative on error.
|
||||||
|
*-------------------------------------------------*/
|
||||||
|
int sem_trywait(sem_t *sem)
|
||||||
|
{
|
||||||
|
DWORD reason;
|
||||||
|
if (sem == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
reason = WaitForSingleObjectEx((HANDLE)sem, 0, FALSE);
|
||||||
|
if (reason == 0) return 0;
|
||||||
|
errno = EAGAIN;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
54
src/compat/semaphore.h
Normal file
54
src/compat/semaphore.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/* semaphore.h
|
||||||
|
*
|
||||||
|
* This file is part of vchanger by Josh Fisher.
|
||||||
|
*
|
||||||
|
* vchanger copyright (C) 2020 Josh Fisher
|
||||||
|
*
|
||||||
|
* vchanger is free software.
|
||||||
|
* You may redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU General Public License version 2, as published by the Free
|
||||||
|
* Software Foundation.
|
||||||
|
*
|
||||||
|
* vchanger is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with vchanger. See the file "COPYING". If not,
|
||||||
|
* write to: The Free Software Foundation, Inc.,
|
||||||
|
* 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SEMAPHORE_H
|
||||||
|
#define _SEMAPHORE_H
|
||||||
|
|
||||||
|
#ifndef HAVE_SEMAPHORE_H
|
||||||
|
/* For systems without symlink() function, use internal version */
|
||||||
|
|
||||||
|
typedef union
|
||||||
|
{
|
||||||
|
char __size[32];
|
||||||
|
long int __align;
|
||||||
|
} sem_t;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sem_t* sem_open(const char *name, int oflag, ...);
|
||||||
|
int sem_post(sem_t *sem);
|
||||||
|
int sem_wait(sem_t *sem);
|
||||||
|
int sem_trywait(sem_t *sem);
|
||||||
|
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
|
||||||
|
int sem_close(sem_t *sem);
|
||||||
|
int sem_unlink(const char *name);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _SEMAPHORE_H */
|
@ -2,7 +2,7 @@
|
|||||||
*
|
*
|
||||||
* This file is part of vchanger by Josh Fisher.
|
* This file is part of vchanger by Josh Fisher.
|
||||||
*
|
*
|
||||||
* vchanger copyright (C) 2008-2015 Josh Fisher
|
* vchanger copyright (C) 2008-2020 Josh Fisher
|
||||||
*
|
*
|
||||||
* vchanger is free software.
|
* vchanger is free software.
|
||||||
* You may redistribute it and/or modify it under the terms of the
|
* You may redistribute it and/or modify it under the terms of the
|
||||||
@ -65,20 +65,13 @@
|
|||||||
#include "loghandler.h"
|
#include "loghandler.h"
|
||||||
#include "bconsole.h"
|
#include "bconsole.h"
|
||||||
#include "diskchanger.h"
|
#include "diskchanger.h"
|
||||||
|
#include "vconf.h"
|
||||||
|
|
||||||
|
|
||||||
/*=================================================
|
/*=================================================
|
||||||
* Class DiskChanger
|
* Class DiskChanger
|
||||||
*=================================================*/
|
*=================================================*/
|
||||||
|
|
||||||
/*-------------------------------------------------
|
|
||||||
* destructor
|
|
||||||
*-------------------------------------------------*/
|
|
||||||
DiskChanger::~DiskChanger()
|
|
||||||
{
|
|
||||||
Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
* Protected method to read previous state of magazine bays.
|
* Protected method to read previous state of magazine bays.
|
||||||
@ -148,6 +141,7 @@ void DiskChanger::InitializeVirtSlots()
|
|||||||
|
|
||||||
/* Create all known slots as initially empty */
|
/* Create all known slots as initially empty */
|
||||||
vslot.clear();
|
vslot.clear();
|
||||||
|
vs.clear();
|
||||||
for (s = 0; s <= dconf.max_slot; s++) {
|
for (s = 0; s <= dconf.max_slot; s++) {
|
||||||
vs.vs = s;
|
vs.vs = s;
|
||||||
vslot.push_back(vs);
|
vslot.push_back(vs);
|
||||||
@ -155,7 +149,7 @@ void DiskChanger::InitializeVirtSlots()
|
|||||||
/* Re-create virtual slots that existed previously if possible */
|
/* Re-create virtual slots that existed previously if possible */
|
||||||
for (m = 0; m < (int)magazine.size(); m++) {
|
for (m = 0; m < (int)magazine.size(); m++) {
|
||||||
/* Create slots if needed to match max slot used by previous magazines */
|
/* Create slots if needed to match max slot used by previous magazines */
|
||||||
last = magazine[m].prev_start_slot + magazine[m].prev_num_slots;
|
last = magazine[m].prev_start_slot + magazine[m].prev_num_slots - 1;
|
||||||
if (last >= (int)vslot.size()) {
|
if (last >= (int)vslot.size()) {
|
||||||
vs.clear();
|
vs.clear();
|
||||||
while ((int)vslot.size() <= last) {
|
while ((int)vslot.size() <= last) {
|
||||||
@ -165,11 +159,11 @@ void DiskChanger::InitializeVirtSlots()
|
|||||||
}
|
}
|
||||||
/* Check this magazine's slots */
|
/* Check this magazine's slots */
|
||||||
if (magazine[m].empty()) {
|
if (magazine[m].empty()) {
|
||||||
log.Info("magazine %d is not mounted", m);
|
vlog.Info("magazine %d is not mounted", m);
|
||||||
/* magazine is not currently mounted, so will have no slots assigned */
|
/* magazine is not currently mounted, so will have no slots assigned */
|
||||||
if (magazine[m].prev_start_slot) {
|
if (magazine[m].prev_start_slot) {
|
||||||
/* Since it was previously mounted, an 'update slots' is needed */
|
/* Since it was previously mounted, an 'update slots' is needed */
|
||||||
log.Warning("update slots needed. magazine %d no longer mounted; previous: %d volumes in slots %d-%d", m,
|
vlog.Warning("update slots needed. magazine %d no longer mounted; previous: %d volumes in slots %d-%d", m,
|
||||||
magazine[m].prev_num_slots, magazine[m].prev_start_slot,
|
magazine[m].prev_num_slots, magazine[m].prev_start_slot,
|
||||||
magazine[m].prev_start_slot + magazine[m].prev_num_slots - 1);
|
magazine[m].prev_start_slot + magazine[m].prev_num_slots - 1);
|
||||||
needs_update = true;
|
needs_update = true;
|
||||||
@ -177,12 +171,12 @@ void DiskChanger::InitializeVirtSlots()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Magazine is currently mounted, so check for change in slot assignment */
|
/* Magazine is currently mounted, so check for change in slot assignment */
|
||||||
log.Info("magazine %d has %d volumes on %s", m, magazine[m].num_slots,
|
vlog.Info("magazine %d has %d volumes on %s", m, magazine[m].num_slots,
|
||||||
magazine[m].mountpoint.c_str());
|
magazine[m].mountpoint.c_str());
|
||||||
if (magazine[m].num_slots != magazine[m].prev_num_slots) {
|
if (magazine[m].num_slots != magazine[m].prev_num_slots) {
|
||||||
/* Number of volumes has changed or magazine was not previously mounted, so
|
/* Number of volumes has changed or magazine was not previously mounted, so
|
||||||
* needs new slot assignment and also 'update slots' will be needed */
|
* needs new slot assignment and also 'update slots' will be needed */
|
||||||
log.Warning("update slots needed. magazine %d has %d volumes, previously had %d", m,
|
vlog.Warning("update slots needed. magazine %d has %d volumes, previously had %d", m,
|
||||||
magazine[m].num_slots, magazine[m].prev_num_slots);
|
magazine[m].num_slots, magazine[m].prev_num_slots);
|
||||||
needs_update = true;
|
needs_update = true;
|
||||||
continue;
|
continue;
|
||||||
@ -194,7 +188,7 @@ void DiskChanger::InitializeVirtSlots()
|
|||||||
/* Magazine is mounted, was previously mounted, and has the same volume count,
|
/* Magazine is mounted, was previously mounted, and has the same volume count,
|
||||||
* so attempt to assign to the same slots previously assigned */
|
* so attempt to assign to the same slots previously assigned */
|
||||||
found = false;
|
found = false;
|
||||||
for (v = magazine[m].prev_start_slot; v < (int)vslot.size(); v++) {
|
for (v = magazine[m].prev_start_slot; v < magazine[m].prev_start_slot + magazine[m].prev_num_slots; v++) {
|
||||||
if (!vslot[v].empty()) {
|
if (!vslot[v].empty()) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
@ -204,7 +198,7 @@ void DiskChanger::InitializeVirtSlots()
|
|||||||
/* Slot used previously has already been assigned to another magazine.
|
/* Slot used previously has already been assigned to another magazine.
|
||||||
* Magazine will need to be assigned a new slot range, so an
|
* Magazine will need to be assigned a new slot range, so an
|
||||||
* 'update slots' will also be needed. */
|
* 'update slots' will also be needed. */
|
||||||
log.Warning("update slots needed. magazine %d previous slots %d-%d are not available", m,
|
vlog.Warning("update slots needed. magazine %d previous slots %d-%d are not available", m,
|
||||||
magazine[m].prev_start_slot, magazine[m].prev_start_slot + magazine[m].prev_num_slots - 1);
|
magazine[m].prev_start_slot, magazine[m].prev_start_slot + magazine[m].prev_num_slots - 1);
|
||||||
needs_update = true;
|
needs_update = true;
|
||||||
continue;
|
continue;
|
||||||
@ -216,7 +210,7 @@ void DiskChanger::InitializeVirtSlots()
|
|||||||
vslot[v].mag_bay = m;
|
vslot[v].mag_bay = m;
|
||||||
vslot[v].mag_slot = s;
|
vslot[v].mag_slot = s;
|
||||||
}
|
}
|
||||||
log.Notice("%d volumes on magazine %d assigned slots %d-%d", magazine[m].num_slots, m,
|
vlog.Notice("%d volumes on magazine %d assigned slots %d-%d", magazine[m].num_slots, m,
|
||||||
magazine[m].start_slot, magazine[m].start_slot + magazine[m].num_slots - 1);
|
magazine[m].start_slot, magazine[m].start_slot + magazine[m].num_slots - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +224,7 @@ void DiskChanger::InitializeVirtSlots()
|
|||||||
vslot[v].mag_bay = m;
|
vslot[v].mag_bay = m;
|
||||||
vslot[v].mag_slot = s;
|
vslot[v].mag_slot = s;
|
||||||
}
|
}
|
||||||
log.Notice("%d volumes on magazine %d assigned slots %d-%d", magazine[m].num_slots, m,
|
vlog.Notice("%d volumes on magazine %d assigned slots %d-%d", magazine[m].num_slots, m,
|
||||||
magazine[m].start_slot, magazine[m].start_slot + magazine[m].num_slots - 1);
|
magazine[m].start_slot, magazine[m].start_slot + magazine[m].num_slots - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,7 +257,7 @@ int DiskChanger::InitializeDrives()
|
|||||||
if (!d) {
|
if (!d) {
|
||||||
rc = errno;
|
rc = errno;
|
||||||
verr.SetErrorWithErrno(rc, "error %d accessing work directory", rc);
|
verr.SetErrorWithErrno(rc, "error %d accessing work directory", rc);
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
de = readdir(d);
|
de = readdir(d);
|
||||||
@ -297,7 +291,7 @@ int DiskChanger::InitializeDrives()
|
|||||||
drive.push_back(ds);
|
drive.push_back(ds);
|
||||||
/* Attempt to restore drive's last state */
|
/* Attempt to restore drive's last state */
|
||||||
if (RestoreDriveState(n)) {
|
if (RestoreDriveState(n)) {
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -351,7 +345,7 @@ int DiskChanger::CreateDriveSymlink(int drv)
|
|||||||
lname[rc] = 0;
|
lname[rc] = 0;
|
||||||
if (fname == lname) {
|
if (fname == lname) {
|
||||||
/* symlink already exists */
|
/* symlink already exists */
|
||||||
log.Info("found symlink for drive %d -> %s", drv, fname.c_str());
|
vlog.Info("found symlink for drive %d -> %s", drv, fname.c_str());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* Symlink points to wrong mountpoint, so delete and re-create */
|
/* Symlink points to wrong mountpoint, so delete and re-create */
|
||||||
@ -362,7 +356,7 @@ int DiskChanger::CreateDriveSymlink(int drv)
|
|||||||
verr.SetErrorWithErrno(rc, "error %d creating symlink for drive %d", rc, drv);
|
verr.SetErrorWithErrno(rc, "error %d creating symlink for drive %d", rc, drv);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
log.Notice("created symlink for drive %d -> %s", drv, fname.c_str());
|
vlog.Notice("created symlink for drive %d -> %s", drv, fname.c_str());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,7 +383,7 @@ int DiskChanger::RemoveDriveSymlink(int drv)
|
|||||||
verr.SetErrorWithErrno(errno, "error %d deleting symlink for drive %d: ", rc, drv);
|
verr.SetErrorWithErrno(errno, "error %d deleting symlink for drive %d: ", rc, drv);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
log.Notice("deleted symlink for drive %d", drv);
|
vlog.Notice("deleted symlink for drive %d", drv);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,7 +410,7 @@ int DiskChanger::SaveDriveState(int drv)
|
|||||||
tFormat(sname, "%s%sdrive_state-%d", conf.work_dir.c_str(), DIR_DELIM, drv);
|
tFormat(sname, "%s%sdrive_state-%d", conf.work_dir.c_str(), DIR_DELIM, drv);
|
||||||
if (drive[drv].empty()) {
|
if (drive[drv].empty()) {
|
||||||
if (access(sname.c_str(), F_OK) == 0) {
|
if (access(sname.c_str(), F_OK) == 0) {
|
||||||
log.Notice("deleted state file for drive %d", drv);
|
vlog.Notice("deleted state file for drive %d", drv);
|
||||||
}
|
}
|
||||||
unlink(sname.c_str());
|
unlink(sname.c_str());
|
||||||
return 0;
|
return 0;
|
||||||
@ -443,7 +437,7 @@ int DiskChanger::SaveDriveState(int drv)
|
|||||||
}
|
}
|
||||||
fclose(FS);
|
fclose(FS);
|
||||||
umask(old_mask);
|
umask(old_mask);
|
||||||
log.Notice("wrote state file for drive %d", drv);
|
vlog.Notice("wrote state file for drive %d", drv);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -477,7 +471,7 @@ int DiskChanger::RestoreDriveState(int drv)
|
|||||||
if (stat(sname.c_str(), &st)) {
|
if (stat(sname.c_str(), &st)) {
|
||||||
/* drive state file not found, so drive is not loaded */
|
/* drive state file not found, so drive is not loaded */
|
||||||
RemoveDriveSymlink(drv);
|
RemoveDriveSymlink(drv);
|
||||||
log.Info("drive %d previously unloaded", drv);
|
vlog.Info("drive %d previously unloaded", drv);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* Read loaded volume info from state file */
|
/* Read loaded volume info from state file */
|
||||||
@ -526,7 +520,7 @@ int DiskChanger::RestoreDriveState(int drv)
|
|||||||
}
|
}
|
||||||
if (v >= (int)vslot.size()) {
|
if (v >= (int)vslot.size()) {
|
||||||
/* Volume last loaded is no longer available. Change state to unloaded. */
|
/* Volume last loaded is no longer available. Change state to unloaded. */
|
||||||
log.Notice("volume %s no longer available, unloading drive %d",
|
vlog.Notice("volume %s no longer available, unloading drive %d",
|
||||||
labl.c_str(), drv);
|
labl.c_str(), drv);
|
||||||
unlink(sname.c_str());
|
unlink(sname.c_str());
|
||||||
RemoveDriveSymlink(drv);
|
RemoveDriveSymlink(drv);
|
||||||
@ -538,7 +532,7 @@ int DiskChanger::RestoreDriveState(int drv)
|
|||||||
if ((rc = CreateDriveSymlink(drv)) != 0) {
|
if ((rc = CreateDriveSymlink(drv)) != 0) {
|
||||||
/* Unable to create symlink */
|
/* Unable to create symlink */
|
||||||
drive[drv].vs = -1;
|
drive[drv].vs = -1;
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -546,7 +540,7 @@ int DiskChanger::RestoreDriveState(int drv)
|
|||||||
vslot[v].drv = drv;
|
vslot[v].drv = drv;
|
||||||
m = vslot[v].mag_bay;
|
m = vslot[v].mag_bay;
|
||||||
ms = vslot[v].mag_slot;
|
ms = vslot[v].mag_slot;
|
||||||
log.Notice("drive %d previously loaded from slot %d (%s)", drv, v, magazine[m].GetVolumeLabel(ms));
|
vlog.Notice("drive %d previously loaded from slot %d (%s)", drv, v, magazine[m].GetVolumeLabel(ms));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -562,7 +556,6 @@ int DiskChanger::RestoreDriveState(int drv)
|
|||||||
int DiskChanger::Initialize()
|
int DiskChanger::Initialize()
|
||||||
{
|
{
|
||||||
/* Make sure we have a lock on this changer */
|
/* Make sure we have a lock on this changer */
|
||||||
if (Lock()) return verr.GetError();
|
|
||||||
magazine.clear();
|
magazine.clear();
|
||||||
vslot.clear();
|
vslot.clear();
|
||||||
drive.clear();
|
drive.clear();
|
||||||
@ -591,38 +584,38 @@ int DiskChanger::LoadDrive(int drv, int slot)
|
|||||||
{
|
{
|
||||||
int rc, m, ms;
|
int rc, m, ms;
|
||||||
|
|
||||||
if (!changer_lock) {
|
|
||||||
verr.SetError(EINVAL, "changer not initialized");
|
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
|
||||||
return EINVAL;
|
|
||||||
}
|
|
||||||
if (drv < 0) {
|
if (drv < 0) {
|
||||||
verr.SetError(EINVAL, "invalid drive number %d", drv);
|
verr.SetError(EINVAL, "invalid drive number %d", drv);
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
SetMaxDrive(drv);
|
SetMaxDrive(drv);
|
||||||
if (slot < 1 || slot >= (int)vslot.size()) {
|
if (slot < 1 || slot >= (int)vslot.size()) {
|
||||||
verr.SetError(EINVAL, "cannot load drive %d from invalid slot %d", drv, slot);
|
verr.SetError(EINVAL, "cannot load drive %d from invalid slot %d", drv, slot);
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
if (!drive[drv].empty()) {
|
if (!drive[drv].empty()) {
|
||||||
if (drive[drv].vs == slot) return 0; /* already loaded from this slot */
|
if (drive[drv].vs == slot) return 0; /* already loaded from this slot */
|
||||||
verr.SetError(EBUSY, "drive %d already loaded from slot %d", drv, slot);
|
verr.SetError(EBUSY, "drive %d already loaded from slot %d", drv, slot);
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
return EBUSY;
|
return EBUSY;
|
||||||
}
|
}
|
||||||
|
if (vslot[slot].drv >= 0) {
|
||||||
|
verr.SetError(EINVAL, "requested slot %d already loaded in drive %d", slot, drv);
|
||||||
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
|
return ENOENT;
|
||||||
|
}
|
||||||
if (vslot[slot].empty()) {
|
if (vslot[slot].empty()) {
|
||||||
verr.SetError(EINVAL, "cannot load drive %d from empty slot %d", drv, slot);
|
verr.SetError(EINVAL, "cannot load drive %d from empty slot %d", drv, slot);
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
return ENOENT;
|
return ENOENT;
|
||||||
}
|
}
|
||||||
/* Create symlink for drive pointing to volume file */
|
/* Create symlink for drive pointing to volume file */
|
||||||
drive[drv].vs = slot;
|
drive[drv].vs = slot;
|
||||||
if ((rc = CreateDriveSymlink(drv))) {
|
if ((rc = CreateDriveSymlink(drv))) {
|
||||||
drive[drv].vs = -1;
|
drive[drv].vs = -1;
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
/* Save state of newly loaded drive */
|
/* Save state of newly loaded drive */
|
||||||
@ -630,14 +623,14 @@ int DiskChanger::LoadDrive(int drv, int slot)
|
|||||||
/* Error writing drive state file */
|
/* Error writing drive state file */
|
||||||
RemoveDriveSymlink(drv);
|
RemoveDriveSymlink(drv);
|
||||||
drive[drv].vs = -1;
|
drive[drv].vs = -1;
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
/* Assign virtual slot to drive */
|
/* Assign virtual slot to drive */
|
||||||
vslot[slot].drv = drv;
|
vslot[slot].drv = drv;
|
||||||
m = vslot[slot].mag_bay;
|
m = vslot[slot].mag_bay;
|
||||||
ms = vslot[slot].mag_slot;
|
ms = vslot[slot].mag_slot;
|
||||||
log.Notice("loaded drive %d from slot %d (%s)", drv, slot, magazine[m].GetVolumeLabel(ms));
|
vlog.Notice("loaded drive %d from slot %d (%s)", drv, slot, magazine[m].GetVolumeLabel(ms));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -652,14 +645,9 @@ int DiskChanger::UnloadDrive(int drv)
|
|||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (!changer_lock) {
|
|
||||||
verr.SetError(EINVAL, "changer not initialized");
|
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
|
||||||
return EINVAL;
|
|
||||||
}
|
|
||||||
if (drv < 0) {
|
if (drv < 0) {
|
||||||
verr.SetError(EINVAL, "invalid drive number %d", drv);
|
verr.SetError(EINVAL, "invalid drive number %d", drv);
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
SetMaxDrive(drv);
|
SetMaxDrive(drv);
|
||||||
@ -669,7 +657,7 @@ int DiskChanger::UnloadDrive(int drv)
|
|||||||
}
|
}
|
||||||
/* Remove drive's symlink */
|
/* Remove drive's symlink */
|
||||||
if ((rc = RemoveDriveSymlink(drv)) != 0) {
|
if ((rc = RemoveDriveSymlink(drv)) != 0) {
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
/* Remove virtual slot assignment */
|
/* Remove virtual slot assignment */
|
||||||
@ -677,10 +665,10 @@ int DiskChanger::UnloadDrive(int drv)
|
|||||||
drive[drv].vs = -1;
|
drive[drv].vs = -1;
|
||||||
/* Update drive state file (will delete state file due to negative slot number) */
|
/* Update drive state file (will delete state file due to negative slot number) */
|
||||||
if ((rc = SaveDriveState(drv)) != 0) {
|
if ((rc = SaveDriveState(drv)) != 0) {
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
log.Notice("unloaded drive %d", drv);
|
vlog.Notice("unloaded drive %d", drv);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -699,26 +687,21 @@ int DiskChanger::CreateVolumes(int bay, int count, int start, const char *label_
|
|||||||
tString label, label_prefix(label_prefix_in);
|
tString label, label_prefix(label_prefix_in);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!changer_lock) {
|
|
||||||
verr.SetError(EINVAL, "changer not initialized");
|
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (bay < 0 || bay >= (int)magazine.size()) {
|
if (bay < 0 || bay >= (int)magazine.size()) {
|
||||||
verr.SetError(EINVAL, "invalid magazine");
|
verr.SetError(EINVAL, "invalid magazine");
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (count < 1) count = 1;
|
if (count < 1) count = 1;
|
||||||
tStrip(tRemoveEOL(label_prefix));
|
tStrip(tRemoveEOL(label_prefix));
|
||||||
if (label_prefix.empty()) {
|
if (label_prefix.empty()) {
|
||||||
/* Default prefix is storage-name_magazine-number */
|
/* Default prefix is storage-name_magazine-number */
|
||||||
tFormat(label_prefix, "%s_%d_", conf.storage_name.c_str(), bay);
|
tFormat(label_prefix, "%s_%04d_", conf.storage_name.c_str(), bay);
|
||||||
}
|
}
|
||||||
if (start < 0) {
|
if (start < 0) {
|
||||||
/* Find highest uniqueness number for this filename prefix */
|
/* Find highest uniqueness number for this filename prefix */
|
||||||
for (i = magazine[bay].num_slots * 5; i > 0; i--) {
|
for (i = magazine[bay].num_slots * 5; i > 0; i--) {
|
||||||
tFormat(label, "%s_%d", label_prefix.c_str(), i);
|
tFormat(label, "%s%04d", label_prefix.c_str(), i);
|
||||||
if (magazine[bay].GetVolumeSlot(label) >= 0) break;
|
if (magazine[bay].GetVolumeSlot(label) >= 0) break;
|
||||||
}
|
}
|
||||||
start = i;
|
start = i;
|
||||||
@ -733,6 +716,7 @@ int DiskChanger::CreateVolumes(int bay, int count, int start, const char *label_
|
|||||||
}
|
}
|
||||||
fprintf(stdout, "creating label '%s'\n", label.c_str());
|
fprintf(stdout, "creating label '%s'\n", label.c_str());
|
||||||
if (magazine[bay].CreateVolume(label)) {
|
if (magazine[bay].CreateVolume(label)) {
|
||||||
|
/* On failure, update magazine state if any were created */
|
||||||
if (i) magazine[bay].save();
|
if (i) magazine[bay].save();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -743,61 +727,7 @@ int DiskChanger::CreateVolumes(int bay, int count, int start, const char *label_
|
|||||||
/* New mag state will require 'update slots' and 'label barcodes' in Bacula */
|
/* New mag state will require 'update slots' and 'label barcodes' in Bacula */
|
||||||
needs_update = true;
|
needs_update = true;
|
||||||
needs_label = true;
|
needs_label = true;
|
||||||
log.Notice("update slots needed. %d volumes added to magazine %d",count , bay);
|
vlog.Notice("%d volumes added to magazine %d",count , bay);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
|
||||||
* Method to cause Bacula to update its catalog to reflect
|
|
||||||
* changes in the available volumes
|
|
||||||
*-------------------------------------------------*/
|
|
||||||
int DiskChanger::UpdateBacula()
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
FILE *update_lock;
|
|
||||||
tString cmd;
|
|
||||||
char lockfile[4096];
|
|
||||||
|
|
||||||
/* Check if update needed */
|
|
||||||
if (!needs_update && !needs_label) return 0; /* Nothing to do */
|
|
||||||
/* Create update lock lockfile */
|
|
||||||
snprintf(lockfile, sizeof(lockfile), "%s%s%s.updatelock", conf.work_dir.c_str(), DIR_DELIM,
|
|
||||||
conf.storage_name.c_str());
|
|
||||||
rc = exclusive_fopen(lockfile, &update_lock);
|
|
||||||
if (rc == EEXIST) {
|
|
||||||
/* Update already in progress in another process, so skip */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (rc) {
|
|
||||||
/* error creating lockfile, so skip */
|
|
||||||
log.Error("bconsole: errno=%d creating update lockfile", rc);
|
|
||||||
if (needs_update)
|
|
||||||
log.Error("WARNING! 'update slots' needed in bconsole");
|
|
||||||
if (needs_label)
|
|
||||||
log.Error("WARNING! 'label barcodes' needed in bconsole");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
log.Debug("created update lockfile for pid %d", getpid());
|
|
||||||
/* Perform update slots command in bconsole */
|
|
||||||
if (needs_update) {
|
|
||||||
/* Issue update slots command in bconsole */
|
|
||||||
tFormat(cmd, "update slots storage=\"%s\"", conf.storage_name.c_str());
|
|
||||||
if(issue_bconsole_command(cmd.c_str())) {
|
|
||||||
log.Error("WARNING! 'update slots' needed in bconsole");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Perform label barcodes command in bconsole */
|
|
||||||
if (needs_label) {
|
|
||||||
tFormat(cmd, "label storage=\"%s\" pool=\"%s\" barcodes\nyes\nyes\n", conf.storage_name.c_str(),
|
|
||||||
conf.def_pool.c_str());
|
|
||||||
if (issue_bconsole_command(cmd.c_str())) {
|
|
||||||
log.Error("WARNING! 'label barcodes' needed in bconsole");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Obtain changer lock before removing update lock */
|
|
||||||
fclose(update_lock);
|
|
||||||
unlink(lockfile);
|
|
||||||
log.Debug("removed update lockfile for pid %d", getpid());
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -809,7 +739,7 @@ const char* DiskChanger::GetVolumeLabel(int slot)
|
|||||||
{
|
{
|
||||||
if (slot <= 0 || slot >= (int)vslot.size()) {
|
if (slot <= 0 || slot >= (int)vslot.size()) {
|
||||||
verr.SetError(-1, "volume label request from invalid slot %d", slot);
|
verr.SetError(-1, "volume label request from invalid slot %d", slot);
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (vslot[slot].empty()) return "";
|
if (vslot[slot].empty()) return "";
|
||||||
@ -825,7 +755,7 @@ const char* DiskChanger::GetVolumePath(tString &path, int slot)
|
|||||||
path.clear();
|
path.clear();
|
||||||
if (slot <= 0 || slot >= (int)vslot.size()) {
|
if (slot <= 0 || slot >= (int)vslot.size()) {
|
||||||
verr.SetError(-1, "volume path request from invalid slot %d", slot);
|
verr.SetError(-1, "volume path request from invalid slot %d", slot);
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
vlog.Error("ERROR! %s", verr.GetErrorMsg());
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (vslot[slot].empty()) return path.c_str();
|
if (vslot[slot].empty()) return path.c_str();
|
||||||
@ -833,78 +763,6 @@ const char* DiskChanger::GetVolumePath(tString &path, int slot)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
|
||||||
* Protected method to lock changer device using a lock file such that
|
|
||||||
* only one process at a time may execute changer commands on the
|
|
||||||
* same autochanger. If another process has the lock, then this process
|
|
||||||
* will sleep 1 second before trying again. This try/wait loop will continue
|
|
||||||
* until the lock is obtained or 'timeout' seconds have expired. If
|
|
||||||
* timeout = 0 then only tries to obtain lock once. If timeout < 0
|
|
||||||
* then doesn't return until the lock is obtained.
|
|
||||||
* On success, returns true. Otherwise on error or timeout, sets
|
|
||||||
* lasterr negative and returns false.
|
|
||||||
*------------------------------------------------*/
|
|
||||||
int DiskChanger::Lock(long timeout_seconds)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
time_t timeout = 0;
|
|
||||||
char lockfile[4096];
|
|
||||||
|
|
||||||
if (changer_lock) return 0;
|
|
||||||
|
|
||||||
if (timeout_seconds < 0) {
|
|
||||||
timeout_seconds = 3600 * 24 * 365;
|
|
||||||
}
|
|
||||||
if (timeout_seconds > 0) {
|
|
||||||
timeout = time(NULL) + timeout_seconds;
|
|
||||||
}
|
|
||||||
snprintf(lockfile, sizeof(lockfile), "%s%s%s.lock", conf.work_dir.c_str(), DIR_DELIM,
|
|
||||||
conf.storage_name.c_str());
|
|
||||||
rc = exclusive_fopen(lockfile, &changer_lock);
|
|
||||||
if (rc == EEXIST && timeout == 0) {
|
|
||||||
/* timeout=0 means do not wait */
|
|
||||||
verr.SetErrorWithErrno(rc, "cannot open lockfile");
|
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
while (rc == EEXIST) {
|
|
||||||
/* sleep before trying again */
|
|
||||||
sleep(1);
|
|
||||||
if (time(NULL) > timeout) {
|
|
||||||
verr.SetError(EBUSY, "timeout waiting for lockfile");
|
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
|
||||||
return EACCES;
|
|
||||||
}
|
|
||||||
rc = exclusive_fopen(lockfile, &changer_lock);
|
|
||||||
}
|
|
||||||
if (rc) {
|
|
||||||
verr.SetErrorWithErrno(rc, "cannot open lockfile");
|
|
||||||
log.Error("ERROR! %s", verr.GetErrorMsg());
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
/* Write PID to lockfile and leave open for exclusive R/W */
|
|
||||||
fprintf(changer_lock, "%d", getpid());
|
|
||||||
fflush(changer_lock);
|
|
||||||
log.Debug("created lockfile for pid %d", getpid());
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
|
||||||
* Protected method to unlock changer device
|
|
||||||
*------------------------------------------------*/
|
|
||||||
void DiskChanger::Unlock()
|
|
||||||
{
|
|
||||||
char lockfile[4096];
|
|
||||||
if (!changer_lock) return;
|
|
||||||
fclose(changer_lock);
|
|
||||||
changer_lock = NULL;
|
|
||||||
snprintf(lockfile, sizeof(lockfile), "%s%s%s.lock", conf.work_dir.c_str(), DIR_DELIM,
|
|
||||||
conf.storage_name.c_str());
|
|
||||||
log.Debug("removing lockfile for pid %d", getpid());
|
|
||||||
unlink(lockfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
* Method returns true if magazine is not mounted,
|
* Method returns true if magazine is not mounted,
|
||||||
* else returns false.
|
* else returns false.
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
*
|
*
|
||||||
* This file is part of vchanger by Josh Fisher.
|
* This file is part of vchanger by Josh Fisher.
|
||||||
*
|
*
|
||||||
* vchanger copyright (C) 2008-2015 Josh Fisher
|
* vchanger copyright (C) 2008-2020 Josh Fisher
|
||||||
*
|
*
|
||||||
* vchanger is free software.
|
* vchanger is free software.
|
||||||
* You may redistribute it and/or modify it under the terms of the
|
* You may redistribute it and/or modify it under the terms of the
|
||||||
@ -30,13 +30,12 @@
|
|||||||
class DiskChanger
|
class DiskChanger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DiskChanger() : changer_lock(NULL), needs_update(false), needs_label(false) {}
|
DiskChanger() : needs_update(false), needs_label(false) {}
|
||||||
virtual ~DiskChanger();
|
virtual ~DiskChanger() {};
|
||||||
int Initialize();
|
int Initialize();
|
||||||
int LoadDrive(int drv, int slot);
|
int LoadDrive(int drv, int slot);
|
||||||
int UnloadDrive(int drv);
|
int UnloadDrive(int drv);
|
||||||
int CreateVolumes(int bay, int count, int start = -1, const char *label_prefix = "");
|
int CreateVolumes(int bay, int count, int start = -1, const char *label_prefix = "");
|
||||||
int UpdateBacula();
|
|
||||||
const char* GetVolumeLabel(int slot);
|
const char* GetVolumeLabel(int slot);
|
||||||
const char* GetVolumePath(tString &fname, int slot);
|
const char* GetVolumePath(tString &fname, int slot);
|
||||||
bool MagazineEmpty(int bay) const;
|
bool MagazineEmpty(int bay) const;
|
||||||
@ -54,8 +53,6 @@ public:
|
|||||||
inline const char* GetErrorMsg() const { return verr.GetErrorMsg(); }
|
inline const char* GetErrorMsg() const { return verr.GetErrorMsg(); }
|
||||||
inline bool NeedsUpdate() const { return needs_update; }
|
inline bool NeedsUpdate() const { return needs_update; }
|
||||||
inline bool NeedsLabel() const { return needs_label; }
|
inline bool NeedsLabel() const { return needs_label; }
|
||||||
int Lock(long timeout = 30);
|
|
||||||
void Unlock();
|
|
||||||
protected:
|
protected:
|
||||||
void InitializeMagazines();
|
void InitializeMagazines();
|
||||||
int FindEmptySlotRange(int count);
|
int FindEmptySlotRange(int count);
|
||||||
@ -67,7 +64,6 @@ protected:
|
|||||||
int SaveDriveState(int drv);
|
int SaveDriveState(int drv);
|
||||||
int RestoreDriveState(int drv);
|
int RestoreDriveState(int drv);
|
||||||
protected:
|
protected:
|
||||||
FILE *changer_lock;
|
|
||||||
bool needs_update;
|
bool needs_update;
|
||||||
bool needs_label;
|
bool needs_label;
|
||||||
ErrorHandler verr;
|
ErrorHandler verr;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* loghandler.cpp
|
/* loghandler.cpp
|
||||||
*
|
*
|
||||||
* Copyright (C) 2013-2014 Josh Fisher
|
* Copyright (C) 2013-2018 Josh Fisher
|
||||||
*
|
*
|
||||||
* This program is free software. You may redistribute it and/or modify
|
* This program is free software. You may redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License, as published by
|
* it under the terms of the GNU General Public License, as published by
|
||||||
@ -22,6 +22,9 @@
|
|||||||
#ifdef HAVE_STDIO_H
|
#ifdef HAVE_STDIO_H
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
#ifdef HAVE_TIME_H
|
#ifdef HAVE_TIME_H
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#endif
|
#endif
|
||||||
@ -34,13 +37,11 @@
|
|||||||
#ifdef HAVE_STDARG_H
|
#ifdef HAVE_STDARG_H
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#endif
|
#endif
|
||||||
#ifndef HAVE_LOCALTIME_R
|
|
||||||
#include "compat/localtime_r.h"
|
#include "compat/localtime_r.h"
|
||||||
#endif
|
|
||||||
#define LOGHANDLER_SOURCE 1
|
#define LOGHANDLER_SOURCE 1
|
||||||
#include "loghandler.h"
|
#include "loghandler.h"
|
||||||
|
|
||||||
LogHandler log;
|
LogHandler vlog;
|
||||||
|
|
||||||
LogHandler::LogHandler() : use_syslog(false), max_debug_level(LOG_WARNING), errfs(stderr)
|
LogHandler::LogHandler() : use_syslog(false), max_debug_level(LOG_WARNING), errfs(stderr)
|
||||||
{
|
{
|
||||||
@ -179,7 +180,7 @@ void LogHandler::WriteLog(int priority, const char *fmt, va_list vl)
|
|||||||
size_t n;
|
size_t n;
|
||||||
struct tm bt;
|
struct tm bt;
|
||||||
time_t t;
|
time_t t;
|
||||||
char buf[1024];
|
char ftim[128], buf[4096];
|
||||||
Lock();
|
Lock();
|
||||||
if (priority > max_debug_level || priority < LOG_EMERG || !fmt) {
|
if (priority > max_debug_level || priority < LOG_EMERG || !fmt) {
|
||||||
Unlock();
|
Unlock();
|
||||||
@ -187,8 +188,8 @@ void LogHandler::WriteLog(int priority, const char *fmt, va_list vl)
|
|||||||
}
|
}
|
||||||
t = time(NULL);
|
t = time(NULL);
|
||||||
localtime_r(&t, &bt);
|
localtime_r(&t, &bt);
|
||||||
strftime(buf, 100, "%b %d %T: ", &bt);
|
strftime(ftim, 100, "%b %d %T: ", &bt);
|
||||||
strncpy(buf + strlen(buf), fmt, sizeof(buf) - strlen(buf));
|
snprintf(buf, sizeof(buf), "%s [%d]: %s", ftim, getpid(), fmt);
|
||||||
if (use_syslog) vsyslog(priority, buf, vl);
|
if (use_syslog) vsyslog(priority, buf, vl);
|
||||||
else {
|
else {
|
||||||
n = strlen(buf);
|
n = strlen(buf);
|
||||||
@ -204,3 +205,17 @@ void LogHandler::WriteLog(int priority, const char *fmt, va_list vl)
|
|||||||
}
|
}
|
||||||
Unlock();
|
Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
* C wrapper to write to LogHandler object
|
||||||
|
***************************************************************************************/
|
||||||
|
|
||||||
|
extern "C" void LogHandler_write(int level, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list vl;
|
||||||
|
va_start(vl, fmt);
|
||||||
|
vlog.WriteLog(level, fmt, vl);
|
||||||
|
va_end(vl);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* loghandler.h
|
/* loghandler.h
|
||||||
*
|
*
|
||||||
* Copyright (C) 2013-2014 Josh Fisher
|
* Copyright (C) 2013-2018 Josh Fisher
|
||||||
*
|
*
|
||||||
* This program is free software. You may redistribute it and/or modify
|
* This program is free software. You may redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License, as published by
|
* it under the terms of the GNU General Public License, as published by
|
||||||
@ -32,6 +32,15 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
void LogHandler_write(int level, const char *format, ...);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
class LogHandler
|
class LogHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -50,6 +59,7 @@ public:
|
|||||||
void Debug(const char *fmt, ... );
|
void Debug(const char *fmt, ... );
|
||||||
void MajorDebug(const char *fmt, ... );
|
void MajorDebug(const char *fmt, ... );
|
||||||
inline bool UsingSyslog() { return use_syslog; }
|
inline bool UsingSyslog() { return use_syslog; }
|
||||||
|
friend void LogHandler_write(int level, const char *format, ...);
|
||||||
protected:
|
protected:
|
||||||
void Lock();
|
void Lock();
|
||||||
void Unlock();
|
void Unlock();
|
||||||
@ -64,7 +74,8 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifndef LOGHANDLER_SOURCE
|
#ifndef LOGHANDLER_SOURCE
|
||||||
extern LogHandler log;
|
extern LogHandler vlog;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _LOGHANDLER_H_ */
|
#endif /* _LOGHANDLER_H_ */
|
||||||
|
131
src/mymutex.cpp
Normal file
131
src/mymutex.cpp
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
/* mymutex.cpp
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2020 Josh Fisher
|
||||||
|
*
|
||||||
|
* This program is free software. You may redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License, as published by
|
||||||
|
* the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. See the file "COPYING". If not,
|
||||||
|
* see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#ifdef HAVE_WINDOWS_H
|
||||||
|
#include "targetver.h"
|
||||||
|
#include <windows.h>
|
||||||
|
#include "win32_util.h"
|
||||||
|
#endif
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STDINT_H
|
||||||
|
#include <stdint.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_LIMITS_H
|
||||||
|
#include <limits.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ERRNO_H
|
||||||
|
#include <errno.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_TIME_H
|
||||||
|
#include <time.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_TIME_H
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_STAT_H
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_WAIT_H
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_FCNTL_H
|
||||||
|
#include <fcntl.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SEMAPHORE_H
|
||||||
|
#include <semaphore.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "compat/semaphore.h"
|
||||||
|
#include "loghandler.h"
|
||||||
|
#include "mypopen.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function to create a mutex owned by the caller. Waits up to max_wait seconds
|
||||||
|
* for the mutex to be created. If max_wait is negative, waits indefinitely. If
|
||||||
|
* max_wait is zero, tries once to create mutex and does not block.
|
||||||
|
* On success, returns the handle of a named mutex. On error, returns zero and
|
||||||
|
* sets errno appropriately.
|
||||||
|
*/
|
||||||
|
void* mymutex_create(const char *storage_name)
|
||||||
|
{
|
||||||
|
char lockname[4096];
|
||||||
|
|
||||||
|
if (!storage_name || !storage_name[0]) {
|
||||||
|
/* Only create named mutex */
|
||||||
|
errno = EINVAL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#ifdef HAVE_WINDOWS_H
|
||||||
|
snprintf(lockname, sizeof(lockname), "vchanger-%s", storage_name);
|
||||||
|
#else
|
||||||
|
snprintf(lockname, sizeof(lockname), "/vchanger-%s", storage_name);
|
||||||
|
#endif
|
||||||
|
return (void*)sem_open(lockname, O_CREAT, 0770, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function to lock an opened mutex given by fd.
|
||||||
|
* On success, returns zero. On error, returns -1 and
|
||||||
|
* sets errno appropriately.
|
||||||
|
*/
|
||||||
|
int mymutex_lock(void *fd, time_t wait_sec)
|
||||||
|
{
|
||||||
|
struct timespec ts;
|
||||||
|
if (wait_sec == 0) return sem_trywait((sem_t*)fd);
|
||||||
|
ts.tv_sec = time(NULL) + wait_sec; /* semaphore.h functions use absolute time */
|
||||||
|
ts.tv_nsec = 0;
|
||||||
|
return sem_timedwait((sem_t*)fd, &ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function to unlock an opened mutex given by fd.
|
||||||
|
* On success, returns zero. On error, returns -1 and
|
||||||
|
* sets errno appropriately.
|
||||||
|
*/
|
||||||
|
int mymutex_unlock(void *fd)
|
||||||
|
{
|
||||||
|
return sem_post((sem_t*)fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function to destroy a mutex owned by the caller.
|
||||||
|
* On success, returns zero. On error, returns -1 and
|
||||||
|
* sets errno appropriately.
|
||||||
|
*/
|
||||||
|
void mymutex_destroy(const char *name, void *fd)
|
||||||
|
{
|
||||||
|
if (fd) {
|
||||||
|
sem_post((sem_t*)fd);
|
||||||
|
sem_close((sem_t*)fd);
|
||||||
|
}
|
||||||
|
if (name && name[0]) sem_unlink(name);
|
||||||
|
}
|
||||||
|
|
32
src/mymutex.h
Normal file
32
src/mymutex.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/* mymutex.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2020 Josh Fisher
|
||||||
|
*
|
||||||
|
* This program is free software. You may redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License, as published by
|
||||||
|
* the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. See the file "COPYING". If not,
|
||||||
|
* see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _MYMUTEX_H_
|
||||||
|
#define _MYMUTEX_H_ 1
|
||||||
|
|
||||||
|
#ifndef HAVE_TIME_H
|
||||||
|
#include <time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void* mymutex_create(const char *storage_name);
|
||||||
|
int mymutex_lock(void* fd, time_t wait_sec);
|
||||||
|
int mymutex_unlock(void* fd);
|
||||||
|
int mymutex_destroy(const char *storage_name, void* fd);
|
||||||
|
|
||||||
|
#endif /* _MYPOPEN_H_ */
|
@ -179,7 +179,7 @@ static int do_mypopen_raw(const char *cline, int *fno_stdin, int *fno_stdout, in
|
|||||||
/* Build argv array from command line string */
|
/* Build argv array from command line string */
|
||||||
if (mypopen_args(cline, argv, argc, argbuf, sizeof(argbuf))) {
|
if (mypopen_args(cline, argv, argc, argbuf, sizeof(argbuf))) {
|
||||||
/* Invalid args, so terminate child */
|
/* Invalid args, so terminate child */
|
||||||
log.Debug("popen: invalid cmdline args for child");
|
vlog.Debug("popen: invalid cmdline args for child");
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -193,7 +193,7 @@ static int do_mypopen_raw(const char *cline, int *fno_stdin, int *fno_stdout, in
|
|||||||
/* error creating pipe */
|
/* error creating pipe */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
log.Debug("popen: child stdin uses pipe (%d -> %d)", pipe_in[0], pipe_in[1]);
|
vlog.Debug("popen: child stdin uses pipe (%d -> %d)", pipe_in[0], pipe_in[1]);
|
||||||
} else if (*fno_stdin == STDIN_FILENO) {
|
} else if (*fno_stdin == STDIN_FILENO) {
|
||||||
/* Caller specified stdin so just let child inherit it */
|
/* Caller specified stdin so just let child inherit it */
|
||||||
fno_stdin = NULL;
|
fno_stdin = NULL;
|
||||||
@ -212,7 +212,7 @@ static int do_mypopen_raw(const char *cline, int *fno_stdin, int *fno_stdout, in
|
|||||||
errno = rc;
|
errno = rc;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
log.Debug("popen: child stdout uses pipe (%d -> %d)", pipe_out[0], pipe_out[1]);
|
vlog.Debug("popen: child stdout uses pipe (%d -> %d)", pipe_out[0], pipe_out[1]);
|
||||||
} else {
|
} else {
|
||||||
if (*fno_stdout == STDOUT_FILENO) fno_stdout = NULL;
|
if (*fno_stdout == STDOUT_FILENO) fno_stdout = NULL;
|
||||||
else fsync(*fno_stdout);
|
else fsync(*fno_stdout);
|
||||||
@ -231,7 +231,7 @@ static int do_mypopen_raw(const char *cline, int *fno_stdin, int *fno_stdout, in
|
|||||||
errno = rc;
|
errno = rc;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
log.Debug("popen: child stderr uses pipe (%d -> %d)", pipe_err[0], pipe_err[1]);
|
vlog.Debug("popen: child stderr uses pipe (%d -> %d)", pipe_err[0], pipe_err[1]);
|
||||||
} else {
|
} else {
|
||||||
if (*fno_stderr == STDERR_FILENO) fno_stderr = NULL;
|
if (*fno_stderr == STDERR_FILENO) fno_stderr = NULL;
|
||||||
else fsync(*fno_stderr);
|
else fsync(*fno_stderr);
|
||||||
@ -239,7 +239,7 @@ static int do_mypopen_raw(const char *cline, int *fno_stdin, int *fno_stdout, in
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* fork a child process to run the command in */
|
/* fork a child process to run the command in */
|
||||||
log.Debug("popen: forking now");
|
vlog.Debug("popen: forking now");
|
||||||
pid = fork();
|
pid = fork();
|
||||||
switch (pid)
|
switch (pid)
|
||||||
{
|
{
|
||||||
@ -251,7 +251,7 @@ static int do_mypopen_raw(const char *cline, int *fno_stdin, int *fno_stdout, in
|
|||||||
|
|
||||||
case 0: /* child is running */
|
case 0: /* child is running */
|
||||||
/* close pipe ends always used by parent */
|
/* close pipe ends always used by parent */
|
||||||
log.Debug("popen: child closing pipe ends %d,%d,%d used by parent", pipe_in[1], pipe_out[0], pipe_err[0]);
|
vlog.Debug("popen: child closing pipe ends %d,%d,%d used by parent", pipe_in[1], pipe_out[0], pipe_err[0]);
|
||||||
if (pipe_in[1] >= 0) close(pipe_in[1]);
|
if (pipe_in[1] >= 0) close(pipe_in[1]);
|
||||||
if (pipe_out[0] >= 0) close(pipe_out[0]);
|
if (pipe_out[0] >= 0) close(pipe_out[0]);
|
||||||
if (pipe_err[0] >= 0) close(pipe_err[0]);
|
if (pipe_err[0] >= 0) close(pipe_err[0]);
|
||||||
@ -259,7 +259,7 @@ static int do_mypopen_raw(const char *cline, int *fno_stdin, int *fno_stdout, in
|
|||||||
if (fno_stdin) {
|
if (fno_stdin) {
|
||||||
if (*fno_stdin < 0) {
|
if (*fno_stdin < 0) {
|
||||||
/* Read end of pipe will be child's stdin */
|
/* Read end of pipe will be child's stdin */
|
||||||
log.Debug("popen: child will read stdin from %d", pipe_in[0]);
|
vlog.Debug("popen: child will read stdin from %d", pipe_in[0]);
|
||||||
dup2(pipe_in[0], STDIN_FILENO);
|
dup2(pipe_in[0], STDIN_FILENO);
|
||||||
close(pipe_in[0]);
|
close(pipe_in[0]);
|
||||||
} else {
|
} else {
|
||||||
@ -272,7 +272,7 @@ static int do_mypopen_raw(const char *cline, int *fno_stdin, int *fno_stdout, in
|
|||||||
if (fno_stdout) {
|
if (fno_stdout) {
|
||||||
if (*fno_stdout < 0) {
|
if (*fno_stdout < 0) {
|
||||||
/* Write end of pipe will be child's stdout */
|
/* Write end of pipe will be child's stdout */
|
||||||
log.Debug("popen: child will write stdout to %d", pipe_out[1]);
|
vlog.Debug("popen: child will write stdout to %d", pipe_out[1]);
|
||||||
dup2(pipe_out[1], STDOUT_FILENO);
|
dup2(pipe_out[1], STDOUT_FILENO);
|
||||||
close(pipe_out[1]);
|
close(pipe_out[1]);
|
||||||
} else {
|
} else {
|
||||||
@ -285,7 +285,7 @@ static int do_mypopen_raw(const char *cline, int *fno_stdin, int *fno_stdout, in
|
|||||||
if (fno_stderr) {
|
if (fno_stderr) {
|
||||||
if (*fno_stderr < 0) {
|
if (*fno_stderr < 0) {
|
||||||
/* Write end of pipe will be child's stderr */
|
/* Write end of pipe will be child's stderr */
|
||||||
log.Debug("popen: child will write stderr to %d", pipe_err[1]);
|
vlog.Debug("popen: child will write stderr to %d", pipe_err[1]);
|
||||||
dup2(pipe_err[1], STDERR_FILENO);
|
dup2(pipe_err[1], STDERR_FILENO);
|
||||||
close(pipe_err[1]);
|
close(pipe_err[1]);
|
||||||
} else {
|
} else {
|
||||||
@ -295,7 +295,7 @@ static int do_mypopen_raw(const char *cline, int *fno_stdin, int *fno_stdout, in
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* now run the command */
|
/* now run the command */
|
||||||
log.Debug("popen: child executing '%s'", argv[0]);
|
vlog.Debug("popen: child executing '%s'", argv[0]);
|
||||||
execvp(argv[0], argv);
|
execvp(argv[0], argv);
|
||||||
/* only gets here if execvp fails */
|
/* only gets here if execvp fails */
|
||||||
return -1;
|
return -1;
|
||||||
@ -304,7 +304,7 @@ static int do_mypopen_raw(const char *cline, int *fno_stdin, int *fno_stdout, in
|
|||||||
/* parent is running this */
|
/* parent is running this */
|
||||||
|
|
||||||
/* close pipe ends always used by child */
|
/* close pipe ends always used by child */
|
||||||
log.Debug("popen: parent closing pipe ends %d,%d,%d used by child", pipe_in[0], pipe_out[1], pipe_err[1]);
|
vlog.Debug("popen: parent closing pipe ends %d,%d,%d used by child", pipe_in[0], pipe_out[1], pipe_err[1]);
|
||||||
if (pipe_in[0] >= 0) close(pipe_in[0]);
|
if (pipe_in[0] >= 0) close(pipe_in[0]);
|
||||||
if (pipe_out[1] >= 0) close(pipe_out[1]);
|
if (pipe_out[1] >= 0) close(pipe_out[1]);
|
||||||
if (pipe_err[1] >= 0) close(pipe_err[1]);
|
if (pipe_err[1] >= 0) close(pipe_err[1]);
|
||||||
@ -314,25 +314,25 @@ static int do_mypopen_raw(const char *cline, int *fno_stdin, int *fno_stdout, in
|
|||||||
if (*fno_stdin < 0) {
|
if (*fno_stdin < 0) {
|
||||||
/* Caller will be writing to child's stdin through pipe */
|
/* Caller will be writing to child's stdin through pipe */
|
||||||
*fno_stdin = pipe_in[1];
|
*fno_stdin = pipe_in[1];
|
||||||
log.Debug("popen: parent writes child's stdin to %d", pipe_in[1]);
|
vlog.Debug("popen: parent writes child's stdin to %d", pipe_in[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fno_stdout) {
|
if (fno_stdout) {
|
||||||
if (*fno_stdout < 0) {
|
if (*fno_stdout < 0) {
|
||||||
/* Caller will be reading from child's stdout through pipe */
|
/* Caller will be reading from child's stdout through pipe */
|
||||||
*fno_stdout = pipe_out[0];
|
*fno_stdout = pipe_out[0];
|
||||||
log.Debug("popen: parent reads child's stdout from %d", pipe_out[0]);
|
vlog.Debug("popen: parent reads child's stdout from %d", pipe_out[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fno_stderr) {
|
if (fno_stderr) {
|
||||||
if (*fno_stderr < 0) {
|
if (*fno_stderr < 0) {
|
||||||
/* Caller will be reading from child's stderr through pipe */
|
/* Caller will be reading from child's stderr through pipe */
|
||||||
*fno_stderr = pipe_err[0];
|
*fno_stderr = pipe_err[0];
|
||||||
log.Debug("popen: parent reads child's stderr from %d", pipe_err[0]);
|
vlog.Debug("popen: parent reads child's stderr from %d", pipe_err[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//sleep(2);
|
//sleep(2);
|
||||||
log.Debug("popen: parent returning pid=%d of child", pid);
|
vlog.Debug("popen: parent returning pid=%d of child", pid);
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -360,7 +360,7 @@ static int do_mypopen_raw(const char *cline, int *fno_stdin, int *fno_stdout, in
|
|||||||
/* Build argv array from command line string */
|
/* Build argv array from command line string */
|
||||||
if (mypopen_args(cline, argv, argc, argbuf, sizeof(argbuf))) {
|
if (mypopen_args(cline, argv, argc, argbuf, sizeof(argbuf))) {
|
||||||
/* Invalid args, so terminate child */
|
/* Invalid args, so terminate child */
|
||||||
log.Debug("popen: invalid cmdline args for child");
|
vlog.Debug("popen: invalid cmdline args for child");
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -375,7 +375,7 @@ static int do_mypopen_raw(const char *cline, int *fno_stdin, int *fno_stdout, in
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
child_in = pipe_in[0];
|
child_in = pipe_in[0];
|
||||||
log.Debug("popen: child stdin uses pipe (%d -> %d)", pipe_in[0], pipe_in[1]);
|
vlog.Debug("popen: child stdin uses pipe (%d -> %d)", pipe_in[0], pipe_in[1]);
|
||||||
} else {
|
} else {
|
||||||
if (*fno_stdin != STDIN_FILENO) {
|
if (*fno_stdin != STDIN_FILENO) {
|
||||||
/* Caller supplied an open file to use as child's stdin */
|
/* Caller supplied an open file to use as child's stdin */
|
||||||
@ -397,7 +397,7 @@ static int do_mypopen_raw(const char *cline, int *fno_stdin, int *fno_stdout, in
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
child_out = pipe_out[1];
|
child_out = pipe_out[1];
|
||||||
log.Debug("popen: child stdout uses pipe (%d -> %d)", pipe_out[0], pipe_out[1]);
|
vlog.Debug("popen: child stdout uses pipe (%d -> %d)", pipe_out[0], pipe_out[1]);
|
||||||
} else {
|
} else {
|
||||||
if (*fno_stdout != STDOUT_FILENO) {
|
if (*fno_stdout != STDOUT_FILENO) {
|
||||||
/* Caller supplied open file to use as child's stdout */
|
/* Caller supplied open file to use as child's stdout */
|
||||||
@ -419,7 +419,7 @@ static int do_mypopen_raw(const char *cline, int *fno_stdin, int *fno_stdout, in
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
child_err = pipe_err[1];
|
child_err = pipe_err[1];
|
||||||
log.Debug("popen: child stderr uses pipe (%d -> %d)", pipe_err[0], pipe_err[1]);
|
vlog.Debug("popen: child stderr uses pipe (%d -> %d)", pipe_err[0], pipe_err[1]);
|
||||||
} else {
|
} else {
|
||||||
if (*fno_stderr != STDERR_FILENO) {
|
if (*fno_stderr != STDERR_FILENO) {
|
||||||
/* Caller supplied an open file to use as child's stderr */
|
/* Caller supplied an open file to use as child's stderr */
|
||||||
@ -547,7 +547,7 @@ static int do_mypopen_raw(const char *cline, int *fno_stdin, int *fno_stdout, in
|
|||||||
if (pipe_out[0] >= 0) *fno_stdout = pipe_out[0];
|
if (pipe_out[0] >= 0) *fno_stdout = pipe_out[0];
|
||||||
if (pipe_err[0] >= 0) *fno_stderr = pipe_err[0];
|
if (pipe_err[0] >= 0) *fno_stderr = pipe_err[0];
|
||||||
|
|
||||||
log.Debug("popen: parent returning pid=%d of child", pid);
|
vlog.Debug("popen: parent returning pid=%d of child", pid);
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
*
|
*
|
||||||
* This file is part of vchanger by Josh Fisher.
|
* This file is part of vchanger by Josh Fisher.
|
||||||
*
|
*
|
||||||
* vchanger copyright (C) 2008-2013 Josh Fisher
|
* vchanger copyright (C) 2008-2018 Josh Fisher
|
||||||
*
|
*
|
||||||
* vchanger is free software.
|
* vchanger is free software.
|
||||||
* You may redistribute it and/or modify it under the terms of the
|
* You may redistribute it and/or modify it under the terms of the
|
||||||
@ -41,6 +41,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "uuidlookup.h"
|
#include "uuidlookup.h"
|
||||||
|
#include "loghandler.h"
|
||||||
|
|
||||||
#ifdef HAVE_WINDOWS_H
|
#ifdef HAVE_WINDOWS_H
|
||||||
|
|
||||||
@ -230,6 +231,7 @@ static int GetDevMountpoint(char *mountp, size_t mountp_sz, const char *devname)
|
|||||||
*/
|
*/
|
||||||
static int GetDevMountpoint(char *mountp, size_t mountp_sz, const char *devname)
|
static int GetDevMountpoint(char *mountp, size_t mountp_sz, const char *devname)
|
||||||
{
|
{
|
||||||
|
LogHandler_write(LOG_ERROR, "build does not support getmntent() or getfsstat() calls");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,8 +258,8 @@ int GetMountpointFromUUID(char *mountp, size_t mountp_sz, const char *uuid_str)
|
|||||||
struct udev_list_entry *devices, *dev_list_entry;
|
struct udev_list_entry *devices, *dev_list_entry;
|
||||||
struct udev_device *dev;
|
struct udev_device *dev;
|
||||||
int rc = -3;
|
int rc = -3;
|
||||||
const char *dev_name, *path, *uuid;
|
const char *dev_name, *dev_links, *path, *uuid;
|
||||||
size_t n, pos, dev_name_len;
|
size_t n, pos, dev_links_len;
|
||||||
char devlink[4096];
|
char devlink[4096];
|
||||||
|
|
||||||
if (!mountp || !mountp_sz) return -2;
|
if (!mountp || !mountp_sz) return -2;
|
||||||
@ -280,29 +282,50 @@ int GetMountpointFromUUID(char *mountp, size_t mountp_sz, const char *uuid_str)
|
|||||||
dev_name = udev_device_get_property_value(dev, "DEVNAME");
|
dev_name = udev_device_get_property_value(dev, "DEVNAME");
|
||||||
if (dev_name == NULL) {
|
if (dev_name == NULL) {
|
||||||
/* Failed to get kernel device node */
|
/* Failed to get kernel device node */
|
||||||
|
LogHandler_write(LOG_DEBUG, "filesystem %s has no udev assigned device node",
|
||||||
|
uuid_str);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
LogHandler_write(LOG_DEBUG, "filesystem %s has udev assigned device %s",
|
||||||
|
uuid_str, dev_name);
|
||||||
/* Lookup mountpoint of the kernel device node */
|
/* Lookup mountpoint of the kernel device node */
|
||||||
rc = GetDevMountpoint(mountp, mountp_sz, dev_name);
|
rc = GetDevMountpoint(mountp, mountp_sz, dev_name);
|
||||||
if (rc == 0) break;
|
if (rc == 0) {
|
||||||
/* If not mounted as the DEVNAME, also check if mounted as
|
/* Found mountpoint */
|
||||||
* a device alias name from DEVLINKS */
|
LogHandler_write(LOG_DEBUG, "filesystem %s (device %s) mounted at %s", uuid_str, dev_name, mountp);
|
||||||
dev_name = udev_device_get_property_value(dev, "DEVLINKS");
|
|
||||||
if (dev_name == NULL) {
|
|
||||||
/* Failed to get device alias links */
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
dev_name_len = strlen(dev_name);
|
if (rc == -4) {
|
||||||
pos = 0;
|
/* If not mounted as the DEVNAME, also check if mounted as
|
||||||
while (rc == -4 && pos < dev_name_len) {
|
* a device alias name from DEVLINKS */
|
||||||
for (n = pos; n < dev_name_len && !isblank(dev_name[n]); n++) ;
|
dev_links = udev_device_get_property_value(dev, "DEVLINKS");
|
||||||
n -= pos;
|
if (dev_links == NULL) {
|
||||||
memmove(devlink, dev_name + pos, n);
|
/* No device alias links found */
|
||||||
devlink[n] = 0;
|
break;
|
||||||
rc = GetDevMountpoint(mountp, mountp_sz, devlink);
|
}
|
||||||
pos += n;
|
LogHandler_write(LOG_DEBUG, "device %s not found in system mounts, searching all udev device aliases",
|
||||||
while (pos < dev_name_len && isblank(dev_name[pos])) ++pos;
|
dev_name);
|
||||||
|
/* For each device alias, look for a mountpoint */
|
||||||
|
dev_links_len = strlen(dev_links);
|
||||||
|
pos = 0;
|
||||||
|
while (rc == -4 && pos < dev_links_len) {
|
||||||
|
for (n = pos; n < dev_links_len && !isblank(dev_links[n]); n++) ;
|
||||||
|
n -= pos;
|
||||||
|
memmove(devlink, dev_links + pos, n);
|
||||||
|
devlink[n] = 0;
|
||||||
|
rc = GetDevMountpoint(mountp, mountp_sz, devlink);
|
||||||
|
if (rc == 0) {
|
||||||
|
/* Device alias is mounted */
|
||||||
|
LogHandler_write(LOG_DEBUG, "filesystem %s (device %s) mounted at %s", uuid_str, devlink,
|
||||||
|
mountp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rc = -4; /* Ignore other errors from attempt to get alias's mountpoint */
|
||||||
|
pos += n;
|
||||||
|
while (pos < dev_links_len && isblank(dev_links[pos])) ++pos;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (rc == -4) LogHandler_write(LOG_DEBUG, "filesystem %s (device %s) not mounted", uuid_str, dev_name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -340,7 +363,11 @@ int GetMountpointFromUUID(char *mountp, size_t mountp_sz, const char *uuid_str)
|
|||||||
#else
|
#else
|
||||||
dev_name = blkid_get_devname(NULL, "UUID", uuid_str);
|
dev_name = blkid_get_devname(NULL, "UUID", uuid_str);
|
||||||
#endif
|
#endif
|
||||||
if (!dev_name) return -3; /* no device with UUID found */
|
if (!dev_name) {
|
||||||
|
LogHandler_write(LOG_DEBUG, "filesystem %s not found", uuid_str);
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
LogHandler_write(LOG_DEBUG, "libblkid found filesystem %s at device %s", uuid_str, dev_name);
|
||||||
|
|
||||||
/* find mount point for device */
|
/* find mount point for device */
|
||||||
rc = GetDevMountpoint(mountp, mountp_sz, dev_name);
|
rc = GetDevMountpoint(mountp, mountp_sz, dev_name);
|
||||||
@ -355,6 +382,7 @@ int GetMountpointFromUUID(char *mountp, size_t mountp_sz, const char *uuid_str)
|
|||||||
*/
|
*/
|
||||||
int GetMountpointFromUUID(char *mountp, size_t mountp_sz, const char *uuid_str)
|
int GetMountpointFromUUID(char *mountp, size_t mountp_sz, const char *uuid_str)
|
||||||
{
|
{
|
||||||
|
LogHandler_write(LOG_DEBUG, "GetMountpointFromUUID: UUID lookups not supported by this build");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
171
src/vchanger.cpp
171
src/vchanger.cpp
@ -2,7 +2,7 @@
|
|||||||
*
|
*
|
||||||
* This file is part of the vchanger package
|
* This file is part of the vchanger package
|
||||||
*
|
*
|
||||||
* vchanger copyright (C) 2008-2015 Josh Fisher
|
* vchanger copyright (C) 2008-2020 Josh Fisher
|
||||||
*
|
*
|
||||||
* vchanger is free software.
|
* vchanger is free software.
|
||||||
* You may redistribute it and/or modify it under the terms of the
|
* You may redistribute it and/or modify it under the terms of the
|
||||||
@ -31,6 +31,9 @@
|
|||||||
#ifdef HAVE_STDINT_H
|
#ifdef HAVE_STDINT_H
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_ERRNO_H
|
||||||
|
#include <errno.h>
|
||||||
|
#endif
|
||||||
#ifdef HAVE_GETOPT_H
|
#ifdef HAVE_GETOPT_H
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#endif
|
#endif
|
||||||
@ -53,7 +56,10 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "compat_defs.h"
|
#include "compat_defs.h"
|
||||||
#include "loghandler.h"
|
#include "loghandler.h"
|
||||||
|
#include "errhandler.h"
|
||||||
#include "diskchanger.h"
|
#include "diskchanger.h"
|
||||||
|
#include "mymutex.h"
|
||||||
|
#include "bconsole.h"
|
||||||
|
|
||||||
DiskChanger changer;
|
DiskChanger changer;
|
||||||
|
|
||||||
@ -80,6 +86,7 @@ typedef struct _cmdparams_s
|
|||||||
{
|
{
|
||||||
bool print_version;
|
bool print_version;
|
||||||
bool print_help;
|
bool print_help;
|
||||||
|
bool force;
|
||||||
int command;
|
int command;
|
||||||
int slot;
|
int slot;
|
||||||
int drive;
|
int drive;
|
||||||
@ -115,12 +122,15 @@ static void print_help(void)
|
|||||||
" changer defined by vchanger configuration file\n"
|
" changer defined by vchanger configuration file\n"
|
||||||
" 'config_file' using 'slot', 'device', and 'drive'\n"
|
" 'config_file' using 'slot', 'device', and 'drive'\n"
|
||||||
" vchanger [options] config_file LISTMAGS\n"
|
" vchanger [options] config_file LISTMAGS\n"
|
||||||
" vchanger extension to list info on all defined magazines.\n"
|
" API extension to list info on all defined magazines.\n"
|
||||||
" vchanger [options] config_file CREATEVOLS mag_ndx count [start] [CREATEVOLS options]\n"
|
" vchanger [options] config_file CREATEVOLS mag_ndx count [start] [CREATEVOLS options]\n"
|
||||||
" vchanger extension to create 'count' empty volume files on the magazine at\n"
|
" API extension to create 'count' empty volume files on the magazine at\n"
|
||||||
" index 'mag_ndx'. If specified, 'start' is the lowest integer to use when\n"
|
" index 'mag_ndx'. If specified, 'start' is the lowest integer to use in\n"
|
||||||
" appending integers to the label prefix when generating volume names.\n"
|
" appending integers to the label prefix when generating volume names.\n"
|
||||||
" vchanger [options] config_file REFRESH\n"
|
" vchanger [options] config_file REFRESH\n"
|
||||||
|
" API extension to issue an Update Slots command in bconsole if a change\n"
|
||||||
|
" in the virtual slot to volume file mapping is detected. The --force flag\n"
|
||||||
|
" forces the bconsole call regardless detected changes.\n"
|
||||||
" vchanger --version\n"
|
" vchanger --version\n"
|
||||||
" print version info\n"
|
" print version info\n"
|
||||||
" vchanger --help\n"
|
" vchanger --help\n"
|
||||||
@ -131,13 +141,13 @@ static void print_help(void)
|
|||||||
"\nCREATEVOLS command options:\n"
|
"\nCREATEVOLS command options:\n"
|
||||||
" -l, --label=string string to use as a prefix for determining the\n"
|
" -l, --label=string string to use as a prefix for determining the\n"
|
||||||
" barcode label of the volume files created. Labels\n"
|
" barcode label of the volume files created. Labels\n"
|
||||||
" will be of the form 'string'_N, where N is an\n"
|
" will be of the form 'string'N, where N is a\n"
|
||||||
" integer. By default the prefix will be generated\n"
|
" 4 digit integer with leading zeros. The magazine\n"
|
||||||
" using the changer name and the position of the\n"
|
" name is used as the prefix string by default.\n"
|
||||||
" magazine's declaration in the configuration file.\n"
|
" --pool=string Overrides the default pool that new volumes should\n"
|
||||||
" --pool=string Overrides the default pool, defined in the vchanger\n"
|
" be placed into when labeling newly created volumes.\n"
|
||||||
" config file, that new volumes should be placed into\n"
|
"\nREFRESH command options:\n"
|
||||||
" when labeling newly created volumes.\n"
|
" --force Force a bconsole update slots command to be invoked\n"
|
||||||
"\nReport bugs to %s.\n", PACKAGE_BUGREPORT);
|
"\nReport bugs to %s.\n", PACKAGE_BUGREPORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,6 +157,7 @@ static void print_help(void)
|
|||||||
#define LONGONLYOPT_VERSION 0
|
#define LONGONLYOPT_VERSION 0
|
||||||
#define LONGONLYOPT_HELP 1
|
#define LONGONLYOPT_HELP 1
|
||||||
#define LONGONLYOPT_POOL 2
|
#define LONGONLYOPT_POOL 2
|
||||||
|
#define LONGONLYOPT_FORCE 3
|
||||||
|
|
||||||
static int parse_cmdline(int argc, char *argv[])
|
static int parse_cmdline(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -158,10 +169,12 @@ static int parse_cmdline(int argc, char *argv[])
|
|||||||
{ "group", 1, 0, 'g' },
|
{ "group", 1, 0, 'g' },
|
||||||
{ "label", 1, 0, 'l' },
|
{ "label", 1, 0, 'l' },
|
||||||
{ "pool", 1, 0, LONGONLYOPT_POOL },
|
{ "pool", 1, 0, LONGONLYOPT_POOL },
|
||||||
|
{ "force", 0, 0, LONGONLYOPT_FORCE },
|
||||||
{ 0, 0, 0, 0 } };
|
{ 0, 0, 0, 0 } };
|
||||||
|
|
||||||
cmdl.print_version = false;
|
cmdl.print_version = false;
|
||||||
cmdl.print_help = false;
|
cmdl.print_help = false;
|
||||||
|
cmdl.force = false;
|
||||||
cmdl.command = 0;
|
cmdl.command = 0;
|
||||||
cmdl.slot = 0;
|
cmdl.slot = 0;
|
||||||
cmdl.drive = 0;
|
cmdl.drive = 0;
|
||||||
@ -198,6 +211,9 @@ static int parse_cmdline(int argc, char *argv[])
|
|||||||
case LONGONLYOPT_POOL:
|
case LONGONLYOPT_POOL:
|
||||||
cmdl.pool = optarg;
|
cmdl.pool = optarg;
|
||||||
break;
|
break;
|
||||||
|
case LONGONLYOPT_FORCE:
|
||||||
|
cmdl.force = true;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "unknown option %s\n", optarg);
|
fprintf(stderr, "unknown option %s\n", optarg);
|
||||||
return -1;
|
return -1;
|
||||||
@ -237,6 +253,11 @@ static int parse_cmdline(int argc, char *argv[])
|
|||||||
fprintf(stderr, "flag --pool not valid for this command\n");
|
fprintf(stderr, "flag --pool not valid for this command\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
/* Make sure only REFRESH command has --force flag */
|
||||||
|
if (cmdl.force && cmdl.command != CMD_REFRESH) {
|
||||||
|
fprintf(stderr, "flag --force not valid for this command\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
/* Check param 3 exists */
|
/* Check param 3 exists */
|
||||||
++ndx;
|
++ndx;
|
||||||
if (ndx >= argc) {
|
if (ndx >= argc) {
|
||||||
@ -378,7 +399,7 @@ static int do_list_cmd()
|
|||||||
fprintf(stdout, "%d:%s\n", slot, changer.GetVolumeLabel(slot));
|
fprintf(stdout, "%d:%s\n", slot, changer.GetVolumeLabel(slot));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.Info(" SUCCESS sent list to stdout");
|
vlog.Info(" SUCCESS sent list to stdout");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,7 +411,7 @@ static int do_list_cmd()
|
|||||||
static int do_slots_cmd()
|
static int do_slots_cmd()
|
||||||
{
|
{
|
||||||
fprintf(stdout, "%d\n", changer.NumSlots());
|
fprintf(stdout, "%d\n", changer.NumSlots());
|
||||||
log.Info(" SUCCESS reporting %d slots", changer.NumSlots());
|
vlog.Info(" SUCCESS reporting %d slots", changer.NumSlots());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,10 +424,10 @@ static int do_load_cmd()
|
|||||||
{
|
{
|
||||||
if (changer.LoadDrive(cmdl.drive, cmdl.slot)) {
|
if (changer.LoadDrive(cmdl.drive, cmdl.slot)) {
|
||||||
fprintf(stderr, "%s\n", changer.GetErrorMsg());
|
fprintf(stderr, "%s\n", changer.GetErrorMsg());
|
||||||
log.Error(" ERROR loading slot %d into drive %d", cmdl.slot, cmdl.drive);
|
vlog.Error(" ERROR loading slot %d into drive %d", cmdl.slot, cmdl.drive);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
log.Info(" SUCCESS loading slot %d into drive %d", cmdl.slot, cmdl.drive);
|
vlog.Info(" SUCCESS loading slot %d into drive %d", cmdl.slot, cmdl.drive);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,10 +440,10 @@ static int do_unload_cmd()
|
|||||||
{
|
{
|
||||||
if (changer.UnloadDrive(cmdl.drive)) {
|
if (changer.UnloadDrive(cmdl.drive)) {
|
||||||
fprintf(stderr, "%s\n", changer.GetErrorMsg());
|
fprintf(stderr, "%s\n", changer.GetErrorMsg());
|
||||||
log.Error(" ERROR unloading slot %d from drive %d", cmdl.slot, cmdl.drive);
|
vlog.Error(" ERROR unloading slot %d from drive %d", cmdl.slot, cmdl.drive);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
log.Info(" SUCCESS unloading slot %d from drive %d", cmdl.slot, cmdl.drive);
|
vlog.Info(" SUCCESS unloading slot %d from drive %d", cmdl.slot, cmdl.drive);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,10 +458,11 @@ static int do_loaded_cmd()
|
|||||||
int slot = changer.GetDriveSlot(cmdl.drive);
|
int slot = changer.GetDriveSlot(cmdl.drive);
|
||||||
if (slot < 0) slot = 0;
|
if (slot < 0) slot = 0;
|
||||||
fprintf(stdout, "%d\n", slot);
|
fprintf(stdout, "%d\n", slot);
|
||||||
log.Info(" SUCCESS reporting drive %d loaded from slot %d", cmdl.drive, slot);
|
vlog.Info(" SUCCESS reporting drive %d loaded from slot %d", cmdl.drive, slot);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
* LISTALL Command
|
* LISTALL Command
|
||||||
* Prints state of drives (loaded or empty), followed by state
|
* Prints state of drives (loaded or empty), followed by state
|
||||||
@ -471,7 +493,7 @@ static int do_list_all()
|
|||||||
fprintf(stdout, "S:%d:E\n", n);
|
fprintf(stdout, "S:%d:E\n", n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.Info(" SUCCESS sent listall to stdout");
|
vlog.Info(" SUCCESS sent listall to stdout");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -487,7 +509,7 @@ static int do_list_magazines()
|
|||||||
|
|
||||||
if (changer.NumMagazines() == 0) {
|
if (changer.NumMagazines() == 0) {
|
||||||
fprintf(stdout, "No magazines are defined\n");
|
fprintf(stdout, "No magazines are defined\n");
|
||||||
log.Info(" SUCCESS no magazines are defined");
|
vlog.Info(" SUCCESS no magazines are defined");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
for (n = 0; n < changer.NumMagazines(); n++) {
|
for (n = 0; n < changer.NumMagazines(); n++) {
|
||||||
@ -498,10 +520,11 @@ static int do_list_magazines()
|
|||||||
changer.GetMagazineStartSlot(n), changer.GetMagazineMountpoint(n));
|
changer.GetMagazineStartSlot(n), changer.GetMagazineMountpoint(n));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.Info(" SUCCESS listing magazine info to stdout");
|
vlog.Info(" SUCCESS listing magazine info to stdout");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
* CREATEVOLS (Create Volumes) Command
|
* CREATEVOLS (Create Volumes) Command
|
||||||
* Creates volume files on the specified magazine
|
* Creates volume files on the specified magazine
|
||||||
@ -511,12 +534,12 @@ static int do_create_vols()
|
|||||||
/* Create new volume files on magazine */
|
/* Create new volume files on magazine */
|
||||||
if (changer.CreateVolumes(cmdl.mag_bay, cmdl.count, cmdl.slot, cmdl.label_prefix.c_str())) {
|
if (changer.CreateVolumes(cmdl.mag_bay, cmdl.count, cmdl.slot, cmdl.label_prefix.c_str())) {
|
||||||
fprintf(stderr, "%s\n", changer.GetErrorMsg());
|
fprintf(stderr, "%s\n", changer.GetErrorMsg());
|
||||||
log.Error(" ERROR");
|
vlog.Error(" ERROR: %s", changer.GetErrorMsg());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
fprintf(stdout, "Created %d volume files on magazine %d\n",
|
fprintf(stdout, "Created %d volume files on magazine %d\n",
|
||||||
cmdl.count, cmdl.mag_bay);
|
cmdl.count, cmdl.mag_bay);
|
||||||
log.Info(" SUCCESS");
|
vlog.Info(" SUCCESS");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -529,13 +552,14 @@ int main(int argc, char *argv[])
|
|||||||
int rc;
|
int rc;
|
||||||
FILE *fs = NULL;
|
FILE *fs = NULL;
|
||||||
int32_t error_code;
|
int32_t error_code;
|
||||||
|
void *command_mux = NULL, *bconsole_mux = NULL;
|
||||||
|
|
||||||
#ifdef HAVE_LOCALE_H
|
#ifdef HAVE_LOCALE_H
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Log initially to stderr */
|
/* Log initially to stderr */
|
||||||
log.OpenLog(stderr, LOG_ERR);
|
vlog.OpenLog(stderr, LOG_ERR);
|
||||||
/* parse the command line */
|
/* parse the command line */
|
||||||
if ((error_code = parse_cmdline(argc, argv)) != 0) {
|
if ((error_code = parse_cmdline(argc, argv)) != 0) {
|
||||||
print_help();
|
print_help();
|
||||||
@ -551,6 +575,7 @@ int main(int argc, char *argv[])
|
|||||||
print_help();
|
print_help();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read vchanger config file */
|
/* Read vchanger config file */
|
||||||
if (!conf.Read(cmdl.config_file)) {
|
if (!conf.Read(cmdl.config_file)) {
|
||||||
return 1;
|
return 1;
|
||||||
@ -573,89 +598,137 @@ int main(int argc, char *argv[])
|
|||||||
fprintf(stderr, "Error opening opening log file\n");
|
fprintf(stderr, "Error opening opening log file\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
log.OpenLog(fs, conf.log_level);
|
vlog.OpenLog(fs, conf.log_level);
|
||||||
}
|
}
|
||||||
/* Validate and commit configuration parameters */
|
/* Validate and commit configuration parameters */
|
||||||
if (!conf.Validate()) {
|
if (!conf.Validate()) {
|
||||||
|
fprintf(stderr, "ERROR! configuration file error\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#ifndef HAVE_WINDOWS_H
|
#ifndef HAVE_WINDOWS_H
|
||||||
/* Ignore SIGPIPE signals */
|
/* Ignore SIGPIPE signals */
|
||||||
signal(SIGPIPE, SIG_IGN);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
#endif
|
#endif
|
||||||
/* Initialize changer. A lock file is created to serialize access
|
|
||||||
|
/* Open/create named mutex */
|
||||||
|
command_mux = mymutex_create("vchanger-command");
|
||||||
|
if (command_mux == 0) {
|
||||||
|
vlog.Error("ERROR! failed to create named mutex errno=%d", errno);
|
||||||
|
fprintf(stderr, "ERROR! failed to create named mutex errno=%d\n", errno);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* Lock mutex to perform command */
|
||||||
|
if (mymutex_lock(command_mux, 300)) {
|
||||||
|
vlog.Error("ERROR! failed to lock named mutex errno=%d", errno);
|
||||||
|
fprintf(stderr, "ERROR! failed to lock named mutex errno=%d\n", errno);
|
||||||
|
mymutex_destroy("vchanger-command", command_mux);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize changer. A named mutex is created to serialize access
|
||||||
* to the changer. As a result, changer initialization may block
|
* to the changer. As a result, changer initialization may block
|
||||||
* for up to 30 seconds, and may fail if a timeout is reached */
|
* for up to 30 seconds, and may fail if a timeout is reached */
|
||||||
if (changer.Initialize()) {
|
if (changer.Initialize()) {
|
||||||
|
vlog.Error("%s", changer.GetErrorMsg());
|
||||||
fprintf(stderr, "%s\n", changer.GetErrorMsg());
|
fprintf(stderr, "%s\n", changer.GetErrorMsg());
|
||||||
|
mymutex_destroy("vchanger-command", command_mux);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Perform command */
|
/* Perform command */
|
||||||
switch (cmdl.command) {
|
switch (cmdl.command) {
|
||||||
case CMD_LIST:
|
case CMD_LIST:
|
||||||
log.Debug("==== preforming LIST command pid=%d", getpid());
|
vlog.Debug("==== preforming LIST command");
|
||||||
error_code = do_list_cmd();
|
error_code = do_list_cmd();
|
||||||
break;
|
break;
|
||||||
case CMD_SLOTS:
|
case CMD_SLOTS:
|
||||||
log.Debug("==== preforming SLOTS command pid=%d", getpid());
|
vlog.Debug("==== preforming SLOTS command");
|
||||||
error_code = do_slots_cmd();
|
error_code = do_slots_cmd();
|
||||||
break;
|
break;
|
||||||
case CMD_LOAD:
|
case CMD_LOAD:
|
||||||
log.Debug("==== preforming LOAD command pid=%d", getpid());
|
vlog.Debug("==== preforming LOAD command");
|
||||||
error_code = do_load_cmd();
|
error_code = do_load_cmd();
|
||||||
break;
|
break;
|
||||||
case CMD_UNLOAD:
|
case CMD_UNLOAD:
|
||||||
log.Debug("==== preforming UNLOAD command pid=%d", getpid());
|
vlog.Debug("==== preforming UNLOAD command");
|
||||||
error_code = do_unload_cmd();
|
error_code = do_unload_cmd();
|
||||||
break;
|
break;
|
||||||
case CMD_LOADED:
|
case CMD_LOADED:
|
||||||
log.Debug("==== preforming LOADED command pid=%d", getpid());
|
vlog.Debug("==== preforming LOADED command");
|
||||||
error_code = do_loaded_cmd();
|
error_code = do_loaded_cmd();
|
||||||
break;
|
break;
|
||||||
case CMD_LISTALL:
|
case CMD_LISTALL:
|
||||||
log.Debug("==== preforming LISTALL command pid=%d", getpid());
|
vlog.Debug("==== preforming LISTALL command");
|
||||||
error_code = do_list_all();
|
error_code = do_list_all();
|
||||||
break;
|
break;
|
||||||
case CMD_LISTMAGS:
|
case CMD_LISTMAGS:
|
||||||
log.Debug("==== preforming LISTMAGS command pid=%d", getpid());
|
vlog.Debug("==== preforming LISTMAGS command");
|
||||||
error_code = do_list_magazines();
|
error_code = do_list_magazines();
|
||||||
break;
|
break;
|
||||||
case CMD_CREATEVOLS:
|
case CMD_CREATEVOLS:
|
||||||
log.Debug("==== preforming CREATEVOLS command pid=%d", getpid());
|
vlog.Debug("==== preforming CREATEVOLS command");
|
||||||
error_code = do_create_vols();
|
error_code = do_create_vols();
|
||||||
break;
|
break;
|
||||||
case CMD_REFRESH:
|
case CMD_REFRESH:
|
||||||
log.Debug("==== preforming REFRESH command pid=%d", getpid());
|
vlog.Debug("==== preforming REFRESH command");
|
||||||
error_code = 0;
|
error_code = 0;
|
||||||
log.Info(" SUCCESS pid=%d", getpid());
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
changer.Unlock();
|
|
||||||
|
|
||||||
/* If there was an error, then exit */
|
/* If there was an error, then exit */
|
||||||
if (error_code) return error_code;
|
if (error_code) {
|
||||||
|
mymutex_destroy("vchanger-command", command_mux);
|
||||||
|
return error_code;
|
||||||
|
}
|
||||||
|
|
||||||
/* If not updating Bacula, then exit */
|
/* If not updating Bacula, then exit */
|
||||||
|
#ifdef HAVE_WINDOWS_H
|
||||||
|
conf.bconsole = ""; /* Issuing bconsole commands not implemented on Windows */
|
||||||
|
#endif
|
||||||
if (conf.bconsole.empty()) {
|
if (conf.bconsole.empty()) {
|
||||||
/* Bacula interaction via bconsole is disabled, so log warnings */
|
/* Bacula interaction via bconsole is disabled, so log warnings */
|
||||||
if (changer.NeedsUpdate())
|
if (changer.NeedsUpdate())
|
||||||
log.Error("WARNING! 'update slots' needed in bconsole pid=%d", getpid());
|
vlog.Error("WARNING! 'update slots' needed in bconsole pid=%d", getpid());
|
||||||
if (changer.NeedsLabel())
|
if (changer.NeedsLabel())
|
||||||
log.Error("WARNING! 'label barcodes' needed in bconsole pid=%d", getpid());
|
vlog.Error("WARNING! 'label barcodes' needed in bconsole pid=%d", getpid());
|
||||||
|
mymutex_destroy("vchanger-command", command_mux);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update Bacula via bconsole */
|
/* Update Bacula via bconsole */
|
||||||
#ifndef HAVE_WINDOWS_H
|
|
||||||
changer.UpdateBacula();
|
|
||||||
#else
|
|
||||||
/* Auto-update of bacula not working for Windows */
|
|
||||||
if (changer.NeedsUpdate())
|
|
||||||
log.Error("WARNING! 'update slots' needed in bconsole");
|
|
||||||
if (changer.NeedsLabel())
|
|
||||||
log.Error("WARNING! 'label barcodes' needed in bconsole");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
/* Create named mutex to prevent further bconsole commands when bconsole
|
||||||
|
* commands have already been initiated */
|
||||||
|
bconsole_mux = mymutex_create("vchanger-bconsole");
|
||||||
|
if (bconsole_mux == 0) {
|
||||||
|
vlog.Error("ERROR! failed to create named mutex errno=%d", errno);
|
||||||
|
fprintf(stderr, "ERROR! failed to create named mutex errno=%d\n", errno);
|
||||||
|
mymutex_destroy("vchanger-command", command_mux);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* Lock mutex to perform command */
|
||||||
|
if (mymutex_lock(bconsole_mux, 0)) {
|
||||||
|
/* If bconsole mutex is locked because another instance has previously invoked
|
||||||
|
* bconsole, then this instance is the result of bconsole itself invoking
|
||||||
|
* additional vchanger processes to handle the previous instance's bconsole
|
||||||
|
* command. So tto prevent a race condition, this instance must not invoke
|
||||||
|
* further bconsole processes. */
|
||||||
|
vlog.Info("invoked from bconsole - skipping further bconsole commands", errno);
|
||||||
|
mymutex_destroy("vchanger-bconsole", bconsole_mux);
|
||||||
|
mymutex_destroy("vchanger-command", command_mux);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unlock the command mutex long enough to issue bconsole commands.
|
||||||
|
* Note that the bconsole mutex is left locked to prevent a race condition
|
||||||
|
* should the invoked bconsole process need to invoke additional
|
||||||
|
* instances of vchanger. */
|
||||||
|
mymutex_unlock(command_mux);
|
||||||
|
IssueBconsoleCommands(changer.NeedsUpdate() | cmdl.force, changer.NeedsLabel());
|
||||||
|
mymutex_lock(command_mux, 300);
|
||||||
|
|
||||||
|
/* Cleanup */
|
||||||
|
mymutex_destroy("vchanger-bconsole", command_mux);
|
||||||
|
mymutex_destroy("vchanger-command", bconsole_mux);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
*
|
*
|
||||||
* This file is part of vchanger by Josh Fisher.
|
* This file is part of vchanger by Josh Fisher.
|
||||||
*
|
*
|
||||||
* vchanger copyright (C) 2008-2014 Josh Fisher
|
* vchanger copyright (C) 2008-2018 Josh Fisher
|
||||||
*
|
*
|
||||||
* vchanger is free software.
|
* vchanger is free software.
|
||||||
* You may redistribute it and/or modify it under the terms of the
|
* You may redistribute it and/or modify it under the terms of the
|
||||||
@ -45,26 +45,21 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_WINDOWS_H
|
#ifdef HAVE_WINDOWS_H
|
||||||
#include "targetver.h"
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SHLOBJ_H
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_DIRECT_H
|
||||||
#include <direct.h>
|
#include <direct.h>
|
||||||
#define DIR_DELIM "\\"
|
|
||||||
#define DIR_DELIM_C '\\'
|
|
||||||
#define MAG_VOLUME_MASK 0
|
|
||||||
#else
|
|
||||||
#define DIR_DELIM "/"
|
|
||||||
#define DIR_DELIM_C '/'
|
|
||||||
#define MAG_VOLUME_MASK S_IWGRP|S_IRWXO
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "compat_defs.h"
|
||||||
#include "loghandler.h"
|
#include "loghandler.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#define __VCONF_SOURCE 1
|
#define __VCONF_SOURCE 1
|
||||||
#include "vconf.h"
|
#include "vconf.h"
|
||||||
|
|
||||||
/* Global configuration object */
|
|
||||||
VchangerConfig conf;
|
|
||||||
|
|
||||||
/*-------------------------------------------
|
/*-------------------------------------------
|
||||||
* Config file keywords and defaults
|
* Config file keywords and defaults
|
||||||
@ -145,19 +140,19 @@ bool VchangerConfig::Read(const char *cfile)
|
|||||||
|
|
||||||
tmp_ini.ClearKeywordValues();
|
tmp_ini.ClearKeywordValues();
|
||||||
if (!cfile || !cfile[0]) {
|
if (!cfile || !cfile[0]) {
|
||||||
log.Error("config file not specified");
|
vlog.Error("config file not specified");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/* Does config file exist */
|
/* Does config file exist */
|
||||||
if (access(cfile, R_OK)) {
|
if (access(cfile, R_OK)) {
|
||||||
log.Error("could not access config file %s", cfile);
|
vlog.Error("could not access config file %s", cfile);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/* Read config file values */
|
/* Read config file values */
|
||||||
rc = tmp_ini.Read(cfile);
|
rc = tmp_ini.Read(cfile);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
if (rc > 0) log.Error("Parse error in %s at line %d", cfile, rc);
|
if (rc > 0) vlog.Error("Parse error in %s at line %d", cfile, rc);
|
||||||
else log.Error("could not open config file %s", cfile);
|
else vlog.Error("could not open config file %s", cfile);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/* Update keyword values */
|
/* Update keyword values */
|
||||||
@ -168,7 +163,7 @@ bool VchangerConfig::Read(const char *cfile)
|
|||||||
storage_name = (const char*)keyword[VK_STORAGE_NAME];
|
storage_name = (const char*)keyword[VK_STORAGE_NAME];
|
||||||
tStrip(storage_name);
|
tStrip(storage_name);
|
||||||
if (storage_name.empty()) {
|
if (storage_name.empty()) {
|
||||||
log.Error("config file keyword '%s' must specify a non-empty string", VK_STORAGE_NAME);
|
vlog.Error("config file keyword '%s' must specify a non-empty string", VK_STORAGE_NAME);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/* Update defaults for this changer name */
|
/* Update defaults for this changer name */
|
||||||
@ -181,7 +176,7 @@ bool VchangerConfig::Read(const char *cfile)
|
|||||||
work_dir = (const char*)keyword[VK_WORK_DIR];
|
work_dir = (const char*)keyword[VK_WORK_DIR];
|
||||||
tStrip(work_dir);
|
tStrip(work_dir);
|
||||||
if (work_dir.empty()) {
|
if (work_dir.empty()) {
|
||||||
log.Error("config file keyword '%s' must specify a non-empty string", VK_WORK_DIR);
|
vlog.Error("config file keyword '%s' must specify a non-empty string", VK_WORK_DIR);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -191,7 +186,7 @@ bool VchangerConfig::Read(const char *cfile)
|
|||||||
logfile = (const char*)keyword[VK_LOGFILE];
|
logfile = (const char*)keyword[VK_LOGFILE];
|
||||||
tStrip(logfile);
|
tStrip(logfile);
|
||||||
if (logfile.empty()) {
|
if (logfile.empty()) {
|
||||||
log.Error("config file keyword '%s' must specify a non-empty string", VK_LOGFILE);
|
vlog.Error("config file keyword '%s' must specify a non-empty string", VK_LOGFILE);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -200,7 +195,7 @@ bool VchangerConfig::Read(const char *cfile)
|
|||||||
if (keyword[VK_LOG_LEVEL].IsSet()) {
|
if (keyword[VK_LOG_LEVEL].IsSet()) {
|
||||||
log_level = (int)keyword[VK_LOG_LEVEL];
|
log_level = (int)keyword[VK_LOG_LEVEL];
|
||||||
if (log_level < 0 || log_level > 7) {
|
if (log_level < 0 || log_level > 7) {
|
||||||
log.Error("config file keyword '%s' must specify a value between 0 and 7 inclusive", VK_LOG_LEVEL);
|
vlog.Error("config file keyword '%s' must specify a value between 0 and 7 inclusive", VK_LOG_LEVEL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -210,7 +205,7 @@ bool VchangerConfig::Read(const char *cfile)
|
|||||||
user = (const char*)keyword[VK_USER];
|
user = (const char*)keyword[VK_USER];
|
||||||
tStrip(user);
|
tStrip(user);
|
||||||
if (user.empty()) {
|
if (user.empty()) {
|
||||||
log.Error("keyword '%s' value cannot be empty", VK_USER);
|
vlog.Error("keyword '%s' value cannot be empty", VK_USER);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -220,7 +215,7 @@ bool VchangerConfig::Read(const char *cfile)
|
|||||||
group = (const char*)keyword[VK_GROUP];
|
group = (const char*)keyword[VK_GROUP];
|
||||||
tStrip(group);
|
tStrip(group);
|
||||||
if (group.empty()) {
|
if (group.empty()) {
|
||||||
log.Error("keyword '%s' value cannot be empty", VK_GROUP);
|
vlog.Error("keyword '%s' value cannot be empty", VK_GROUP);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -242,7 +237,7 @@ bool VchangerConfig::Read(const char *cfile)
|
|||||||
def_pool = (const char*)keyword[VK_DEF_POOL];
|
def_pool = (const char*)keyword[VK_DEF_POOL];
|
||||||
tStrip(def_pool);
|
tStrip(def_pool);
|
||||||
if (def_pool.empty()) {
|
if (def_pool.empty()) {
|
||||||
log.Error("keyword '%s' value cannot be empty", VK_DEF_POOL);
|
vlog.Error("keyword '%s' value cannot be empty", VK_DEF_POOL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -252,13 +247,13 @@ bool VchangerConfig::Read(const char *cfile)
|
|||||||
magazine = keyword[VK_MAGAZINE];
|
magazine = keyword[VK_MAGAZINE];
|
||||||
}
|
}
|
||||||
if (magazine.empty()) {
|
if (magazine.empty()) {
|
||||||
log.Error("config file keyword '%s' must appear at least once", VK_MAGAZINE);
|
vlog.Error("config file keyword '%s' must appear at least once", VK_MAGAZINE);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (n = 0; n < (int)magazine.size(); n++) {
|
for (n = 0; n < (int)magazine.size(); n++) {
|
||||||
tStrip(magazine[n]);
|
tStrip(magazine[n]);
|
||||||
if (magazine[n].empty()) {
|
if (magazine[n].empty()) {
|
||||||
log.Error("config file keyword '%s' cannot be set to the empty string", VK_MAGAZINE);
|
vlog.Error("config file keyword '%s' cannot be set to the empty string", VK_MAGAZINE);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -283,13 +278,13 @@ bool VchangerConfig::Validate()
|
|||||||
#else
|
#else
|
||||||
if (_mkdir(work_dir.c_str())) {
|
if (_mkdir(work_dir.c_str())) {
|
||||||
#endif
|
#endif
|
||||||
log.Error("could not create work directory '%s'", work_dir.c_str());
|
vlog.Error("could not create work directory '%s'", work_dir.c_str());
|
||||||
umask(old_mask);
|
umask(old_mask);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
umask(old_mask);
|
umask(old_mask);
|
||||||
} else {
|
} else {
|
||||||
log.Error("could not access work directory '%s'", work_dir.c_str());
|
vlog.Error("could not access work directory '%s'", work_dir.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -299,7 +294,7 @@ bool VchangerConfig::Validate()
|
|||||||
if (!bconsole_config.empty()) {
|
if (!bconsole_config.empty()) {
|
||||||
if (access(bconsole_config.c_str(), R_OK)) {
|
if (access(bconsole_config.c_str(), R_OK)) {
|
||||||
/* If bconsole config doesn't exist or is not readable, disable use of bconsole */
|
/* If bconsole config doesn't exist or is not readable, disable use of bconsole */
|
||||||
log.Warning("cannot read bconsole config file. Disabling Bacula interaction.");
|
vlog.Warning("cannot read bconsole config file. Disabling Bacula interaction.");
|
||||||
bconsole.clear();
|
bconsole.clear();
|
||||||
bconsole_config.clear();
|
bconsole_config.clear();
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
*
|
*
|
||||||
* This file is part of vchanger by Josh Fisher.
|
* This file is part of vchanger by Josh Fisher.
|
||||||
*
|
*
|
||||||
* vchanger copyright (C) 2008-2014 Josh Fisher
|
* vchanger copyright (C) 2008-2018 Josh Fisher
|
||||||
*
|
*
|
||||||
* vchanger is free software.
|
* vchanger is free software.
|
||||||
* You may redistribute it and/or modify it under the terms of the
|
* You may redistribute it and/or modify it under the terms of the
|
||||||
@ -65,6 +65,7 @@ extern char DEFAULT_STATEDIR[4096];
|
|||||||
#else
|
#else
|
||||||
char DEFAULT_LOGDIR[4096];
|
char DEFAULT_LOGDIR[4096];
|
||||||
char DEFAULT_STATEDIR[4096];
|
char DEFAULT_STATEDIR[4096];
|
||||||
|
VchangerConfig conf;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _VCONF_H_ */
|
#endif /* _VCONF_H_ */
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#................-
|
#................-
|
||||||
#. Date of creation: 2015-06-01
|
#. Date of creation: 2020-05-06
|
||||||
#. Name: installer.nsi
|
#. Name: installer.nsi
|
||||||
#................-
|
#................-
|
||||||
#..- Package parameters ...
|
#..- Package parameters ...
|
||||||
@ -9,7 +9,15 @@ SetCompressor lzma
|
|||||||
!include MUI2.nsh
|
!include MUI2.nsh
|
||||||
!include WinMessages.nsh
|
!include WinMessages.nsh
|
||||||
!include x64.nsh
|
!include x64.nsh
|
||||||
!insertmacro MUI_LANGUAGE English
|
!insertmacro MUI_PAGE_WELCOME
|
||||||
|
!insertmacro MUI_PAGE_LICENSE "license.txt"
|
||||||
|
!insertmacro MUI_PAGE_DIRECTORY
|
||||||
|
!insertmacro MUI_PAGE_INSTFILES
|
||||||
|
!insertmacro MUI_PAGE_FINISH
|
||||||
|
!insertmacro MUI_UNPAGE_CONFIRM
|
||||||
|
!insertmacro MUI_UNPAGE_INSTFILES
|
||||||
|
!insertmacro MUI_LANGUAGE "English"
|
||||||
|
|
||||||
#... Installation Windows Parameters ..
|
#... Installation Windows Parameters ..
|
||||||
!define APPNAME "vchanger"
|
!define APPNAME "vchanger"
|
||||||
!define COMPANYNAME "Josh Fisher"
|
!define COMPANYNAME "Josh Fisher"
|
||||||
@ -17,20 +25,20 @@ SetCompressor lzma
|
|||||||
# These three must be integers
|
# These three must be integers
|
||||||
!define VERSIONMAJOR 1
|
!define VERSIONMAJOR 1
|
||||||
!define VERSIONMINOR 0
|
!define VERSIONMINOR 0
|
||||||
!define VERSIONBUILD 1
|
!define VERSIONBUILD 3
|
||||||
# These will be displayed by the "Click here for support information" link in "Add/Remove Programs"
|
# These will be displayed by the "Click here for support information" link in "Add/Remove Programs"
|
||||||
!define HELPURL "http://sourceforge.net/projects/vchanger/" # "Support Information" link
|
!define HELPURL "http://sourceforge.net/projects/vchanger/" # "Support Information" link
|
||||||
Name "vchanger 1.0.1"
|
Name "vchanger 1.0.3"
|
||||||
VIProductVersion "1.0.1.0"
|
VIProductVersion "1.0.3.0"
|
||||||
VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductName" "vchanger Installer"
|
VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductName" "vchanger Installer"
|
||||||
VIAddVersionKey /LANG=${LANG_ENGLISH} "LegalCopyright" "Copyright (c) Josh Fisher 2008-2015"
|
VIAddVersionKey /LANG=${LANG_ENGLISH} "LegalCopyright" "Copyright (c) Josh Fisher 2008-2020"
|
||||||
VIAddVersionKey /LANG=${LANG_ENGLISH} "FileDescription" "vchanger Windows Installer"
|
VIAddVersionKey /LANG=${LANG_ENGLISH} "FileDescription" "vchanger Windows Installer"
|
||||||
VIAddVersionKey /LANG=${LANG_ENGLISH} "FileVersion" "1.0.1"
|
VIAddVersionKey /LANG=${LANG_ENGLISH} "FileVersion" "1.0.3"
|
||||||
ShowInstDetails nevershow
|
ShowInstDetails nevershow
|
||||||
SilentInstall normal
|
SilentInstall normal
|
||||||
RequestExecutionLevel admin
|
RequestExecutionLevel admin
|
||||||
AutoCloseWindow True
|
AutoCloseWindow True
|
||||||
OutFile "vchanger-1.0.1.exe"
|
OutFile "vchanger-1.0.3.exe"
|
||||||
|
|
||||||
PageEx license
|
PageEx license
|
||||||
LicenseData "license.txt"
|
LicenseData "license.txt"
|
||||||
@ -121,13 +129,13 @@ Function .onInit
|
|||||||
SetShellVarContext all
|
SetShellVarContext all
|
||||||
#Determine the bitness of the OS and enable the correct section
|
#Determine the bitness of the OS and enable the correct section
|
||||||
${If} ${RunningX64}
|
${If} ${RunningX64}
|
||||||
SectionSetFlags SEC0001 ${SECTION_OFF}
|
SectionSetFlags ${SEC0001} ${SECTION_OFF}
|
||||||
SectionSetFlags SEC0002 ${SF_SELECTED}
|
SectionSetFlags ${SEC0002} ${SF_SELECTED}
|
||||||
StrCpy $INSTDIR "$PROGRAMFILES64\vchanger"
|
StrCpy $INSTDIR "$PROGRAMFILES64\vchanger"
|
||||||
SetRegView 64
|
SetRegView 64
|
||||||
${Else}
|
${Else}
|
||||||
SectionSetFlags SEC0002 ${SECTION_OFF}
|
SectionSetFlags ${SEC0002} ${SECTION_OFF}
|
||||||
SectionSetFlags SEC0001 ${SF_SELECTED}
|
SectionSetFlags ${SEC0001} ${SF_SELECTED}
|
||||||
StrCpy $INSTDIR "$PROGRAMFILES32\vchanger"
|
StrCpy $INSTDIR "$PROGRAMFILES32\vchanger"
|
||||||
SetRegView 32
|
SetRegView 32
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#
|
#
|
||||||
# Build for 32-bit and 64-bit Windows binary and create NSIS installer
|
# Build for 32-bit and 64-bit Windows binary and create NSIS installer
|
||||||
#
|
#
|
||||||
VERS=1.0.1
|
VERS=1.0.3
|
||||||
rm -f ./win32/vchanger-$VERS.exe
|
rm -f ./win32/vchanger-$VERS.exe
|
||||||
rm -f ./win32/vchanger.exe
|
rm -f ./win32/vchanger.exe
|
||||||
rm -f ./win32/vchanger64.exe
|
rm -f ./win32/vchanger64.exe
|
||||||
|
Loading…
x
Reference in New Issue
Block a user