~ubuntu-branches/ubuntu/utopic/vsftpd/utopic-proposed

« back to all changes in this revision

Viewing changes to .pc/04-link-local.patch/sysutil.c

  • Committer: Package Import Robot
  • Author(s): Daniel Llewellyn (Bang Communications)
  • Date: 2013-05-08 14:08:53 UTC
  • mfrom: (2.6.1 squeeze)
  • Revision ID: package-import@ubuntu.com-20130508140853-ahhuki963v9fuuns
Tags: 3.0.2-1ubuntu2
* debian/patches/13-disable-clone-newpid.patch
  - patch to remove CLONE_NEWPID syscall
    see: https://bugzilla.novell.com/show_bug.cgi?id=786024#c38
    Fixes LP: #1160372

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Part of Very Secure FTPd
 
3
 * Licence: GPL v2
 
4
 * Author: Chris Evans
 
5
 * 
 
6
 * sysutil.c
 
7
 *
 
8
 * Routines to make the libc/syscall API more pleasant to use. Long term,
 
9
 * more libc/syscalls will go in here to reduce the number of .c files with
 
10
 * dependencies on libc or syscalls.
 
11
 */
 
12
 
 
13
#define PRIVATE_HANDS_OFF_syscall_retval syscall_retval
 
14
#define PRIVATE_HANDS_OFF_exit_status exit_status
 
15
#include "sysutil.h"
 
16
#include "utility.h"
 
17
#include "tunables.h"
 
18
#include "sysdeputil.h"
 
19
 
 
20
/* Activate 64-bit file support on Linux/32bit plus others */
 
21
#define _FILE_OFFSET_BITS 64
 
22
#define _LARGEFILE_SOURCE 1
 
23
#define _LARGEFILE64_SOURCE 1
 
24
#define _LARGE_FILES 1
 
25
 
 
26
/* For Linux, this adds nothing :-) */
 
27
#include "port/porting_junk.h"
 
28
 
 
29
#include <signal.h>
 
30
#include <string.h>
 
31
#include <stdlib.h>
 
32
#include <unistd.h>
 
33
#include <sys/types.h>
 
34
#include <sys/socket.h>
 
35
#include <sys/mman.h>
 
36
#include <sys/stat.h>
 
37
#include <fcntl.h>
 
38
#include <netinet/in.h>
 
39
#include <stdio.h>
 
40
#include <dirent.h>
 
41
#include <time.h>
 
42
#include <arpa/inet.h>
 
43
#include <errno.h>
 
44
#include <pwd.h>
 
45
#include <grp.h>
 
46
#include <ctype.h>
 
47
#include <sys/wait.h>
 
48
#include <sys/time.h>
 
49
/* Must be before netinet/ip.h. Found on FreeBSD, Solaris */
 
50
#include <netinet/in_systm.h>
 
51
#include <netinet/ip.h>
 
52
#include <netinet/tcp.h>
 
53
#include <limits.h>
 
54
#include <syslog.h>
 
55
#include <utime.h>
 
56
#include <netdb.h>
 
57
#include <sys/resource.h>
 
58
 
 
59
/* Private variables to this file */
 
60
/* Current umask() */
 
61
static unsigned int s_current_umask;
 
62
/* Cached time */
 
63
static struct timeval s_current_time;
 
64
/* Current pid */
 
65
static int s_current_pid = -1;
 
66
/* Exit function */
 
67
static exitfunc_t s_exit_func;
 
68
/* Difference in timezone from GMT in seconds */
 
69
static long s_timezone;
 
70
 
 
71
/* Our internal signal handling implementation details */
 
72
static struct vsf_sysutil_sig_details
 
73
{
 
74
  vsf_sighandle_t sync_sig_handler;
 
75
  void* p_private;
 
76
  volatile sig_atomic_t pending;
 
77
  int running;
 
78
  int use_alarm;
 
79
} s_sig_details[NSIG];
 
80
 
 
81
static vsf_context_io_t s_io_handler;
 
82
static void* s_p_io_handler_private;
 
83
static int s_io_handler_running;
 
84
 
 
85
struct vsf_sysutil_sockaddr
 
86
{
 
87
  union
 
88
  {
 
89
    struct sockaddr u_sockaddr;
 
90
    struct sockaddr_in u_sockaddr_in;
 
91
    struct sockaddr_in6 u_sockaddr_in6;
 
92
  } u;
 
93
};
 
94
 
 
95
/* File locals */
 
96
static void vsf_sysutil_common_sighandler(int signum);
 
97
static void vsf_sysutil_alrm_sighandler(int signum);
 
98
static int vsf_sysutil_translate_sig(const enum EVSFSysUtilSignal sig);
 
99
static void vsf_sysutil_set_sighandler(int sig, void (*p_handlefunc)(int));
 
100
static int vsf_sysutil_translate_memprot(
 
101
  const enum EVSFSysUtilMapPermission perm);
 
102
static int vsf_sysutil_translate_openmode(
 
103
  const enum EVSFSysUtilOpenMode mode);
 
104
static void vsf_sysutil_alloc_statbuf(struct vsf_sysutil_statbuf** p_ptr);
 
105
void vsf_sysutil_sockaddr_alloc(struct vsf_sysutil_sockaddr** p_sockptr);
 
106
static int lock_internal(int fd, int lock_type);
 
107
 
 
108
static void
 
109
vsf_sysutil_alrm_sighandler(int signum)
 
110
{
 
111
  (void) signum;
 
112
  alarm(1);
 
113
}
 
114
 
 
115
static void
 
116
vsf_sysutil_common_sighandler(int signum)
 
117
{
 
118
  if (signum < 0 || signum >= NSIG)
 
119
  {
 
120
    /* "cannot happen" */
 
121
    return;
 
122
  }
 
123
  if (s_sig_details[signum].sync_sig_handler)
 
124
  {
 
125
    s_sig_details[signum].pending = 1;
 
126
    /* Since this synchronous signal framework has a small race (signal coming
 
127
     * in just before we start a blocking call), there's the option to fire an
 
128
     * alarm repeatedly until the signal is handled.
 
129
     */
 
130
    if (s_sig_details[signum].use_alarm)
 
131
    {
 
132
      alarm(1);
 
133
    }
 
134
  }
 
135
}
 
136
 
 
137
/* Notes. This signal check is evaluated after potentially blocking system
 
138
 * calls, i.e. at highly defined points in the code. Since we only interrupt
 
139
 * at these definite locations, the signal handlers can be non-trivial
 
140
 * without us having to worry about re-entrancy.
 
141
 *
 
142
 * We guarantee that a handler for a given signal is not re-entrant. This
 
143
 * is taken care of by the "running" flag.
 
144
 *
 
145
 * This call itself can only be re-entered once we dereference the actual
 
146
 * hander function pointer, so we are safe with respect to races modifying
 
147
 * the "running" flag.
 
148
 */
 
149
void
 
150
vsf_sysutil_check_pending_actions(
 
151
  const enum EVSFSysUtilInterruptContext context, int retval, int fd)
 
152
{
 
153
  unsigned int i;
 
154
  /* Check the i/o handler before the signal handlers */
 
155
  if (s_io_handler && !s_io_handler_running && context == kVSFSysUtilIO)
 
156
  {
 
157
    s_io_handler_running = 1;
 
158
    (*s_io_handler)(retval, fd, s_p_io_handler_private);
 
159
    s_io_handler_running = 0;
 
160
  }
 
161
  for (i=0; i < NSIG; ++i)
 
162
  {
 
163
    if (s_sig_details[i].pending && !s_sig_details[i].running)
 
164
    {
 
165
      s_sig_details[i].running = 1;
 
166
      if (s_sig_details[i].use_alarm)
 
167
      {
 
168
        alarm(0);
 
169
      }
 
170
      if (s_sig_details[i].sync_sig_handler)
 
171
      {
 
172
        s_sig_details[i].pending = 0;
 
173
        (*(s_sig_details[i].sync_sig_handler))(s_sig_details[i].p_private);
 
174
      }
 
175
      s_sig_details[i].running = 0;
 
176
    }
 
177
  }
 
178
}
 
179
 
 
180
static int
 
181
vsf_sysutil_translate_sig(const enum EVSFSysUtilSignal sig)
 
182
{
 
183
  int realsig = 0;
 
184
  switch (sig)
 
185
  {
 
186
    case kVSFSysUtilSigALRM:
 
187
      realsig = SIGALRM;
 
188
      break;
 
189
    case kVSFSysUtilSigTERM:
 
190
      realsig = SIGTERM;
 
191
      break;
 
192
    case kVSFSysUtilSigCHLD:
 
193
      realsig = SIGCHLD;
 
194
      break;
 
195
    case kVSFSysUtilSigPIPE:
 
196
      realsig = SIGPIPE;
 
197
      break;
 
198
    case kVSFSysUtilSigURG:
 
199
      realsig = SIGURG;
 
200
      break;
 
201
    case kVSFSysUtilSigHUP:
 
202
      realsig = SIGHUP;
 
203
      break;
 
204
    default:
 
205
      bug("unknown signal in vsf_sysutil_translate_sig");
 
206
      break;
 
207
  }
 
208
  if (realsig < 0 || realsig >= NSIG)
 
209
  {
 
210
    bug("signal out of range in vsf_sysutil_translate_sig");
 
211
  }
 
212
  return realsig;
 
213
}
 
214
 
 
215
void
 
216
vsf_sysutil_install_sighandler(const enum EVSFSysUtilSignal sig,
 
217
                               vsf_sighandle_t handler,
 
218
                               void* p_private,
 
219
                               int use_alarm)
 
220
{
 
221
  int realsig = vsf_sysutil_translate_sig(sig);
 
222
  s_sig_details[realsig].p_private = p_private;
 
223
  s_sig_details[realsig].sync_sig_handler = handler;
 
224
  s_sig_details[realsig].use_alarm = use_alarm;
 
225
  vsf_sysutil_set_sighandler(realsig, vsf_sysutil_common_sighandler);
 
226
  if (use_alarm && realsig != SIGALRM)
 
227
  {
 
228
    vsf_sysutil_set_sighandler(SIGALRM, vsf_sysutil_alrm_sighandler);
 
229
  }
 
230
}
 
231
 
 
232
void
 
233
vsf_sysutil_default_sig(const enum EVSFSysUtilSignal sig)
 
234
{
 
235
  int realsig = vsf_sysutil_translate_sig(sig);
 
236
  vsf_sysutil_set_sighandler(realsig, SIG_DFL);
 
237
  s_sig_details[realsig].p_private = NULL;
 
238
  s_sig_details[realsig].sync_sig_handler = NULL;
 
239
}
 
240
 
 
241
void
 
242
vsf_sysutil_install_null_sighandler(const enum EVSFSysUtilSignal sig)
 
243
{
 
244
  int realsig = vsf_sysutil_translate_sig(sig);
 
245
  s_sig_details[realsig].p_private = NULL;
 
246
  s_sig_details[realsig].sync_sig_handler = NULL;
 
247
  vsf_sysutil_set_sighandler(realsig, vsf_sysutil_common_sighandler);
 
248
}
 
249
 
 
250
void
 
251
vsf_sysutil_install_async_sighandler(const enum EVSFSysUtilSignal sig,
 
252
                                     vsf_async_sighandle_t handler)
 
253
{
 
254
  int realsig = vsf_sysutil_translate_sig(sig);
 
255
  s_sig_details[realsig].p_private = NULL;
 
256
  s_sig_details[realsig].sync_sig_handler = NULL;
 
257
  vsf_sysutil_block_sig(sig);
 
258
  vsf_sysutil_set_sighandler(realsig, handler);
 
259
}
 
260
 
 
261
static void
 
262
vsf_sysutil_set_sighandler(int sig, void (*p_handlefunc)(int))
 
263
{
 
264
  int retval;
 
265
  struct sigaction sigact;
 
266
  vsf_sysutil_memclr(&sigact, sizeof(sigact));
 
267
  sigact.sa_handler = p_handlefunc;
 
268
  retval = sigfillset(&sigact.sa_mask);
 
269
  if (retval != 0)
 
270
  {
 
271
    die("sigfillset");
 
272
  }
 
273
  retval = sigaction(sig, &sigact, NULL);
 
274
  if (retval != 0)
 
275
  {
 
276
    die("sigaction");
 
277
  }
 
278
}
 
279
 
 
280
void
 
281
vsf_sysutil_block_sig(const enum EVSFSysUtilSignal sig)
 
282
{
 
283
  sigset_t sset;
 
284
  int retval;
 
285
  int realsig = vsf_sysutil_translate_sig(sig);
 
286
  retval = sigemptyset(&sset);
 
287
  if (retval != 0)
 
288
  {
 
289
    die("sigemptyset");
 
290
  }
 
291
  retval = sigaddset(&sset, realsig);
 
292
  if (retval != 0)
 
293
  {
 
294
    die("sigaddset");
 
295
  }
 
296
  retval = sigprocmask(SIG_BLOCK, &sset, NULL);
 
297
  if (retval != 0)
 
298
  {
 
299
    die("sigprocmask");
 
300
  }
 
301
}
 
302
 
 
303
void
 
304
vsf_sysutil_unblock_sig(const enum EVSFSysUtilSignal sig)
 
305
{
 
306
  sigset_t sset;
 
307
  int retval;
 
308
  int realsig = vsf_sysutil_translate_sig(sig);
 
309
  retval = sigemptyset(&sset);
 
310
  if (retval != 0)
 
311
  {
 
312
    die("sigemptyset");
 
313
  }
 
314
  retval = sigaddset(&sset, realsig);
 
315
  if (retval != 0)
 
316
  {
 
317
    die("sigaddset");
 
318
  }
 
319
  retval = sigprocmask(SIG_UNBLOCK, &sset, NULL);
 
320
  if (retval != 0)
 
321
  {
 
322
    die("sigprocmask");
 
323
  }
 
324
}
 
325
void
 
326
vsf_sysutil_install_io_handler(vsf_context_io_t handler, void* p_private)
 
327
{
 
328
  if (s_io_handler != NULL)
 
329
  {
 
330
    bug("double register of i/o handler");
 
331
  }
 
332
  s_io_handler = handler;
 
333
  s_p_io_handler_private = p_private;
 
334
}
 
