Coverage Report

Created: 2025-11-16 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wget2/libwget/random.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2012 Tim Ruehsen
3
 * Copyright (c) 2016-2024 Free Software Foundation, Inc.
4
 *
5
 * This file is part of libwget.
6
 *
7
 * Libwget is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU Lesser General Public License as published by
9
 * the Free Software Foundation, either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * Libwget is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public License
18
 * along with libwget.  If not, see <https://www.gnu.org/licenses/>.
19
 *
20
 *
21
 * a multi-thread safe wrapper around gnulib random_r()
22
 *
23
 * Changelog
24
 * 22.01.2016  Tim Ruehsen  created
25
 *
26
 */
27
28
#include <config.h>
29
30
#include <stddef.h>
31
#include <stdlib.h>
32
#include <unistd.h>
33
#include <time.h>
34
#ifdef _WIN32
35
#  include <process.h>  /* getpid() */
36
#endif
37
38
#include <wget.h>
39
#include "private.h"
40
41
/**
42
 * \file
43
 * \brief Random functions
44
 * \defgroup libwget-random Random functions
45
 * @{
46
 *
47
 * This is wrapper code around gnulib's srandom_r() and random_r() with automatic seeding
48
 */
49
50
static int seeded;
51
static char statebuf[64];
52
static struct random_data state;
53
static wget_thread_mutex mutex;
54
static bool initialized;
55
56
static void  random_exit(void)
57
0
{
58
0
  if (initialized) {
59
0
    wget_thread_mutex_destroy(&mutex);
60
0
    initialized = false;
61
0
  }
62
0
}
63
64
INITIALIZER(random_init)
65
4
{
66
4
  if (!initialized) {
67
4
    wget_thread_mutex_init(&mutex);
68
4
    initialized = true;
69
4
    atexit(random_exit);
70
4
  }
71
4
}
72
73
/**
74
 * Random API initialization, allocating/preparing the internal resources.
75
 *
76
 * On systems with automatic library constructors, this function
77
 * doesn't have to be called explicitly.
78
 *
79
 * This function is not thread-safe.
80
 */
81
void wget_random_init(void)
82
0
{
83
0
  random_init();
84
0
}
85
86
/**
87
 * Random API deinitialization, free'ing all internal resources.
88
 *
89
 * On systems with automatic library destructors, this function
90
 * doesn't have to be called explicitly.
91
 *
92
 * This function is not thread-safe.
93
 */
94
void wget_random_exit(void)
95
0
{
96
0
  random_exit();
97
0
}
98
99
/**
100
 * \return Random value between 0 and RAND_MAX
101
 *
102
 * This functions wraps around gnulib's random_r(). It performs a thread-safe seeding on the first use,
103
 * if not done before by wget_srandom();
104
 */
105
int wget_random(void)
106
0
{
107
0
  int32_t r;
108
109
0
  wget_thread_mutex_lock(mutex);
110
111
0
  if (!seeded) {
112
    // seed random generator, used e.g. by Digest Authentication and --random-wait
113
0
    initstate_r((unsigned)(time(NULL) ^ getpid()), statebuf, sizeof(statebuf), &state);
114
0
    seeded = 1;
115
0
  }
116
117
0
  if (random_r(&state, &r))
118
0
    r = 0; // return 0 on failure
119
120
0
  wget_thread_mutex_unlock(mutex);
121
122
0
  return (int)r;
123
0
}
124
125
/**
126
 * \param[in] seed Value to seed the random generator
127
 *
128
 * This functions wraps around srandom_r() to make a thread-safe seeding for wget_random().
129
 */
130
void wget_srandom(unsigned int seed)
131
0
{
132
0
  wget_thread_mutex_lock(mutex);
133
134
0
  initstate_r(seed, statebuf, sizeof(statebuf), &state);
135
0
  seeded = 1;
136
137
0
  wget_thread_mutex_unlock(mutex);
138
0
}
139
140
/**@}*/