335
 
 
336
void
 
337
vsf_sysutil_uninstall_io_handler(void)
 
338
{
 
339
  if (s_io_handler == NULL)
 
340
  {
 
341
    bug("no i/o handler to unregister!");
 
342
  }
 
343
  s_io_handler = NULL;
 
344
  s_p_io_handler_private = NULL;
 
345
}
 
346
 
 
347
void
 
348
vsf_sysutil_set_alarm(const unsigned int trigger_seconds)
 
349
{
 
350
  (void) alarm(trigger_seconds);
 
351
}
 
352
 
 
353
void
 
354
vsf_sysutil_clear_alarm(void)
 
355
{
 
356
  vsf_sysutil_set_alarm(0);
 
357
}
 
358
 
 
359
int
 
360
vsf_sysutil_read(const int fd, void* p_buf, const unsigned int size)
 
361
{
 
362
  while (1)
 
363
  {
 
364
    int retval = read(fd, p_buf, size);
 
365
    int saved_errno = errno;
 
366
    vsf_sysutil_check_pending_actions(kVSFSysUtilIO, retval, fd);
 
367
    if (retval < 0 && saved_errno == EINTR)
 
368
    {
 
369
      continue;
 
370
    }
 
371
    return retval;
 
372
  }
 
373
}
 
374
 
 
375
int
 
376
vsf_sysutil_write(const int fd, const void* p_buf, const unsigned int size)
 
377
{
 
378
  while (1)
 
379
  {
 
380
    int retval = write(fd, p_buf, size);
 
381
    int saved_errno = errno;
 
382
    vsf_sysutil_check_pending_actions(kVSFSysUtilIO, retval, fd);
 
383
    if (retval < 0 && saved_errno == EINTR)
 
384
    {
 
385
      continue;
 
386
    }
 
387
    return retval;
 
388
  }
 
389
}
 
390
 
 
391
int
 
392
vsf_sysutil_read_loop(const int fd, void* p_buf, unsigned int size)
 
393
{
 
394
  int retval;
 
395
  int num_read = 0;
 
396
  if (size > INT_MAX)
 
397
  {
 
398
    die("size too big in vsf_sysutil_read_loop");
 
399
  }
 
400
  while (1)
 
401
  {
 
402
    retval = vsf_sysutil_read(fd, (char*)p_buf + num_read, size);
 
403
    if (retval < 0)
 
404
    {
 
405
      return retval;
 
406
    }
 
407
    else if (retval == 0)
 
408
    {
 
409
      /* Read all we're going to read.. */
 
410
      return num_read; 
 
411
    }
 
412
    if ((unsigned int) retval > size)
 
413
    {
 
414
      die("retval too big in vsf_sysutil_read_loop");
 
415
    }
 
416
    num_read += retval;
 
417
    size -= (unsigned int) retval;
 
418
    if (size == 0)
 
419
    {
 
420
      /* Hit the read target, cool. */
 
421
      return num_read;
 
422
    }
 
423
  }
 
424
}
 
425
 
 
426
int
 
427
vsf_sysutil_write_loop(const int fd, const void* p_buf, unsigned int size)
 
428
{
 
429
  int retval;
 
430
  int num_written = 0;
 
431
  if (size > INT_MAX)
 
432
  {
 
433
    die("size too big in vsf_sysutil_write_loop");
 
434
  }
 
435
  while (1)
 
436
  {
 
437
    retval = vsf_sysutil_write(fd, (const char*)p_buf + num_written, size);
 
438
    if (retval < 0)
 
439
    {
 
440
      /* Error */
 
441
      return retval;
 
442
    }
 
443
    else if (retval == 0)
 
444
    {
 
445
      /* Written all we're going to write.. */
 
446
      return num_written;
 
447
    }
 
448
    if ((unsigned int) retval > size)
 
449
    {
 
450
      die("retval too big in vsf_sysutil_write_loop");
 
451
    }
 
452
    num_written += retval;
 
453
    size -= (unsigned int) retval;
 
454
    if (size == 0)
 
455
    {
 
456
      /* Hit the write target, cool. */
 
457
      return num_written;
 
458
    }
 
459
  }
 
460
}
 
461
 
 
462
filesize_t
 
463
vsf_sysutil_get_file_offset(const int file_fd)
 
464
{
 
465
  filesize_t retval = lseek(file_fd, 0, SEEK_CUR);
 
466
  if (retval < 0)
 
467
  {
 
468
    die("lseek");
 
469
  }
 
470
  return retval;
 
471
}
 
472
 
 
473
void
 
474
vsf_sysutil_lseek_to(const int fd, filesize_t seek_pos)
 
475
{
 
476
  filesize_t retval;
 
477
  if (seek_pos < 0)
 
478
  {
 
479
    die("negative seek_pos in vsf_sysutil_lseek_to");
 
480
  }
 
481
  retval = lseek(fd, seek_pos, SEEK_SET);
 
482
  if (retval < 0)
 
483
  {
 
484
    die("lseek");
 
485
  }
 
486
}
 
487
 
 
488
void
 
489
vsf_sysutil_lseek_end(const int fd)
 
490
{
 
491
  filesize_t retval;
 
492
  retval = lseek(fd, 0, SEEK_END);
 
493
  if (retval < 0)
 
494
  {
 
495
    die("lseek");
 
496
  }
 
497
}
 
498
 
 
499
void*
 
500
vsf_sysutil_malloc(unsigned int size)
 
501
{
 
502
  void* p_ret;
 
503
  /* Paranoia - what if we got an integer overflow/underflow? */
 
504
  if (size == 0 || size > INT_MAX)
 
505
  {
 
506
    bug("zero or big size in vsf_sysutil_malloc");
 
507
  }  
 
508
  p_ret = malloc(size);
 
509
  if (p_ret == NULL)
 
510
  {
 
511
    die("malloc");
 
512
  }
 
513
  return p_ret;
 
514
}
 
515
 
 
516
void*
 
517
vsf_sysutil_realloc(void* p_ptr, unsigned int size)
 
518
{
 
519
  void* p_ret;
 
520
  if (size == 0 || size > INT_MAX)
 
521
  {
 
522
    bug("zero or big size in vsf_sysutil_realloc");
 
523
  }
 
524
  p_ret = realloc(p_ptr, size);
 
525
  if (p_ret == NULL)
 
526
  {
 
527
    die("realloc");
 
528
  }
 
529
  return p_ret;
 
530
}
 
531
 
 
532
void
 
533
vsf_sysutil_free(void* p_ptr)
 
534
{
 
535
  if (p_ptr == NULL)
 
536
  {
 
537
    bug("vsf_sysutil_free got a null pointer");
 
538
  }
 
539
  free(p_ptr);
 
540
}
 
541
 
 
542
unsigned int
 
543
vsf_sysutil_getpid(void)
 
544
{
 
545
  if (s_current_pid == -1)
 
546
  {
 
547
    s_current_pid = vsf_sysutil_getpid_nocache();
 
548
  }
 
549
  return (unsigned int) s_current_pid;
 
550
}
 
551
 
 
552
int
 
553
vsf_sysutil_fork(void)
 
554
{
 
555
  int retval = vsf_sysutil_fork_failok();
 
556
  if (retval < 0)
 
557
  {
 
558
    die("fork");
 
559
  }
 
560
  return retval;
 
561
}
 
562
 
 
563
int
 
564
vsf_sysutil_fork_failok(void)
 
565
{
 
566
  int retval;
 
567
  retval = fork();
 
568
  if (retval == 0)
 
569
  {
 
570
    vsf_sysutil_post_fork();
 
571
  }
 
572
  return retval;
 
573
}
 
574
 
 
575
void
 
576
vsf_sysutil_set_exit_func(exitfunc_t exitfunc)
 
577
{
 
578
  s_exit_func = exitfunc;
 
579
}
 
580
 
 
581
void
 
582
vsf_sysutil_exit(int exit_code)
 
583
{
 
584
  if (s_exit_func)
 
585
  {
 
586
    exitfunc_t curr_func = s_exit_func;
 
587
    /* Prevent recursion */
 
588
    s_exit_func = 0;
 
589
    (*curr_func)();
 
590
  }
 
591
  _exit(exit_code);
 
592
}
 
593
 
 
594
struct vsf_sysutil_wait_retval
 
595
vsf_sysutil_wait(void)
 
596
{
 
597
  struct vsf_sysutil_wait_retval retval;
 
598
  vsf_sysutil_memclr(&retval, sizeof(retval));
 
599
  while (1)
 
600
  {
 
601
    int sys_ret = wait(&retval.exit_status);
 
602
    if (sys_ret < 0 && errno == EINTR)
 
603
    {
 
604
      vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0);
 
605
      continue;
 
606
    }
 
607
    retval.syscall_retval = sys_ret;
 
608
    return retval;
 
609
  }
 
610
}
 
611
 
 
612
int
 
613
vsf_sysutil_wait_reap_one(void)
 
614
{
 
615
  int retval = waitpid(-1, NULL, WNOHANG);
 
616
  if (retval == 0 || (retval < 0 && errno == ECHILD))
 
617
  {
 
618
    /* No more children */
 
619
    return 0;
 
620
  }
 
621
  if (retval < 0)
 
622
  {
 
623
    die("waitpid");
 
624
  }
 
625
  /* Got one */
 
626
  return retval;
 
627
}
 
628
 
 
629
int
 
630
vsf_sysutil_wait_get_retval(const struct vsf_sysutil_wait_retval* p_waitret)
 
631
{
 
632
  return p_waitret->syscall_retval;
 
633
}
 
634
 
 
635
int
 
636
vsf_sysutil_wait_exited_normally(
 
637
  const struct vsf_sysutil_wait_retval* p_waitret)
 
638
{
 
639
  int status = ((struct vsf_sysutil_wait_retval*) p_waitret)->exit_status;
 
640
  return WIFEXITED(status);
 
641
}
 
642
 
 
643
int
 
644
vsf_sysutil_wait_get_exitcode(const struct vsf_sysutil_wait_retval* p_waitret)
 
645
{
 
646
  int status;
 
647
  if (!vsf_sysutil_wait_exited_normally(p_waitret))
 
648
  {
 
649
    bug("not a normal exit in vsf_sysutil_wait_get_exitcode");
 
650
  }
 
651
  status = ((struct vsf_sysutil_wait_retval*) p_waitret)->exit_status;
 
652
  return WEXITSTATUS(status);
 
653
}
 
654
 
 
655
void
 
656
vsf_sysutil_activate_keepalive(int fd)
 
657
{
 
658
  int keepalive = 1;
 
659
  int retval = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive,
 
660
                          sizeof(keepalive));
 
661
  if (retval != 0)
 
662
  {
 
663
    die("setsockopt: keepalive");
 
664
  }
 
665
}
 
666
 
 
667
void
 
668
vsf_sysutil_activate_reuseaddr(int fd)
 
669
{
 
670
  int reuseaddr = 1;
 
671
  int retval = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
 
672
                          sizeof(reuseaddr));
 
673
  if (retval != 0)
 
674
  {
 
675
    die("setsockopt: reuseaddr");
 
676
  }
 
677
}
 
678
 
 
679
void
 
680
vsf_sysutil_set_nodelay(int fd)
 
681
{
 
682
  int nodelay = 1;
 
683
  int retval = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &nodelay,
 
684
                          sizeof(nodelay));
 
685
  if (retval != 0)
 
686
  {
 
687
    die("setsockopt: nodelay");
 
688
  }
 
689
}
 
690
 
 
691
void
 
692
vsf_sysutil_activate_sigurg(int fd)
 
693
{
 
694
  int retval = fcntl(fd, F_SETOWN, vsf_sysutil_getpid());
 
695
  if (retval != 0)
 
696
  {
 
697
    die("fcntl");
 
698
  }
 
699
}
 
700
 
 
701
void
 
702
vsf_sysutil_activate_oobinline(int fd)
 
703
{
 
704
  int oob_inline = 1;
 
705
  int retval = setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &oob_inline,
 
706
                          sizeof(oob_inline));
 
707
  if (retval != 0)
 
708
  {
 
709
    die("setsockopt: oobinline");
 
710
  }
 
711
}
 
712
 
 
713
void
 
714
vsf_sysutil_set_iptos_throughput(int fd)
 
715
{
 
716
  int tos = IPTOS_THROUGHPUT;
 
717
  /* Ignore failure to set (maybe this IP stack demands privilege for this) */
 
718
  (void) setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
 
719
}
 
720
 
 
721
void
 
722
vsf_sysutil_activate_linger(int fd)
 
723
{
 
724
  int retval;
 
725
  struct linger the_linger;
 
726
  vsf_sysutil_memclr(&the_linger, sizeof(the_linger));
 
727
  the_linger.l_onoff = 1;
 
728
  the_linger.l_linger = 60 * 10;
 
729
  retval = setsockopt(fd, SOL_SOCKET, SO_LINGER, &the_linger,
 
730
                      sizeof(the_linger));
 
731
  if (retval != 0)
 
732
  {
 
733
    die("setsockopt: linger");
 
734
  }
 
735
}
 
736
 
 
737
void
 
738
vsf_sysutil_deactivate_linger_failok(int fd)
 
739
{
 
740
  struct linger the_linger;
 
741
  the_linger.l_onoff = 0;
 
742
  the_linger.l_linger = 0;
 
743
  (void) setsockopt(fd, SOL_SOCKET, SO_LINGER, &the_linger, sizeof(the_linger));
 
744
}
 
745
 
 
746
void
 
747
vsf_sysutil_activate_noblock(int fd)
 
748
{
 
749
  int retval;
 
750
  int curr_flags = fcntl(fd, F_GETFL);
 
751
  if (vsf_sysutil_retval_is_error(curr_flags))
 
752
  {
 
753
    die("fcntl");
 
754
  }
 
755
  curr_flags |= O_NONBLOCK;
 
756
  retval = fcntl(fd, F_SETFL, curr_flags);
 
757
  if (retval != 0)
 
758
  {
 
759
    die("fcntl");
 
760
  }
 
761
}
 
762
 
 
763
void
 
764
vsf_sysutil_deactivate_noblock(int fd)
 
765
{
 
766
  int retval;
 
767
  int curr_flags = fcntl(fd, F_GETFL);
 
768
  if (vsf_sysutil_retval_is_error(curr_flags))
 
769
  {
 
770
    die("fcntl");
 
771
  }
 
772
  curr_flags &= ~O_NONBLOCK;
 
773
  retval = fcntl(fd, F_SETFL, curr_flags);
 
774
  if (retval != 0)
 
775
  {
 
776
    die("fcntl");
 
777
  }
 
778
}
 
779
 
 
780
int
 
781
vsf_sysutil_recv_peek(const int fd, void* p_buf, unsigned int len)
 
782
{
 
783
  while (1)
 
784
  {
 
785
    int retval = recv(fd, p_buf, len, MSG_PEEK);
 
786
    int saved_errno = errno;
 
787
    vsf_sysutil_check_pending_actions(kVSFSysUtilIO, retval, fd);
 
788
    if (retval < 0 && saved_errno == EINTR)
 
789
    {
 
790
      continue;
 
791
    }
 
792
    return retval;
 
793
  }
 
794
}
 
795
 
 
796
int
 
797
vsf_sysutil_atoi(const char* p_str)
 
798
{
 
799
  return atoi(p_str);
 
800
}
 
801
 
 
802
filesize_t
 
803
vsf_sysutil_a_to_filesize_t(const char* p_str)
 
804
{
 
805
  /* atoll() is C99 standard - but even modern FreeBSD, OpenBSD don't have
 
806
   * it, so we'll supply our own
 
807
   */
 
808
  filesize_t result = 0;
 
809
  filesize_t mult = 1;
 
810
  unsigned int len = vsf_sysutil_strlen(p_str);
 
811
  unsigned int i;
 
812
  /* Bail if the number is excessively big (petabytes!) */
 
813
  if (len > 15)
 
814
  {
 
815
    return 0;
 
816
  }
 
817
  for (i=0; i<len; ++i)
 
818
  {
 
819
    char the_char = p_str[len-(i+1)];
 
820
    filesize_t val;
 
821
    if (the_char < '0' || the_char > '9')
 
822
    {
 
823
      return 0;
 
824
    }
 
825
    val = the_char - '0';
 
826
    val *= mult;
 
827
    result += val;
 
828
    mult *= 10;
 
829
  }
 
830
  return result;
 
831
}
 
832
 
 
833
const char*
 
834
vsf_sysutil_ulong_to_str(unsigned long the_ulong)
 
835
{
 
836
  static char ulong_buf[32];
 
837
  (void) snprintf(ulong_buf, sizeof(ulong_buf), "%lu", the_ulong);
 
838
  return ulong_buf;
 
839
}
 
840
 
 
841
const char*
 
842
vsf_sysutil_filesize_t_to_str(filesize_t the_filesize)
 
843
{
 
844
  static char filesize_buf[32];
 
845
  if (sizeof(long) == 8)
 
846
  {
 
847
    /* Avoid using non-standard %ll if we can */
 
848
    (void) snprintf(filesize_buf, sizeof(filesize_buf), "%ld",
 
849
                    (long) the_filesize);
 
850
  }
 
851
  else
 
852
  {
 
853
    (void) snprintf(filesize_buf, sizeof(filesize_buf), "%lld", the_filesize);
 
854
  }
 
855
  return filesize_buf;
 
856
}
 
857
 
 
858
const char*
 
859
vsf_sysutil_double_to_str(double the_double)
 
860
{
 
861
  static char double_buf[32];
 
862
  (void) snprintf(double_buf, sizeof(double_buf), "%.2f", the_double);
 
863
  return double_buf;
 
864
}
 
865
 
 
866
const char*
 
867
vsf_sysutil_uint_to_octal(unsigned int the_uint)
 
868
{
 
869
  static char octal_buf[32];
 
870
  if (the_uint == 0)
 
871
  {
 
872
    octal_buf[0] = '0';
 
873
    octal_buf[1] = '\0';
 
874
  }
 
875
  else
 
876
  {
 
877
    (void) snprintf(octal_buf, sizeof(octal_buf), "0%o", the_uint);
 
878
  }
 
879
  return octal_buf;
 
880
}
 
881
 
 
882
unsigned int
 
883
vsf_sysutil_octal_to_uint(const char* p_str)
 
884
{
 
885
  /* NOTE - avoiding using sscanf() parser */
 
886
  unsigned int result = 0;
 
887
  int seen_non_zero_digit = 0;
 
888
  while (*p_str != '\0')
 
889
  {
 
890
    int digit = *p_str;
 
891
    if (!isdigit(digit) || digit > '7')
 
892
    {
 
893
      break;
 
894
    }
 
895
    if (digit != '0')
 
896
    {
 
897
      seen_non_zero_digit = 1;
 
898
    }
 
899
    if (seen_non_zero_digit)
 
900
    {
 
901
      result <<= 3;
 
902
      result += (digit - '0');
 
903
    }
 
904
    p_str++;
 
905
  }
 
906
  return result;
 
907
}
 
908
 
 
909
int
 
910
vsf_sysutil_toupper(int the_char)
 
911
{
 
912
  return toupper((unsigned char) the_char);
 
913
}
 
914
 
 
915
int
 
916
vsf_sysutil_isspace(int the_char)
 
917
{
 
918
  return isspace((unsigned char) the_char);
 
919
}
 
920
 
 
921
int
 
922
vsf_sysutil_isprint(int the_char)
 
923
{
 
924
  /* From Solar - we know better than some libc's! Don't let any potential
 
925
   * control chars through
 
926
   */
 
927
  unsigned char uc = (unsigned char) the_char;
 
928
  if (uc <= 31)
 
929
  {
 
930
    return 0;
 
931
  }
 
932
  if (uc == 177)
 
933
  {
 
934
    return 0;
 
935
  }
 
936
  if (uc >= 128 && uc <= 159)
 
937
  {
 
938
    return 0;
 
939
  }
 
940
  return isprint(the_char);
 
941
}
 
942
 
 
943
int
 
944
vsf_sysutil_isalnum(int the_char)
 
945
{
 
946
  return isalnum((unsigned char) the_char);
 
947
}
 
948
 
 
949
int
 
950
vsf_sysutil_isdigit(int the_char)
 
951
{
 
952
  return isdigit((unsigned char) the_char);
 
953
}
 
954
 
 
955
char*
 
956
vsf_sysutil_getcwd(char* p_dest, const unsigned int buf_size)
 
957
{
 
958
  char* p_retval;
 
959
  if (buf_size == 0) {
 
960
    return p_dest;
 
961
  }
 
962
  p_retval = getcwd(p_dest, buf_size);
 
963
  p_dest[buf_size - 1] = '\0';
 
964
  return p_retval;
 
965
}
 
966
 
 
967
int
 
968
vsf_sysutil_mkdir(const char* p_dirname, const unsigned int mode)
 
969
{
 
970
  return mkdir(p_dirname, mode);
 
971
}
 
972
 
 
973
int
 
974
vsf_sysutil_rmdir(const char* p_dirname)
 
975
{
 
976
  return rmdir(p_dirname);
 
977
}
 
978
 
 
979
int
 
980
vsf_sysutil_chdir(const char* p_dirname)
 
981
{
 
982
  return chdir(p_dirname);
 
983
}
 
984
 
 
985
int
 
986
vsf_sysutil_rename(const char* p_from, const char* p_to)
 
987
{
 
988
  return rename(p_from, p_to);
 
989
}
 
990
 
 
991
struct vsf_sysutil_dir*
 
992
vsf_sysutil_opendir(const char* p_dirname)
 
993
{
 
994
  return (struct vsf_sysutil_dir*) opendir(p_dirname);
 
995
}
 
996
 
 
997
void
 
998
vsf_sysutil_closedir(struct vsf_sysutil_dir* p_dir)
 
999
{
 
1000
  DIR* p_real_dir = (DIR*) p_dir;
 
1001
  int retval = closedir(p_real_dir);
 
1002
  if (retval != 0)
 
1003
  {
 
1004
    die("closedir");
 
1005
  }
 
1006
}
 
1007
 
 
1008
const char*
 
1009
vsf_sysutil_next_dirent(struct vsf_sysutil_dir* p_dir)
 
1010
{
 
1011
  DIR* p_real_dir = (DIR*) p_dir;
 
1012
  struct dirent* p_dirent = readdir(p_real_dir);
 
1013
  if (p_dirent == NULL)
 
1014
  {
 
1015
    return NULL;
 
1016
  }
 
1017
  return p_dirent->d_name;
 
1018
}
 
1019
 
 
1020
unsigned int
 
1021
vsf_sysutil_strlen(const char* p_text)
 
1022
{
 
1023
  size_t ret = strlen(p_text);
 
1024
  /* A defense in depth measure. */
 
1025
  if (ret > INT_MAX / 8)
 
1026
  {
 
1027
    die("string suspiciously long");
 
1028
  }
 
1029
  return (unsigned int) ret;
 
1030
}
 
1031
 
 
1032
char*
 
1033
vsf_sysutil_strdup(const char* p_str)
 
1034
{
 
1035
  return strdup(p_str);
 
1036
}
 
1037
 
 
1038
void
 
1039
vsf_sysutil_memclr(void* p_dest, unsigned int size)
 
1040
{
 
1041
  /* Safety */
 
1042
  if (size == 0)
 
1043
  {
 
1044
    return;
 
1045
  }
 
1046
  memset(p_dest, '\0', size);
 
1047
}
 
1048
 
 
1049
void
 
1050
vsf_sysutil_memcpy(void* p_dest, const void* p_src, const unsigned int size)
 
1051
{
 
1052
  /* Safety */
 
1053
  if (size == 0)
 
1054
  {
 
1055
    return;
 
1056
  }
 
1057
  /* Defense in depth */
 
1058
  if (size > INT_MAX)
 
1059
  {
 
1060
    die("possible negative value to memcpy?");
 
1061
  }
 
1062
  memcpy(p_dest, p_src, size);
 
1063
}
 
1064
 
 
1065
void
 
1066
vsf_sysutil_strcpy(char* p_dest, const char* p_src, unsigned int maxsize)
 
1067
{
 
1068
  if (maxsize == 0)
 
1069
  {
 
1070
    return;
 
1071
  }
 
1072
  strncpy(p_dest, p_src, maxsize);
 
1073
  p_dest[maxsize - 1] = '\0';
 
1074
}
 
1075
 
 
1076
int
 
1077
vsf_sysutil_memcmp(const void* p_src1, const void* p_src2, unsigned int size)
 
1078
{
 
1079
  /* Safety */
 
1080
  if (size == 0)
 
1081
  {
 
1082
    return 0;
 
1083
  }
 
1084
  return memcmp(p_src1, p_src2, size);
 
1085
}
 
1086
 
 
1087
int
 
1088
vsf_sysutil_strcmp(const char* p_src1, const char* p_src2)
 
1089
{
 
1090
  return strcmp(p_src1, p_src2);
 
1091
}
 
1092
 
 
1093
unsigned int
 
1094
vsf_sysutil_getpagesize(void)
 
1095
{
 
1096
  static unsigned int s_page_size;
 
1097
  if (s_page_size == 0)
 
1098
  {
 
1099
    s_page_size = getpagesize();
 
1100
    if (s_page_size == 0)
 
1101
    {
 
1102
      die("getpagesize");
 
1103
    }
 
1104
  }
 
1105
  return s_page_size;
 
1106
}
 
1107
 
 
1108
static int
 
1109
vsf_sysutil_translate_memprot(const enum EVSFSysUtilMapPermission perm)
 
1110
{
 
1111
  int retval = 0;
 
1112
  switch (perm)
 
1113
  {
 
1114
    case kVSFSysUtilMapProtReadOnly:
 
1115
      retval = PROT_READ;
 
1116
      break;
 
1117
    case kVSFSysUtilMapProtNone:
 
1118
      retval = PROT_NONE;
 
1119
      break;
 
1120
    default:
 
1121
      bug("bad value in vsf_sysutil_translate_memprot");
 
1122
      break;
 
1123
  }
 
1124
  return retval;
 
1125
}
 
1126
 
 
1127
void
 
1128
vsf_sysutil_memprotect(void* p_addr, unsigned int len,
 
1129
                       const enum EVSFSysUtilMapPermission perm)
 
1130
{
 
1131
  int prot = vsf_sysutil_translate_memprot(perm);
 
1132
  int retval = mprotect(p_addr, len, prot);
 
1133
  if (retval != 0)
 
1134
  {
 
1135
    die("mprotect");
 
1136
  }
 
1137
}
 
1138
 
 
1139
void
 
1140
vsf_sysutil_memunmap(void* p_start, unsigned int length)
 
1141
{
 
1142
  int retval = munmap(p_start, length);
 
1143
  if (retval != 0)
 
1144
  {
 
1145
    die("munmap");
 
1146
  }
 
1147
}
 
1148
 
 
1149
static int
 
1150
vsf_sysutil_translate_openmode(const enum EVSFSysUtilOpenMode mode)
 
1151
{
 
1152
  int retval = 0;
 
1153
  switch (mode)
 
1154
  {
 
1155
    case kVSFSysUtilOpenReadOnly:
 
1156
      retval = O_RDONLY;
 
1157
      break;
 
1158
    case kVSFSysUtilOpenWriteOnly:
 
1159
      retval = O_WRONLY;
 
1160
      break;
 
1161
    case kVSFSysUtilOpenReadWrite:
 
1162
      retval = O_RDWR;
 
1163
      break;
 
1164
    default:
 
1165
      bug("bad mode in vsf_sysutil_translate_openmode");
 
1166
      break;
 
1167
  }
 
1168
  return retval;
 
1169
}
 
1170
 
 
1171
int
 
1172
vsf_sysutil_open_file(const char* p_filename,
 
1173
                      const enum EVSFSysUtilOpenMode mode)
 
1174
{
 
1175
  return open(p_filename, vsf_sysutil_translate_openmode(mode) | O_NONBLOCK);
 
1176
}
 
1177
 
 
1178
int
 
1179
vsf_sysutil_create_file_exclusive(const char* p_filename)
 
1180
{
 
1181
  /* umask() also contributes to end mode */
 
1182
  return open(p_filename, O_CREAT | O_EXCL | O_WRONLY | O_APPEND,
 
1183
              tunable_file_open_mode);
 
1184
}
 
1185
 
 
1186
int
 
1187
vsf_sysutil_create_or_open_file(const char* p_filename, unsigned int mode)
 
1188
{
 
1189
  return open(p_filename, O_CREAT | O_WRONLY | O_NONBLOCK, mode);
 
1190
}
 
1191
 
 
1192
int
 
1193
vsf_sysutil_create_or_open_file_append(const char* p_filename,
 
1194
                                       unsigned int mode)
 
1195
{
 
1196
  return open(p_filename, O_CREAT | O_WRONLY | O_NONBLOCK | O_APPEND, mode);
 
1197
}
 
1198
 
 
1199
void
 
1200
vsf_sysutil_dupfd2(int old_fd, int new_fd)
 
1201
{
 
1202
  int retval;
 
1203
  if (old_fd == new_fd)
 
1204
  {
 
1205
    return;
 
1206
  }
 
1207
  retval = dup2(old_fd, new_fd);
 
1208
  if (retval != new_fd)
 
1209
  {
 
1210
    die("dup2");
 
1211
  }
 
1212
}
 
1213
 
 
1214
void
 
1215
vsf_sysutil_close(int fd)
 
1216
{
 
1217
  while (1)
 
1218
  {
 
1219
    int retval = close(fd);
 
1220
    if (retval != 0)
 
1221
    {
 
1222
      if (errno == EINTR)
 
1223
      {
 
1224
        vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0);
 
1225
        continue;
 
1226
      }
 
1227
      die("close");
 
1228
    }
 
1229
    return;
 
1230
  }
 
1231
}
 
1232
 
 
1233
int
 
1234
vsf_sysutil_close_failok(int fd)
 
1235
{
 
1236
  return close(fd);
 
1237
}
 
1238
 
 
1239
int
 
1240
vsf_sysutil_unlink(const char* p_dead)
 
1241
{
 
1242
  return unlink(p_dead);
 
1243
}
 
1244
 
 
1245
int
 
1246
vsf_sysutil_write_access(const char* p_filename)
 
1247
{
 
1248
  int retval = access(p_filename, W_OK);
 
1249
  return (retval == 0);
 
1250
}
 
1251
 
 
1252
static void
 
1253
vsf_sysutil_alloc_statbuf(struct vsf_sysutil_statbuf** p_ptr)
 
1254
{
 
1255
  if (*p_ptr == NULL)
 
1256
  {
 
1257
    *p_ptr = vsf_sysutil_malloc(sizeof(struct stat));
 
1258
  }
 
1259
}
 
1260
 
 
1261
void
 
1262
vsf_sysutil_fstat(int fd, struct vsf_sysutil_statbuf** p_ptr)
 
1263
{
 
1264
  int retval;
 
1265
  vsf_sysutil_alloc_statbuf(p_ptr);
 
1266
  retval = fstat(fd, (struct stat*) (*p_ptr));
 
1267
  if (retval != 0)
 
1268
  {
 
1269
    die("fstat");
 
1270
  }
 
1271
}
 
1272
 
 
1273
int
 
1274
vsf_sysutil_stat(const char* p_name, struct vsf_sysutil_statbuf** p_ptr)
 
1275
{
 
1276
  vsf_sysutil_alloc_statbuf(p_ptr);
 
1277
  return stat(p_name, (struct stat*) (*p_ptr));
 
1278
}
 
1279
 
 
1280
int
 
1281
vsf_sysutil_lstat(const char* p_name, struct vsf_sysutil_statbuf** p_ptr)
 
1282
{
 
1283
  vsf_sysutil_alloc_statbuf(p_ptr);
 
1284
  return lstat(p_name, (struct stat*) (*p_ptr));
 
1285
}
 
1286
 
 
1287
void
 
1288
vsf_sysutil_dir_stat(const struct vsf_sysutil_dir* p_dir,
 
1289
                     struct vsf_sysutil_statbuf** p_ptr)
 
1290
{
 
1291
  int fd = dirfd((DIR*) p_dir);
 
1292
  vsf_sysutil_fstat(fd, p_ptr);
 
1293
}
 
1294
 
 
1295
int
 
1296
vsf_sysutil_statbuf_is_regfile(const struct vsf_sysutil_statbuf* p_stat)
 
1297
{
 
1298
  const struct stat* p_realstat = (const struct stat*) p_stat;
 
1299
  return S_ISREG(p_realstat->st_mode);
 
1300
}
 
1301
 
 
1302
int
 
1303
vsf_sysutil_statbuf_is_symlink(const struct vsf_sysutil_statbuf* p_stat)
 
1304
{
 
1305
  const struct stat* p_realstat = (const struct stat*) p_stat;
 
1306
  return S_ISLNK(p_realstat->st_mode);
 
1307
}
 
1308
 
 
1309
int
 
1310
vsf_sysutil_statbuf_is_socket(const struct vsf_sysutil_statbuf* p_stat)
 
1311
{
 
1312
  const struct stat* p_realstat = (const struct stat*) p_stat;
 
1313
  return S_ISSOCK(p_realstat->st_mode);
 
1314
}
 
1315
 
 
1316
int
 
1317
vsf_sysutil_statbuf_is_dir(const struct vsf_sysutil_statbuf* p_stat)
 
1318
{
 
1319
  const struct stat* p_realstat = (const struct stat*) p_stat;
 
1320
  return S_ISDIR(p_realstat->st_mode);
 
1321
}
 
1322
 
 
1323
const char*
 
1324
vsf_sysutil_statbuf_get_perms(const struct vsf_sysutil_statbuf* p_statbuf)
 
1325
{
 
1326
  static char perms[11];
 
1327
  int i;
 
1328
  const struct stat* p_stat = (const struct stat*) p_statbuf;
 
1329
  for (i=0; i<10; i++)
 
1330
  {
 
1331
    perms[i] = '-';
 
1332
  }
 
1333
  perms[0] = '?';
 
1334
  switch (p_stat->st_mode & S_IFMT)
 
1335
  {
 
1336
    case S_IFREG: perms[0] = '-'; break;
 
1337
    case S_IFDIR: perms[0] = 'd'; break;
 
1338
    case S_IFLNK: perms[0] = 'l'; break;
 
1339
    case S_IFIFO: perms[0] = 'p'; break;
 
1340
    case S_IFSOCK: perms[0] = 's'; break;
 
1341
    case S_IFCHR: perms[0] = 'c'; break;
 
1342
    case S_IFBLK: perms[0] = 'b'; break;
 
1343
    default: break;
 
1344
  }
 
1345
  if (p_stat->st_mode & S_IRUSR) perms[1] = 'r';
 
1346
  if (p_stat->st_mode & S_IWUSR) perms[2] = 'w';
 
1347
  if (p_stat->st_mode & S_IXUSR) perms[3] = 'x';
 
1348
  if (p_stat->st_mode & S_IRGRP) perms[4] = 'r';
 
1349
  if (p_stat->st_mode & S_IWGRP) perms[5] = 'w';
 
1350
  if (p_stat->st_mode & S_IXGRP) perms[6] = 'x';
 
1351
  if (p_stat->st_mode & S_IROTH) perms[7] = 'r';
 
1352
  if (p_stat->st_mode & S_IWOTH) perms[8] = 'w';
 
1353
  if (p_stat->st_mode & S_IXOTH) perms[9] = 'x';
 
1354
  if (p_stat->st_mode & S_ISUID) perms[3] = (perms[3] == 'x') ? 's' : 'S';
 
1355
  if (p_stat->st_mode & S_ISGID) perms[6] = (perms[6] == 'x') ? 's' : 'S';
 
1356
  if (p_stat->st_mode & S_ISVTX) perms[9] = (perms[9] == 'x') ? 't' : 'T';
 
1357
  perms[10] = '\0';
 
1358
  return perms;
 
1359
}
 
1360
 
 
1361
const char*
 
1362
vsf_sysutil_statbuf_get_date(const struct vsf_sysutil_statbuf* p_statbuf,
 
1363
                             int use_localtime, long curr_time)
 
1364
{
 
1365
  static char datebuf[64];
 
1366
  int retval;
 
1367
  struct tm* p_tm;
 
1368
  const struct stat* p_stat = (const struct stat*) p_statbuf;
 
1369
  const char* p_date_format = "%b %d %H:%M";
 
1370
  if (!use_localtime)
 
1371
  {
 
1372
    p_tm = gmtime(&p_stat->st_mtime);
 
1373
  }
 
1374
  else
 
1375
  {
 
1376
    p_tm = localtime(&p_stat->st_mtime);
 
1377
  }
 
1378
  /* Is this a future or 6 months old date? If so, we drop to year format */
 
1379
  if (p_stat->st_mtime > curr_time ||
 
1380
      (curr_time - p_stat->st_mtime) > 60*60*24*182)
 
1381
  {
 
1382
    p_date_format = "%b %d  %Y";
 
1383
  }
 
1384
  retval = strftime(datebuf, sizeof(datebuf), p_date_format, p_tm);
 
1385
  datebuf[sizeof(datebuf)-1] = '\0';
 
1386
  if (retval == 0)
 
1387
  {
 
1388
    die("strftime");
 
1389
  }
 
1390
  return datebuf;
 
1391
}
 
1392
 
 
1393
const char*
 
1394
vsf_sysutil_statbuf_get_numeric_date(
 
1395
  const struct vsf_sysutil_statbuf* p_statbuf,
 
1396
  int use_localtime)
 
1397
{
 
1398
  static char datebuf[15];
 
1399
  const struct stat* p_stat = (const struct stat*) p_statbuf;
 
1400
  struct tm* p_tm;
 
1401
  int retval;
 
1402
  if (!use_localtime)
 
1403
  {
 
1404
    p_tm = gmtime(&p_stat->st_mtime);
 
1405
  }
 
1406
  else
 
1407
  {
 
1408
    p_tm = localtime(&p_stat->st_mtime);
 
1409
  }
 
1410
  retval = strftime(datebuf, sizeof(datebuf), "%Y%m%d%H%M%S", p_tm);
 
1411
  if (retval == 0)
 
1412
  {
 
1413
    die("strftime");
 
1414
  }
 
1415
  return datebuf;
 
1416
}
 
1417
 
 
1418
filesize_t
 
1419
vsf_sysutil_statbuf_get_size(const struct vsf_sysutil_statbuf* p_statbuf)
 
1420
{
 
1421
  const struct stat* p_stat = (const struct stat*) p_statbuf;
 
1422
  if (p_stat->st_size < 0)
 
1423
  {
 
1424
    die("invalid inode size in vsf_sysutil_statbuf_get_size");
 
1425
  }
 
1426
  return p_stat->st_size;
 
1427
}
 
1428
 
 
1429
int
 
1430
vsf_sysutil_statbuf_get_uid(const struct vsf_sysutil_statbuf* p_statbuf)
 
1431
{
 
1432
  const struct stat* p_stat = (const struct stat*) p_statbuf;
 
1433
  return p_stat->st_uid;
 
1434
}
 
1435
 
 
1436
int
 
1437
vsf_sysutil_statbuf_get_gid(const struct vsf_sysutil_statbuf* p_statbuf)
 
1438
{
 
1439
  const struct stat* p_stat = (const struct stat*) p_statbuf;
 
1440
  return p_stat->st_gid;
 
1441
}
 
1442
 
 
1443
unsigned int
 
1444
vsf_sysutil_statbuf_get_links(const struct vsf_sysutil_statbuf* p_statbuf)
 
1445
{
 
1446
  const struct stat* p_stat = (const struct stat*) p_statbuf;
 
1447
  return p_stat->st_nlink;
 
1448
}
 
1449
 
 
1450
int
 
1451
vsf_sysutil_statbuf_is_readable_other(
 
1452
  const struct vsf_sysutil_statbuf* p_statbuf)
 
1453
{
 
1454
  const struct stat* p_stat = (const struct stat*) p_statbuf;
 
1455
  if (p_stat->st_mode & S_IROTH)
 
1456
  {
 
1457
    return 1;
 
1458
  }
 
1459
  return 0;
 
1460
}
 
1461
 
 
1462
const char*
 
1463
vsf_sysutil_statbuf_get_sortkey_mtime(
 
1464
  const struct vsf_sysutil_statbuf* p_statbuf)
 
1465
{
 
1466
  static char intbuf[32];
 
1467
  const struct stat* p_stat = (const struct stat*) p_statbuf;
 
1468
  /* This slight hack function must return a character date format such that
 
1469
   * more recent dates appear later in the alphabet! Most notably, we must
 
1470
   * make sure we pad to the same length with 0's 
 
1471
   */
 
1472
  snprintf(intbuf, sizeof(intbuf), "%030ld", (long) p_stat->st_mtime);
 
1473
  return intbuf;
 
1474
}
 
1475
 
 
1476
void
 
1477
vsf_sysutil_fchown(const int fd, const int uid, const int gid)
 
1478
{
 
1479
  if (fchown(fd, uid, gid) != 0)
 
1480
  {
 
1481
    die("fchown");
 
1482
  }
 
1483
}
 
1484
 
 
1485
void
 
1486
vsf_sysutil_fchmod(const int fd, unsigned int mode)
 
1487
{
 
1488
  mode = mode & 0777;
 
1489
  if (fchmod(fd, mode))
 
1490
  {
 
1491
    die("fchmod");
 
1492
  }
 
1493
}
 
1494
 
 
1495
int
 
1496
vsf_sysutil_chmod(const char* p_filename, unsigned int mode)
 
1497
{
 
1498
  /* Safety: mask "mode" to just access permissions, e.g. no suid setting! */
 
1499
  mode = mode & 0777;
 
1500
  return chmod(p_filename, mode);
 
1501
}
 
1502
 
 
1503
int
 
1504
vsf_sysutil_lock_file_write(int fd)
 
1505
{
 
1506
  return lock_internal(fd, F_WRLCK);
 
1507
}
 
1508
 
 
1509
int
 
1510
vsf_sysutil_lock_file_read(int fd)
 
1511
{
 
1512
  return lock_internal(fd, F_RDLCK);
 
1513
}
 
1514
 
 
1515
static int
 
1516
lock_internal(int fd, int lock_type)
 
1517
{
 
1518
  struct flock the_lock;
 
1519
  int retval;
 
1520
  int saved_errno;
 
1521
  vsf_sysutil_memclr(&the_lock, sizeof(the_lock));
 
1522
  the_lock.l_type = lock_type;
 
1523
  the_lock.l_whence = SEEK_SET;
 
1524
  the_lock.l_start = 0;
 
1525
  the_lock.l_len = 0;
 
1526
  do
 
1527
  {
 
1528
    retval = fcntl(fd, F_SETLKW, &the_lock);
 
1529
    saved_errno = errno;
 
1530
    vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0);
 
1531
  }
 
1532
  while (retval < 0 && saved_errno == EINTR);
 
1533
  return retval;
 
1534
}
 
1535
 
 
1536
void
 
1537
vsf_sysutil_unlock_file(int fd)
 
1538
{
 
1539
  int retval;
 
1540
  struct flock the_lock;
 
1541
  vsf_sysutil_memclr(&the_lock, sizeof(the_lock));
 
1542
  the_lock.l_type = F_UNLCK;
 
1543
  the_lock.l_whence = SEEK_SET;
 
1544
  the_lock.l_start = 0;
 
1545
  the_lock.l_len = 0;
 
1546
  retval = fcntl(fd, F_SETLK, &the_lock);
 
1547
  if (retval != 0)
 
1548
  {
 
1549
    die("fcntl");
 
1550
  }
 
1551
}
 
1552
 
 
1553
int
 
1554
vsf_sysutil_readlink(const char* p_filename, char* p_dest, unsigned int bufsiz)
 
1555
{
 
1556
  int retval;
 
1557
  if (bufsiz == 0) {
 
1558
    return -1;
 
1559
  }
 
1560
  retval = readlink(p_filename, p_dest, bufsiz - 1);
 
1561
  if (retval < 0)
 
1562
  {
 
1563
    return retval;
 
1564
  }
 
1565
  /* Ensure buffer is NULL terminated; readlink(2) doesn't do that */
 
1566
  p_dest[retval] = '\0';
 
1567
  return retval;
 
1568
}
 
1569
 
 
1570
int
 
1571
vsf_sysutil_retval_is_error(int retval)
 
1572
{
 
1573
  if (retval < 0)
 
1574
  {
 
1575
    return 1;
 
1576
  }
 
1577
  return 0;
 
1578
}
 
1579
 
 
1580
enum EVSFSysUtilError
 
1581
vsf_sysutil_get_error(void)
 
1582
{
 
1583
  enum EVSFSysUtilError retval = kVSFSysUtilErrUnknown;
 
1584
  switch (errno)
 
1585
  {
 
1586
    case EADDRINUSE:
 
1587
      retval = kVSFSysUtilErrADDRINUSE;
 
1588
      break;
 
1589
    case ENOSYS:
 
1590
      retval = kVSFSysUtilErrNOSYS;
 
1591
      break;
 
1592
    case EINTR:
 
1593
      retval = kVSFSysUtilErrINTR;
 
1594
      break;
 
1595
    case EINVAL:
 
1596
      retval = kVSFSysUtilErrINVAL;
 
1597
      break;
 
1598
    case EOPNOTSUPP:
 
1599
      retval = kVSFSysUtilErrOPNOTSUPP;
 
1600
      break;
 
1601
    case EACCES:
 
1602
      retval = kVSFSysUtilErrACCES;
 
1603
      break;
 
1604
    case ENOENT:
 
1605
      retval = kVSFSysUtilErrNOENT;
 
1606
      break;
 
1607
    default:
 
1608
      break;
 
1609
  }
 
1610
  return retval;
 
1611
}
 
1612
 
 
1613
int
 
1614
vsf_sysutil_get_ipv4_sock(void)
 
1615
{
 
1616
  int retval = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
 
1617
  if (retval < 0)
 
1618
  {
 
1619
    die("socket");
 
1620
  }
 
1621
  return retval;
 
1622
}
 
1623
 
 
1624
int
 
1625
vsf_sysutil_get_ipv6_sock(void)
 
1626
{
 
1627
  int retval = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
 
1628
  if (retval < 0)
 
1629
  {
 
1630
    die("socket");
 
1631
  }
 
1632
  return retval;
 
1633
}
 
1634
 
 
1635
struct vsf_sysutil_socketpair_retval
 
1636
vsf_sysutil_unix_stream_socketpair(void)
 
1637
{
 
1638
  struct vsf_sysutil_socketpair_retval retval;
 
1639
  int the_sockets[2];
 
1640
  int sys_retval = socketpair(PF_UNIX, SOCK_STREAM, 0, the_sockets);
 
1641
  if (sys_retval != 0)
 
1642
  {
 
1643
    die("socketpair");
 
1644
  }
 
1645
  retval.socket_one = the_sockets[0];
 
1646
  retval.socket_two = the_sockets[1];
 
1647
  return retval;
 
1648
}
 
1649
 
 
1650
int
 
1651
vsf_sysutil_bind(int fd, const struct vsf_sysutil_sockaddr* p_sockptr)
 
1652
{
 
1653
  const struct sockaddr* p_sockaddr = &p_sockptr->u.u_sockaddr;
 
1654
  int len = 0;
 
1655
  if (p_sockaddr->sa_family == AF_INET)
 
1656
  {
 
1657
    len = sizeof(struct sockaddr_in);
 
1658
  }
 
1659
  else if (p_sockaddr->sa_family == AF_INET6)
 
1660
  {
 
1661
    len = sizeof(struct sockaddr_in6);
 
1662
  }
 
1663
  else
 
1664
  {
 
1665
    die("can only support ipv4 and ipv6 currently");
 
1666
  }
 
1667
  return bind(fd, p_sockaddr, len);
 
1668
}
 
1669
 
 
1670
int
 
1671
vsf_sysutil_listen(int fd, const unsigned int backlog)
 
1672
{
 
1673
  int retval = listen(fd, backlog);
 
1674
  if (vsf_sysutil_retval_is_error(retval) &&
 
1675
      vsf_sysutil_get_error() != kVSFSysUtilErrADDRINUSE)
 
1676
  {
 
1677
    die("listen");
 
1678
  }
 
1679
  return retval;
 
1680
}
 
1681
 
 
1682
/* Warning: callers of this function assume it does NOT make use of any
 
1683
 * non re-entrant calls such as malloc().
 
1684
 */
 
1685
int
 
1686
vsf_sysutil_accept_timeout(int fd, struct vsf_sysutil_sockaddr* p_sockaddr,
 
1687
                           unsigned int wait_seconds)
 
1688
{
 
1689
  struct vsf_sysutil_sockaddr remote_addr;
 
1690
  int retval;
 
1691
  int saved_errno;
 
1692
  fd_set accept_fdset;
 
1693
  struct timeval timeout;
 
1694
  socklen_t socklen = sizeof(remote_addr);
 
1695
  if (p_sockaddr)
 
1696
  {
 
1697
    vsf_sysutil_memclr(p_sockaddr, sizeof(*p_sockaddr));
 
1698
  }
 
1699
  if (wait_seconds > 0)
 
1700
  {
 
1701
    FD_ZERO(&accept_fdset);
 
1702
    FD_SET(fd, &accept_fdset);
 
1703
    timeout.tv_sec = wait_seconds;
 
1704
    timeout.tv_usec = 0;
 
1705
    do
 
1706
    {
 
1707
      retval = select(fd + 1, &accept_fdset, NULL, NULL, &timeout);
 
1708
      saved_errno = errno;
 
1709
      vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0);
 
1710
    }
 
1711
    while (retval < 0 && saved_errno == EINTR);
 
1712
    if (retval <= 0)
 
1713
    {
 
1714
      if (retval == 0)
 
1715
      {
 
1716
        errno = EAGAIN;
 
1717
      }
 
1718
      return -1;
 
1719
    }
 
1720
  }
 
1721
  retval = accept(fd, &remote_addr.u.u_sockaddr, &socklen);
 
1722
  vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0);
 
1723
  if (retval < 0)
 
1724
  {
 
1725
    return retval;
 
1726
  }
 
1727
  /* FreeBSD bug / paranoia: ai32@drexel.edu */
 
1728
  if (socklen == 0)
 
1729
  {
 
1730
    return -1;
 
1731
  }
 
1732
  if (remote_addr.u.u_sockaddr.sa_family != AF_INET &&
 
1733
      remote_addr.u.u_sockaddr.sa_family != AF_INET6)
 
1734
  {
 
1735
    die("can only support ipv4 and ipv6 currently");
 
1736
  }
 
1737
  if (p_sockaddr)
 
1738
  {
 
1739
    if (remote_addr.u.u_sockaddr.sa_family == AF_INET)
 
1740
    {
 
1741
      vsf_sysutil_memclr(&remote_addr.u.u_sockaddr_in.sin_zero,
 
1742
                         sizeof(remote_addr.u.u_sockaddr_in.sin_zero));
 
1743
      vsf_sysutil_memcpy(p_sockaddr, &remote_addr.u.u_sockaddr_in,
 
1744
                         sizeof(remote_addr.u.u_sockaddr_in));
 
1745
    }
 
1746
    else
 
1747
    {
 
1748
      vsf_sysutil_memcpy(p_sockaddr, &remote_addr.u.u_sockaddr_in6,
 
1749
                         sizeof(remote_addr.u.u_sockaddr_in6));
 
1750
    }
 
1751
  }
 
1752
  return retval;
 
1753
}
 
1754
 
 
1755
int
 
1756
vsf_sysutil_connect_timeout(int fd, const struct vsf_sysutil_sockaddr* p_addr,
 
1757
                            unsigned int wait_seconds)
 
1758
{
 
1759
  const struct sockaddr* p_sockaddr = &p_addr->u.u_sockaddr;
 
1760
  unsigned int addrlen = 0;
 
1761
  int retval;
 
1762
  int saved_errno;
 
1763
  if (p_sockaddr->sa_family == AF_INET)
 
1764
  {
 
1765
    addrlen = sizeof(p_addr->u.u_sockaddr_in);
 
1766
  }
 
1767
  else if (p_sockaddr->sa_family == AF_INET6)
 
1768
  {
 
1769
    addrlen = sizeof(p_addr->u.u_sockaddr_in6);
 
1770
  }
 
1771
  else
 
1772
  {
 
1773
    die("can only support ipv4 and ipv6 currently");
 
1774
  }
 
1775
  if (wait_seconds > 0)
 
1776
  {
 
1777
    vsf_sysutil_activate_noblock(fd);
 
1778
  }
 
1779
  retval = connect(fd, p_sockaddr, addrlen);
 
1780
  if (retval < 0 && errno == EINPROGRESS)
 
1781
  {
 
1782
    fd_set connect_fdset;
 
1783
    struct timeval timeout;
 
1784
    FD_ZERO(&connect_fdset);
 
1785
    FD_SET(fd, &connect_fdset);
 
1786
    timeout.tv_sec = wait_seconds;
 
1787
    timeout.tv_usec = 0;
 
1788
    do
 
1789
    {
 
1790
      retval = select(fd + 1, NULL, &connect_fdset, NULL, &timeout);
 
1791
      saved_errno = errno;
 
1792
      vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0);
 
1793
    }
 
1794
    while (retval < 0 && saved_errno == EINTR);
 
1795
    if (retval <= 0)
 
1796
    {
 
1797
      if (retval == 0)
 
1798
      {
 
1799
        errno = EAGAIN;
 
1800
      }
 
1801
      retval = -1;
 
1802
    }
 
1803
    else
 
1804
    {
 
1805
      socklen_t socklen = sizeof(retval);
 
1806
      int sockoptret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &retval, &socklen);
 
1807
      if (sockoptret != 0)
 
1808
      {
 
1809
        die("getsockopt");
 
1810
      }
 
1811
      if (retval != 0)
 
1812
      {
 
1813
        errno = retval;
 
1814
        retval = -1;
 
1815
      }
 
1816
    }
 
1817
  }
 
1818
  if (wait_seconds > 0)
 
1819
  {
 
1820
    vsf_sysutil_deactivate_noblock(fd);
 
1821
  }
 
1822
  return retval;
 
1823
}
 
1824
 
 
1825
void
 
1826
vsf_sysutil_getsockname(int fd, struct vsf_sysutil_sockaddr** p_sockptr)
 
1827
{
 
1828
  struct vsf_sysutil_sockaddr the_addr;
 
1829
  int retval;
 
1830
  socklen_t socklen = sizeof(the_addr);
 
1831
  vsf_sysutil_sockaddr_clear(p_sockptr);
 
1832
  retval = getsockname(fd, &the_addr.u.u_sockaddr, &socklen);
 
1833
  if (retval != 0)
 
1834
  {
 
1835
    die("getsockname");
 
1836
  }
 
1837
  if (the_addr.u.u_sockaddr.sa_family != AF_INET &&
 
1838
      the_addr.u.u_sockaddr.sa_family != AF_INET6)
 
1839
  {
 
1840
    die("can only support ipv4 and ipv6 currently");
 
1841
  }
 
1842
  vsf_sysutil_sockaddr_alloc(p_sockptr);
 
1843
  if (socklen > sizeof(the_addr))
 
1844
  {
 
1845
    socklen = sizeof(the_addr);
 
1846
  }
 
1847
  vsf_sysutil_memcpy(*p_sockptr, &the_addr, socklen);
 
1848
}
 
1849
 
 
1850
void
 
1851
vsf_sysutil_getpeername(int fd, struct vsf_sysutil_sockaddr** p_sockptr)
 
1852
{
 
1853
  struct vsf_sysutil_sockaddr the_addr;
 
1854
  int retval;
 
1855
  socklen_t socklen = sizeof(the_addr);
 
1856
  vsf_sysutil_sockaddr_clear(p_sockptr);
 
1857
  retval = getpeername(fd, &the_addr.u.u_sockaddr, &socklen);
 
1858
  if (retval != 0)
 
1859
  {
 
1860
    die("getpeername");
 
1861
  }
 
1862
  if (the_addr.u.u_sockaddr.sa_family != AF_INET &&
 
1863
      the_addr.u.u_sockaddr.sa_family != AF_INET6)
 
1864
  {
 
1865
    die("can only support ipv4 and ipv6 currently");
 
1866
  }
 
1867
  vsf_sysutil_sockaddr_alloc(p_sockptr);
 
1868
  if (socklen > sizeof(the_addr))
 
1869
  {
 
1870
    socklen = sizeof(the_addr);
 
1871
  }
 
1872
  vsf_sysutil_memcpy(*p_sockptr, &the_addr, socklen);
 
1873
}
 
1874
 
 
1875
void
 
1876
vsf_sysutil_shutdown_failok(int fd)
 
1877
{
 
1878
  /* SHUT_RDWR is a relatively new addition */
 
1879
  #ifndef SHUT_RDWR
 
1880
  #define SHUT_RDWR 2
 
1881
  #endif
 
1882
  (void) shutdown(fd, SHUT_RDWR);
 
1883
}
 
1884
 
 
1885
void
 
1886
vsf_sysutil_shutdown_read_failok(int fd)
 
1887
{
 
1888
  /* SHUT_RD is a relatively new addition */
 
1889
  #ifndef SHUT_RD
 
1890
  #define SHUT_RD 0
 
1891
  #endif
 
1892
  (void) shutdown(fd, SHUT_RD);
 
1893
}
 
1894
 
 
1895
void
 
1896
vsf_sysutil_sockaddr_clear(struct vsf_sysutil_sockaddr** p_sockptr)
 
1897
{
 
1898
  if (*p_sockptr != NULL)
 
1899
  {
 
1900
    vsf_sysutil_free(*p_sockptr);
 
1901
    *p_sockptr = NULL;
 
1902
  }
 
1903
}
 
1904
 
 
1905
void
 
1906
vsf_sysutil_sockaddr_alloc(struct vsf_sysutil_sockaddr** p_sockptr)
 
1907
{
 
1908
  vsf_sysutil_sockaddr_clear(p_sockptr);
 
1909
  *p_sockptr = vsf_sysutil_malloc(sizeof(**p_sockptr));
 
1910
  vsf_sysutil_memclr(*p_sockptr, sizeof(**p_sockptr));
 
1911
}
 
1912
 
 
1913
void
 
1914
vsf_sysutil_sockaddr_alloc_ipv4(struct vsf_sysutil_sockaddr** p_sockptr)
 
1915
{
 
1916
  vsf_sysutil_sockaddr_alloc(p_sockptr);
 
1917
  (*p_sockptr)->u.u_sockaddr.sa_family = AF_INET;
 
1918
}
 
1919
 
 
1920
void
 
1921
vsf_sysutil_sockaddr_alloc_ipv6(struct vsf_sysutil_sockaddr** p_sockptr)
 
1922
{
 
1923
  vsf_sysutil_sockaddr_alloc(p_sockptr);
 
1924
  (*p_sockptr)->u.u_sockaddr.sa_family = AF_INET6;
 
1925
}
 
1926
 
 
1927
void
 
1928
vsf_sysutil_sockaddr_clone(struct vsf_sysutil_sockaddr** p_sockptr,
 
1929
                           const struct vsf_sysutil_sockaddr* p_src)
 
1930
{
 
1931
  struct vsf_sysutil_sockaddr* p_sockaddr = 0;
 
1932
  vsf_sysutil_sockaddr_alloc(p_sockptr);
 
1933
  p_sockaddr = *p_sockptr;
 
1934
  if (p_src->u.u_sockaddr.sa_family == AF_INET)
 
1935
  {
 
1936
    p_sockaddr->u.u_sockaddr.sa_family = AF_INET;
 
1937
    vsf_sysutil_memcpy(&p_sockaddr->u.u_sockaddr_in.sin_addr,
 
1938
                       &p_src->u.u_sockaddr_in.sin_addr,
 
1939
                       sizeof(p_sockaddr->u.u_sockaddr_in.sin_addr));
 
1940
  }
 
1941
  else if (p_src->u.u_sockaddr.sa_family == AF_INET6)
 
1942
  {
 
1943
    p_sockaddr->u.u_sockaddr.sa_family = AF_INET6;
 
1944
    vsf_sysutil_memcpy(&p_sockaddr->u.u_sockaddr_in6.sin6_addr,
 
1945
                       &p_src->u.u_sockaddr_in6.sin6_addr,
 
1946
                       sizeof(p_sockaddr->u.u_sockaddr_in6.sin6_addr));
 
1947
    p_sockaddr->u.u_sockaddr_in6.sin6_scope_id =
 
1948
        p_src->u.u_sockaddr_in6.sin6_scope_id;
 
1949
  }
 
1950
  else
 
1951
  {
 
1952
    die("can only support ipv4 and ipv6 currently");
 
1953
  }
 
1954
}
 
1955
 
 
1956
int
 
1957
vsf_sysutil_sockaddr_addr_equal(const struct vsf_sysutil_sockaddr* p1,
 
1958
                                const struct vsf_sysutil_sockaddr* p2)
 
1959
{
 
1960
  int family1 = p1->u.u_sockaddr.sa_family;
 
1961
  int family2 = p2->u.u_sockaddr.sa_family;
 
1962
  if (family1 != family2)
 
1963
  {
 
1964
    if (family1 == AF_INET && family2 == AF_INET6)
 
1965
    {
 
1966
      const void* p_ipv4_addr = vsf_sysutil_sockaddr_ipv6_v4(p2);
 
1967
      if (p_ipv4_addr &&
 
1968
          !vsf_sysutil_memcmp(p_ipv4_addr, &p1->u.u_sockaddr_in.sin_addr,
 
1969
                              sizeof(p1->u.u_sockaddr_in.sin_addr)))
 
1970
      {
 
1971
        return 1;
 
1972
      }
 
1973
    }
 
1974
    else if (family1 == AF_INET6 && family2 == AF_INET)
 
1975
    {
 
1976
      const void* p_ipv4_addr = vsf_sysutil_sockaddr_ipv6_v4(p1);
 
1977
      if (p_ipv4_addr &&
 
1978
          !vsf_sysutil_memcmp(p_ipv4_addr, &p2->u.u_sockaddr_in.sin_addr,
 
1979
                              sizeof(p2->u.u_sockaddr_in.sin_addr)))
 
1980
      {
 
1981
        return 1;
 
1982
      }
 
1983
    }
 
1984
    return 0;
 
1985
  }
 
1986
  if (family1 == AF_INET)
 
1987
  {
 
1988
    if (vsf_sysutil_memcmp(&p1->u.u_sockaddr_in.sin_addr,
 
1989
                           &p2->u.u_sockaddr_in.sin_addr,
 
1990
                           sizeof(p1->u.u_sockaddr_in.sin_addr)) == 0)
 
1991
    {
 
1992
      return 1;
 
1993
    }
 
1994
  }
 
1995
  else if (family1 == AF_INET6)
 
1996
  {
 
1997
    if (vsf_sysutil_memcmp(&p1->u.u_sockaddr_in6.sin6_addr,
 
1998
                           &p2->u.u_sockaddr_in6.sin6_addr,
 
1999
                           sizeof(p1->u.u_sockaddr_in6.sin6_addr)) == 0)
 
2000
    {
 
2001
      return 1;
 
2002
    }
 
2003
  }
 
2004
  return 0;
 
2005
}
 
2006
 
 
2007
int
 
2008
vsf_sysutil_sockaddr_is_ipv6(const struct vsf_sysutil_sockaddr* p_sockaddr)
 
2009
{
 
2010
  if (p_sockaddr->u.u_sockaddr.sa_family == AF_INET6)
 
2011
  {
 
2012
    return 1;
 
2013
  }
 
2014
  return 0;
 
2015
}
 
2016
 
 
2017
void
 
2018
vsf_sysutil_sockaddr_set_ipv4addr(struct vsf_sysutil_sockaddr* p_sockptr,
 
2019
                                  const unsigned char* p_raw)
 
2020
{
 
2021
  if (p_sockptr->u.u_sockaddr.sa_family == AF_INET)
 
2022
  {
 
2023
    vsf_sysutil_memcpy(&p_sockptr->u.u_sockaddr_in.sin_addr, p_raw,
 
2024
                       sizeof(p_sockptr->u.u_sockaddr_in.sin_addr));
 
2025
  }
 
2026
  else if (p_sockptr->u.u_sockaddr.sa_family == AF_INET6)
 
2027
  {
 
2028
    static struct vsf_sysutil_sockaddr* s_p_sockaddr;
 
2029
    vsf_sysutil_sockaddr_alloc_ipv4(&s_p_sockaddr);
 
2030
    vsf_sysutil_memcpy(&s_p_sockaddr->u.u_sockaddr_in.sin_addr, p_raw,
 
2031
                       sizeof(s_p_sockaddr->u.u_sockaddr_in.sin_addr));
 
2032
    vsf_sysutil_memcpy(&p_sockptr->u.u_sockaddr_in6.sin6_addr,
 
2033
                       vsf_sysutil_sockaddr_ipv4_v6(s_p_sockaddr),
 
2034
                       sizeof(p_sockptr->u.u_sockaddr_in6.sin6_addr));
 
2035
  }
 
2036
  else
 
2037
  {
 
2038
    bug("bad family");
 
2039
  }
 
2040
}
 
2041
 
 
2042
void
 
2043
vsf_sysutil_sockaddr_set_ipv6addr(struct vsf_sysutil_sockaddr* p_sockptr,
 
2044
                                  const unsigned char* p_raw)
 
2045
{
 
2046
  if (p_sockptr->u.u_sockaddr.sa_family == AF_INET6)
 
2047
  {
 
2048
    vsf_sysutil_memcpy(&p_sockptr->u.u_sockaddr_in6.sin6_addr, p_raw,
 
2049
                       sizeof(p_sockptr->u.u_sockaddr_in6.sin6_addr));
 
2050
  }
 
2051
  else
 
2052
  {
 
2053
    bug("bad family");
 
2054
  }
 
2055
}
 
2056
 
 
2057
const void*
 
2058
vsf_sysutil_sockaddr_ipv6_v4(const struct vsf_sysutil_sockaddr* p_addr)
 
2059
{
 
2060
  static unsigned char pattern[12] =
 
2061
      { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF };
 
2062
  const unsigned char* p_addr_start;
 
2063
  if (p_addr->u.u_sockaddr.sa_family != AF_INET6)
 
2064
  {
 
2065
    return 0;
 
2066
  }
 
2067
  if (vsf_sysutil_memcmp(pattern, &p_addr->u.u_sockaddr_in6.sin6_addr, 12))
 
2068
  {
 
2069
    return 0;
 
2070
  }
 
2071
  p_addr_start = (const unsigned char*)&p_addr->u.u_sockaddr_in6.sin6_addr;
 
2072
  return &p_addr_start[12];
 
2073
}
 
2074
 
 
2075
const void*
 
2076
vsf_sysutil_sockaddr_ipv4_v6(const struct vsf_sysutil_sockaddr* p_addr)
 
2077
{
 
2078
  static unsigned char ret[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF };
 
2079
  if (p_addr->u.u_sockaddr.sa_family != AF_INET)
 
2080
  {
 
2081
    return 0;
 
2082
  }
 
2083
  vsf_sysutil_memcpy(&ret[12], &p_addr->u.u_sockaddr_in.sin_addr, 4);
 
2084
  return ret;
 
2085
}
 
2086
 
 
2087
void*
 
2088
vsf_sysutil_sockaddr_get_raw_addr(struct vsf_sysutil_sockaddr* p_sockptr)
 
2089
{
 
2090
  if (p_sockptr->u.u_sockaddr.sa_family == AF_INET)
 
2091
  {
 
2092
    return &p_sockptr->u.u_sockaddr_in.sin_addr;
 
2093
  }
 
2094
  else if (p_sockptr->u.u_sockaddr.sa_family == AF_INET6)
 
2095
  {
 
2096
    return &p_sockptr->u.u_sockaddr_in6.sin6_addr;
 
2097
  }
 
2098
  else
 
2099
  {
 
2100
    bug("bad family");
 
2101
  }
 
2102
  return 0;
 
2103
}
 
2104
 
 
2105
unsigned int
 
2106
vsf_sysutil_get_ipaddr_size(void)
 
2107
{
 
2108
  struct vsf_sysutil_sockaddr addr;
 
2109
  unsigned int size = sizeof(addr.u.u_sockaddr_in.sin_addr);
 
2110
  unsigned int size2 = sizeof(addr.u.u_sockaddr_in6.sin6_addr);
 
2111
  if (size2 > size)
 
2112
  {
 
2113
    size = size2;
 
2114
  }
 
2115
  return size;
 
2116
}
 
2117
 
 
2118
int
 
2119
vsf_sysutil_get_ipsock(const struct vsf_sysutil_sockaddr* p_addr)
 
2120
{
 
2121
  if (p_addr->u.u_sockaddr.sa_family == AF_INET)
 
2122
  {
 
2123
    return vsf_sysutil_get_ipv4_sock();
 
2124
  }
 
2125
  else if (p_addr->u.u_sockaddr.sa_family == AF_INET6)
 
2126
  {
 
2127
    return vsf_sysutil_get_ipv6_sock();
 
2128
  }
 
2129
  else
 
2130
  {
 
2131
    bug("bad family");
 
2132
  }
 
2133
  return -1;
 
2134
}
 
2135
 
 
2136
void
 
2137
vsf_sysutil_sockaddr_set_any(struct vsf_sysutil_sockaddr* p_sockaddr)
 
2138
{
 
2139
  if (p_sockaddr->u.u_sockaddr.sa_family == AF_INET)
 
2140
  {
 
2141
    vsf_sysutil_memclr(&p_sockaddr->u.u_sockaddr_in.sin_addr,
 
2142
                       sizeof(p_sockaddr->u.u_sockaddr_in.sin_addr));
 
2143
  }
 
2144
  else if (p_sockaddr->u.u_sockaddr.sa_family == AF_INET6)
 
2145
  {
 
2146
    vsf_sysutil_memclr(&p_sockaddr->u.u_sockaddr_in6.sin6_addr,
 
2147
                       sizeof(p_sockaddr->u.u_sockaddr_in6.sin6_addr));
 
2148
  }
 
2149
  else
 
2150
  {
 
2151
    bug("bad family");
 
2152
  }
 
2153
}
 
2154
 
 
2155
unsigned short
 
2156
vsf_sysutil_sockaddr_get_port(const struct vsf_sysutil_sockaddr* p_sockptr)
 
2157
{
 
2158
  if (p_sockptr->u.u_sockaddr.sa_family == AF_INET)
 
2159
  {
 
2160
    return ntohs(p_sockptr->u.u_sockaddr_in.sin_port);
 
2161
  }
 
2162
  else if (p_sockptr->u.u_sockaddr.sa_family == AF_INET6)
 
2163
  {
 
2164
    return ntohs(p_sockptr->u.u_sockaddr_in6.sin6_port);
 
2165
  }
 
2166
  else
 
2167
  {
 
2168
    bug("bad family");
 
2169
  }
 
2170
  /* NOTREACHED */
 
2171
  return 0;
 
2172
}
 
2173
 
 
2174
void
 
2175
vsf_sysutil_sockaddr_set_port(struct vsf_sysutil_sockaddr* p_sockptr,
 
2176
                              unsigned short the_port)
 
2177
{
 
2178
  if (p_sockptr->u.u_sockaddr.sa_family == AF_INET)
 
2179
  {
 
2180
    p_sockptr->u.u_sockaddr_in.sin_port = htons(the_port);
 
2181
  }
 
2182
  else if (p_sockptr->u.u_sockaddr.sa_family == AF_INET6)
 
2183
  {
 
2184
    p_sockptr->u.u_sockaddr_in6.sin6_port = htons(the_port);
 
2185
  }
 
2186
  else
 
2187
  {
 
2188
    bug("bad family");
 
2189
  }
 
2190
}
 
2191
 
 
2192
int
 
2193
vsf_sysutil_is_port_reserved(unsigned short the_port)
 
2194
{
 
2195
  if (the_port < IPPORT_RESERVED)
 
2196
  {
 
2197
    return 1;
 
2198
  }
 
2199
  return 0;
 
2200
}
 
2201
 
 
2202
const char*
 
2203
vsf_sysutil_inet_ntop(const struct vsf_sysutil_sockaddr* p_sockptr)
 
2204
{
 
2205
  const struct sockaddr* p_sockaddr = &p_sockptr->u.u_sockaddr;
 
2206
  if (p_sockaddr->sa_family == AF_INET)
 
2207
  {
 
2208
    return inet_ntoa(p_sockptr->u.u_sockaddr_in.sin_addr);
 
2209
  }
 
2210
  else if (p_sockaddr->sa_family == AF_INET6)
 
2211
  {
 
2212
    static char inaddr_buf[64];
 
2213
    const char* p_ret = inet_ntop(AF_INET6,
 
2214
                                  &p_sockptr->u.u_sockaddr_in6.sin6_addr,
 
2215
                                  inaddr_buf, sizeof(inaddr_buf));
 
2216
    inaddr_buf[sizeof(inaddr_buf) - 1] = '\0';
 
2217
    if (p_ret == NULL)
 
2218
    {
 
2219
      inaddr_buf[0] = '\0';
 
2220
    }
 
2221
    return inaddr_buf;
 
2222
  }
 
2223
  else
 
2224
  {
 
2225
    die("can only support ipv4 and ipv6 currently");
 
2226
    return 0;
 
2227
  }
 
2228
}
 
2229
 
 
2230
const char*
 
2231
vsf_sysutil_inet_ntoa(const void* p_raw_addr)
 
2232
{
 
2233
  return inet_ntoa(*((struct in_addr*)p_raw_addr));
 
2234
}
 
2235
 
 
2236
int
 
2237
vsf_sysutil_inet_aton(const char* p_text, struct vsf_sysutil_sockaddr* p_addr)
 
2238
{
 
2239
  struct in_addr sin_addr;
 
2240
  if (p_addr->u.u_sockaddr.sa_family != AF_INET)
 
2241
  {
 
2242
    bug("bad family");
 
2243
  }
 
2244
  if (inet_aton(p_text, &sin_addr))
 
2245
  {
 
2246
    vsf_sysutil_memcpy(&p_addr->u.u_sockaddr_in.sin_addr,
 
2247
                       &sin_addr, sizeof(p_addr->u.u_sockaddr_in.sin_addr));
 
2248
    return 1;
 
2249
  }
 
2250
  else
 
2251
  {
 
2252
    return 0;
 
2253
  }
 
2254
}
 
2255
 
 
2256
void
 
2257
vsf_sysutil_dns_resolve(struct vsf_sysutil_sockaddr** p_sockptr,
 
2258
                        const char* p_name)
 
2259
{
 
2260
  struct hostent* hent = gethostbyname(p_name);
 
2261
  if (hent == NULL)
 
2262
  {
 
2263
    die2("cannot resolve host:", p_name);
 
2264
  }
 
2265
  vsf_sysutil_sockaddr_clear(p_sockptr);
 
2266
  if (hent->h_addrtype == AF_INET)
 
2267
  {
 
2268
    unsigned int len = hent->h_length;
 
2269
    if (len > sizeof((*p_sockptr)->u.u_sockaddr_in.sin_addr))
 
2270
    {
 
2271
      len = sizeof((*p_sockptr)->u.u_sockaddr_in.sin_addr);
 
2272
    }
 
2273
    vsf_sysutil_sockaddr_alloc_ipv4(p_sockptr);
 
2274
    vsf_sysutil_memcpy(&(*p_sockptr)->u.u_sockaddr_in.sin_addr,
 
2275
                       hent->h_addr_list[0], len);
 
2276
  }
 
2277
  else if (hent->h_addrtype == AF_INET6)
 
2278
  {
 
2279
    unsigned int len = hent->h_length;
 
2280
    if (len > sizeof((*p_sockptr)->u.u_sockaddr_in6.sin6_addr))
 
2281
    {
 
2282
      len = sizeof((*p_sockptr)->u.u_sockaddr_in6.sin6_addr);
 
2283
    }
 
2284
    vsf_sysutil_sockaddr_alloc_ipv6(p_sockptr);
 
2285
    vsf_sysutil_memcpy(&(*p_sockptr)->u.u_sockaddr_in6.sin6_addr,
 
2286
                       hent->h_addr_list[0], len);
 
2287
  }
 
2288
  else
 
2289
  {
 
2290
    die("gethostbyname(): neither IPv4 nor IPv6");
 
2291
  }
 
2292
}
 
2293
 
 
2294
struct vsf_sysutil_user*
 
2295
vsf_sysutil_getpwuid(const int uid)
 
2296
{
 
2297
  if (uid < 0)
 
2298
  {
 
2299
    bug("negative uid in vsf_sysutil_getpwuid");
 
2300
  }
 
2301
  return (struct vsf_sysutil_user*) getpwuid((unsigned int) uid);
 
2302
}
 
2303
 
 
2304
struct vsf_sysutil_user*
 
2305
vsf_sysutil_getpwnam(const char* p_user)
 
2306
{
 
2307
  return (struct vsf_sysutil_user*) getpwnam(p_user);
 
2308
}
 
2309
 
 
2310
const char*
 
2311
vsf_sysutil_user_getname(const struct vsf_sysutil_user* p_user)
 
2312
{
 
2313
  const struct passwd* p_passwd = (const struct passwd*) p_user;
 
2314
  return p_passwd->pw_name;
 
2315
}
 
2316
 
 
2317
const char*
 
2318
vsf_sysutil_user_get_homedir(const struct vsf_sysutil_user* p_user)
 
2319
{
 
2320
  const struct passwd* p_passwd = (const struct passwd*) p_user;
 
2321
  return p_passwd->pw_dir;
 
2322
}
 
2323
 
 
2324
int
 
2325
vsf_sysutil_user_getuid(const struct vsf_sysutil_user* p_user)
 
2326
{
 
2327
  const struct passwd* p_passwd = (const struct passwd*) p_user;
 
2328
  return p_passwd->pw_uid;
 
2329
}
 
2330
 
 
2331
int
 
2332
vsf_sysutil_user_getgid(const struct vsf_sysutil_user* p_user)
 
2333
 
2334
  const struct passwd* p_passwd = (const struct passwd*) p_user;
 
2335
  return p_passwd->pw_gid;
 
2336
}
 
2337
 
 
2338
struct vsf_sysutil_group*
 
2339
vsf_sysutil_getgrgid(const int gid)
 
2340
{
 
2341
  if (gid < 0)
 
2342
  {
 
2343
    die("negative gid in vsf_sysutil_getgrgid");
 
2344
  }
 
2345
  return (struct vsf_sysutil_group*) getgrgid((unsigned int) gid);
 
2346
}
 
2347
 
 
2348
const char*
 
2349
vsf_sysutil_group_getname(const struct vsf_sysutil_group* p_group)
 
2350
{
 
2351
  const struct group* p_grp = (const struct group*) p_group;
 
2352
  return p_grp->gr_name;
 
2353
}
 
2354
 
 
2355
unsigned char
 
2356
vsf_sysutil_get_random_byte(void)
 
2357
{
 
2358
  static int seeded;
 
2359
  unsigned int uint_res;
 
2360
  unsigned char c1, c2, c3, c4;
 
2361
  if (!seeded)
 
2362
  {
 
2363
    struct timeval tv;
 
2364
    int retval = gettimeofday(&tv, NULL);
 
2365
    if (retval != 0)
 
2366
    {
 
2367
      die("gettimeofday");
 
2368
    }
 
2369
    srand((unsigned)tv.tv_usec);
 
2370
    seeded = 1;
 
2371
  }
 
2372
  uint_res = rand();
 
2373
  c1 = uint_res & 0x000000ff;
 
2374
  c2 = (uint_res >> 8) & 0x000000ff;
 
2375
  c3 = (uint_res >> 16) & 0x000000ff;
 
2376
  c4 = (uint_res >> 24) & 0x000000ff;
 
2377
  return c1 ^ c2 ^ c3 ^ c4;    
 
2378
}
 
2379
 
 
2380
int
 
2381
vsf_sysutil_running_as_root(void)
 
2382
{
 
2383
  return (getuid() == 0);
 
2384
}
 
2385
 
 
2386
void
 
2387
vsf_sysutil_setuid(const struct vsf_sysutil_user* p_user)
 
2388
{
 
2389
  const struct passwd* p_passwd = (const struct passwd*) p_user;
 
2390
  vsf_sysutil_setuid_numeric(p_passwd->pw_uid);
 
2391
}
 
2392
 
 
2393
void
 
2394
vsf_sysutil_setuid_numeric(int uid)
 
2395
{
 
2396
  int retval = setuid(uid);
 
2397
  if (retval != 0)
 
2398
  {
 
2399
    die("setuid");
 
2400
  }
 
2401
}
 
2402
 
 
2403
void
 
2404
vsf_sysutil_setgid(const struct vsf_sysutil_user* p_user)
 
2405
{
 
2406
  const struct passwd* p_passwd = (const struct passwd*) p_user;
 
2407
  vsf_sysutil_setgid_numeric(p_passwd->pw_gid);
 
2408
}
 
2409
 
 
2410
void
 
2411
vsf_sysutil_setgid_numeric(int gid)
 
2412
{
 
2413
  int retval = setgid(gid);
 
2414
  if (retval != 0)
 
2415
  {
 
2416
    die("setgid");
 
2417
  }
 
2418
}
 
2419
 
 
2420
int
 
2421
vsf_sysutil_geteuid(void)
 
2422
{
 
2423
  int retval = geteuid();
 
2424
  if (retval < 0)
 
2425
  {
 
2426
    die("geteuid");
 
2427
  }
 
2428
  return retval;
 
2429
}
 
2430
 
 
2431
int
 
2432
vsf_sysutil_getegid(void)
 
2433
{
 
2434
  int retval = getegid();
 
2435
  if (retval < 0)
 
2436
  {
 
2437
    die("getegid");
 
2438
  }
 
2439
  return retval;
 
2440
}
 
2441
 
 
2442
void
 
2443
vsf_sysutil_seteuid(const struct vsf_sysutil_user* p_user)
 
2444
{
 
2445
  const struct passwd* p_passwd = (const struct passwd*) p_user;
 
2446
  vsf_sysutil_seteuid_numeric(p_passwd->pw_uid);
 
2447
}
 
2448
 
 
2449
void
 
2450
vsf_sysutil_setegid(const struct vsf_sysutil_user* p_user)
 
2451
{
 
2452
  const struct passwd* p_passwd = (const struct passwd*) p_user;
 
2453
  vsf_sysutil_setegid_numeric(p_passwd->pw_gid);
 
2454
}
 
2455
 
 
2456
void
 
2457
vsf_sysutil_seteuid_numeric(int uid)
 
2458
{
 
2459
  /* setreuid() would seem to be more portable than seteuid() */
 
2460
  int retval = setreuid(-1, uid);
 
2461
  if (retval != 0)
 
2462
  {
 
2463
    die("seteuid");
 
2464
  }
 
2465
}
 
2466
 
 
2467
void
 
2468
vsf_sysutil_setegid_numeric(int gid)
 
2469
{
 
2470
  /* setregid() would seem to be more portable than setegid() */
 
2471
  int retval = setregid(-1, gid);
 
2472
  if (retval != 0)
 
2473
  {
 
2474
    die("setegid");
 
2475
  }
 
2476
}
 
2477
 
 
2478
void
 
2479
vsf_sysutil_clear_supp_groups(void)
 
2480
{
 
2481
  int retval = setgroups(0, NULL);
 
2482
  if (retval != 0)
 
2483
  {
 
2484
    die("setgroups");
 
2485
  }
 
2486
}
 
2487
 
 
2488
void
 
2489
vsf_sysutil_initgroups(const struct vsf_sysutil_user* p_user)
 
2490
{
 
2491
  const struct passwd* p_passwd = (const struct passwd*) p_user;
 
2492
  int retval = initgroups(p_passwd->pw_name, p_passwd->pw_gid);
 
2493
  if (retval != 0)
 
2494
  {
 
2495
    die("initgroups");
 
2496
  }
 
2497
}
 
2498
 
 
2499
void
 
2500
vsf_sysutil_chroot(const char* p_root_path)
 
2501
{
 
2502
  int retval = chroot(p_root_path);
 
2503
  if (retval != 0)
 
2504
  {
 
2505
    die("chroot");
 
2506
  }
 
2507
}
 
2508
 
 
2509
unsigned int
 
2510
vsf_sysutil_get_umask(void)
 
2511
{
 
2512
  return s_current_umask;
 
2513
}
 
2514
 
 
2515
void
 
2516
vsf_sysutil_set_umask(unsigned int new_umask)
 
2517
{
 
2518
  s_current_umask = (new_umask & 0777);
 
2519
  (void) umask(s_current_umask);
 
2520
}
 
2521
 
 
2522
void
 
2523
vsf_sysutil_make_session_leader(void)
 
2524
{
 
2525
  /* This makes us the leader if we are not already */
 
2526
  (void) setsid();
 
2527
  /* Check we're the leader */
 
2528
  if ((int) vsf_sysutil_getpid() != getpgrp())
 
2529
  {
 
2530
    die("not session leader");
 
2531
  }
 
2532
}
 
2533
 
 
2534
void
 
2535
vsf_sysutil_reopen_standard_fds(void)
 
2536
{
 
2537
  /* This reopens STDIN, STDOUT and STDERR to /dev/null */
 
2538
  int fd;
 
2539
  if ((fd = open("/dev/null", O_RDWR, 0)) < 0)
 
2540
  {
 
2541
    goto error;
 
2542
  }
 
2543
  vsf_sysutil_dupfd2(fd, STDIN_FILENO);
 
2544
  vsf_sysutil_dupfd2(fd, STDOUT_FILENO);
 
2545
  vsf_sysutil_dupfd2(fd, STDERR_FILENO);
 
2546
  if ( fd > 2 )
 
2547
  {
 
2548
    vsf_sysutil_close(fd);
 
2549
  }
 
2550
  return;
 
2551
 
 
2552
error:
 
2553
  die("reopening standard file descriptors to /dev/null failed");
 
2554
}
 
2555
 
 
2556
void
 
2557
vsf_sysutil_tzset(void)
 
2558
{
 
2559
  int retval;
 
2560
  char tzbuf[sizeof("+HHMM!")];
 
2561
  time_t the_time = time(NULL);
 
2562
  struct tm* p_tm;
 
2563
  tzset();
 
2564
  p_tm = localtime(&the_time);
 
2565
  if (p_tm == NULL)
 
2566
  {
 
2567
    die("localtime");
 
2568
  }
 
2569
  /* Set our timezone in the TZ environment variable to cater for the fact
 
2570
   * that modern glibc does not cache /etc/localtime (which becomes inaccessible
 
2571
   * when we chroot().
 
2572
   */
 
2573
  retval = strftime(tzbuf, sizeof(tzbuf), "%z", p_tm);
 
2574
  tzbuf[sizeof(tzbuf) - 1] = '\0';
 
2575
  if (retval == 5)
 
2576
  {
 
2577
    /* Static because putenv() does not copy the string. */
 
2578
    static char envtz[sizeof("TZ=UTC-hh:mm")];
 
2579
    /* Insert a colon so we have e.g. -05:00 instead of -0500 */
 
2580
    tzbuf[5] = tzbuf[4];
 
2581
    tzbuf[4] = tzbuf[3];
 
2582
    tzbuf[3] = ':';
 
2583
    /* Invert the sign - we just got the offset _from_ UTC but for TZ, we need
 
2584
     * the offset _to_ UTC.
 
2585
     */
 
2586
    if (tzbuf[0] == '+')
 
2587
    {
 
2588
      tzbuf[0] = '-';
 
2589
    }
 
2590
    else
 
2591
    {
 
2592
      tzbuf[0] = '+';
 
2593
    }
 
2594
    snprintf(envtz, sizeof(envtz), "TZ=UTC%s", tzbuf);
 
2595
    putenv(envtz);
 
2596
    s_timezone = ((tzbuf[1] - '0') * 10 + (tzbuf[2] - '0')) * 60 * 60;
 
2597
    s_timezone += ((tzbuf[4] - '0') * 10 + (tzbuf[5] - '0')) * 60;
 
2598
    if (tzbuf[0] == '-')
 
2599
    {
 
2600
      s_timezone *= -1;
 
2601
    }
 
2602
  }
 
2603
  /* Call in to the time subsystem again now that TZ is set, trying to force
 
2604
   * caching of the actual zoneinfo for the timezone.
 
2605
   */
 
2606
  p_tm = localtime(&the_time);
 
2607
  if (p_tm == NULL)
 
2608
  {
 
2609
    die("localtime #2");
 
2610
  }
 
2611
  p_tm = gmtime(&the_time);
 
2612
  if (p_tm == NULL)
 
2613
  {
 
2614
    die("gmtime");
 
2615
  }
 
2616
}
 
2617
 
 
2618
const char*
 
2619
vsf_sysutil_get_current_date(void)
 
2620
{
 
2621
  static char datebuf[64];
 
2622
  time_t curr_time;
 
2623
  const struct tm* p_tm;
 
2624
  int i = 0;
 
2625
  curr_time = vsf_sysutil_get_time_sec();
 
2626
  p_tm = localtime(&curr_time);
 
2627
  if (strftime(datebuf, sizeof(datebuf), "%a %b!%d %H:%M:%S %Y", p_tm) == 0)
 
2628
  {
 
2629
    die("strftime");
 
2630
  }
 
2631
  datebuf[sizeof(datebuf) - 1] = '\0';
 
2632
  /* This hack is because %e in strftime() isn't so portable */
 
2633
  while (datebuf[i] != '!' && datebuf[i] != '\0')
 
2634
  {
 
2635
    ++i;
 
2636
  }
 
2637
  if (datebuf[i] == '!')
 
2638
  {
 
2639
    datebuf[i] = ' ';
 
2640
    if (datebuf[i+1] == '0')
 
2641
    {
 
2642
      datebuf[i+1] = ' ';
 
2643
    }
 
2644
  }
 
2645
  return datebuf;
 
2646
}
 
2647
 
 
2648
long
 
2649
vsf_sysutil_get_time_sec(void)
 
2650
{
 
2651
  if (gettimeofday(&s_current_time, NULL) != 0)
 
2652
  {
 
2653
    die("gettimeofday");
 
2654
  }
 
2655
  return s_current_time.tv_sec;
 
2656
}
 
2657
 
 
2658
long
 
2659
vsf_sysutil_get_time_usec(void)
 
2660
{
 
2661
  return s_current_time.tv_usec;
 
2662
}
 
2663
 
 
2664
void
 
2665
vsf_sysutil_qsort(void* p_base, unsigned int num_elem, unsigned int elem_size,
 
2666
                  int (*p_compar)(const void *, const void *))
 
2667
{
 
2668
  qsort(p_base, num_elem, elem_size, p_compar);
 
2669
}
 
2670
 
 
2671
void
 
2672
vsf_sysutil_sleep(double seconds)
 
2673
{
 
2674
  int retval;
 
2675
  int saved_errno;
 
2676
  double fractional;
 
2677
  time_t secs;
 
2678
  struct timespec ts;
 
2679
  secs = (time_t) seconds;
 
2680
  fractional = seconds - (double) secs;
 
2681
  ts.tv_sec = secs;
 
2682
  ts.tv_nsec = (long) (fractional * (double) 1000000000);
 
2683
  do
 
2684
  {
 
2685
    retval = nanosleep(&ts, &ts);
 
2686
    saved_errno = errno;
 
2687
    vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0);
 
2688
  } while (retval == -1 && saved_errno == EINTR);
 
2689
}
 
2690
 
 
2691
char*
 
2692
vsf_sysutil_getenv(const char* p_var)
 
2693
{
 
2694
  return getenv(p_var);
 
2695
}
 
2696
 
 
2697
void
 
2698
vsf_sysutil_openlog(int force)
 
2699
{
 
2700
  int facility = LOG_DAEMON;
 
2701
  int option = LOG_PID;
 
2702
  if (!force)
 
2703
  {
 
2704
    option |= LOG_NDELAY;
 
2705
  }
 
2706
#ifdef LOG_FTP
 
2707
  facility = LOG_FTP;
 
2708
#endif
 
2709
  openlog("vsftpd", option, facility);
 
2710
}
 
2711
 
 
2712
void
 
2713
vsf_sysutil_closelog(void)
 
2714
{
 
2715
  closelog();
 
2716
}
 
2717
 
 
2718
void
 
2719
vsf_sysutil_syslog(const char* p_text, int severe)
 
2720
{
 
2721
  int prio = LOG_INFO;
 
2722
  if (severe)
 
2723
  {
 
2724
    prio = LOG_WARNING;
 
2725
  }
 
2726
  syslog(prio, "%s", p_text);
 
2727
}
 
2728
 
 
2729
long
 
2730
vsf_sysutil_parse_time(const char* p_text)
 
2731
{
 
2732
  struct tm the_time;
 
2733
  unsigned int len = vsf_sysutil_strlen(p_text);
 
2734
  vsf_sysutil_memclr(&the_time, sizeof(the_time));
 
2735
  if (len >= 8)
 
2736
  {
 
2737
    char yr[5];
 
2738
    char mon[3];
 
2739
    char day[3];
 
2740
    vsf_sysutil_strcpy(yr, p_text, 5);
 
2741
    vsf_sysutil_strcpy(mon, p_text + 4, 3);
 
2742
    vsf_sysutil_strcpy(day, p_text + 6, 3);
 
2743
    the_time.tm_year = vsf_sysutil_atoi(yr) - 1900;
 
2744
    the_time.tm_mon = vsf_sysutil_atoi(mon) - 1;
 
2745
    the_time.tm_mday = vsf_sysutil_atoi(day);
 
2746
  }
 
2747
  if (len >= 14)
 
2748
  {
 
2749
    char hr[3];
 
2750
    char mins[3];
 
2751
    char sec[3];
 
2752
    vsf_sysutil_strcpy(hr, p_text + 8, 3);
 
2753
    vsf_sysutil_strcpy(mins, p_text + 10, 3);
 
2754
    vsf_sysutil_strcpy(sec, p_text + 12, 3);
 
2755
    the_time.tm_hour = vsf_sysutil_atoi(hr);
 
2756
    the_time.tm_min = vsf_sysutil_atoi(mins);
 
2757
    the_time.tm_sec = vsf_sysutil_atoi(sec);
 
2758
  }
 
2759
  return mktime(&the_time);
 
2760
}
 
2761
 
 
2762
int
 
2763
vsf_sysutil_setmodtime(const char* p_file, long the_time, int is_localtime)
 
2764
{
 
2765
  struct utimbuf new_times;
 
2766
  if (!is_localtime)
 
2767
  {
 
2768
    the_time -= s_timezone;
 
2769
  }
 
2770
  vsf_sysutil_memclr(&new_times, sizeof(new_times));
 
2771
  new_times.actime = the_time;
 
2772
  new_times.modtime = the_time;
 
2773
  return utime(p_file, &new_times);
 
2774
}
 
2775
 
 
2776
void
 
2777
vsf_sysutil_ftruncate(int fd)
 
2778
{
 
2779
  int ret = ftruncate(fd, 0);
 
2780
  if (ret != 0)
 
2781
  {
 
2782
    die("ftruncate");
 
2783
  }
 
2784
}
 
2785
 
 
2786
int
 
2787
vsf_sysutil_getuid(void)
 
2788
{
 
2789
  return getuid();
 
2790
}
 
2791
 
 
2792
void
 
2793
vsf_sysutil_set_address_space_limit(unsigned long bytes)
 
2794
{
 
2795
  /* Unfortunately, OpenBSD is missing RLIMIT_AS. */
 
2796
#ifdef RLIMIT_AS
 
2797
  int ret;
 
2798
  struct rlimit rlim;
 
2799
  rlim.rlim_cur = bytes;
 
2800
  rlim.rlim_max = bytes;
 
2801
  ret = setrlimit(RLIMIT_AS, &rlim);
 
2802
  /* Permit EPERM as this could indicate that the shell launching vsftpd already
 
2803
   * has a lower limit.
 
2804
   */
 
2805
  if (ret != 0 && errno != EPERM)
 
2806
  {
 
2807
    die("setrlimit");
 
2808
  }
 
2809
#endif /* RLIMIT_AS */
 
2810
  (void) bytes;
 
2811
}
 
2812
 
 
2813
void
 
2814
vsf_sysutil_set_no_fds()
 
2815
{
 
2816
  int ret;
 
2817
  struct rlimit rlim;
 
2818
  rlim.rlim_cur = 0;
 
2819
  rlim.rlim_max = 0;
 
2820
  ret = setrlimit(RLIMIT_NOFILE, &rlim);
 
2821
  if (ret != 0)
 
2822
  {
 
2823
    die("setrlimit NOFILE");
 
2824
  }
 
2825
}
 
2826
 
 
2827
void
 
2828
vsf_sysutil_set_no_procs()
 
2829
{
 
2830
#ifdef RLIMIT_NPROC
 
2831
  int ret;
 
2832
  struct rlimit rlim;
 
2833
  rlim.rlim_cur = 0;
 
2834
  rlim.rlim_max = 0;
 
2835
  ret = setrlimit(RLIMIT_NPROC, &rlim);
 
2836
  if (ret != 0)
 
2837
  {
 
2838
    die("setrlimit NPROC");
 
2839
  }
 
2840
#endif
 
2841
}
 
2842
 
 
2843
void
 
2844
vsf_sysutil_post_fork()
 
2845
{
 
2846
  int i;
 
2847
  /* Don't inherit any exit function. */
 
2848
  s_exit_func = NULL;
 
2849
  /* Uncached the current PID. */ 
 
2850
  s_current_pid = -1;
 
2851
  /* Don't inherit anything relating to the synchronous signal system */
 
2852
  s_io_handler = NULL;
 
2853
  for (i=0; i < NSIG; ++i)
 
2854
  {
 
2855
    s_sig_details[i].sync_sig_handler = NULL;
 
2856
  }
 
2857
  for (i=0; i < NSIG; ++i)
 
2858
  {
 
2859
    s_sig_details[i].pending = 0;
 
2860
  }
 
2861
}