]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/vms-misc.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / bfd / vms-misc.c
CommitLineData
0c376465 1/* vms-misc.c -- BFD back-end for VMS/VAX (openVMS/VAX) and
252b5132 2 EVAX (openVMS/Alpha) files.
d87bef3a 3 Copyright (C) 1996-2023 Free Software Foundation, Inc.
0c376465
TG
4
5 Miscellaneous functions.
252b5132
RH
6
7 Written by Klaus K"ampf (kkaempf@rmi.de)
8
7920ce38
NC
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
cd123cb7 11 the Free Software Foundation; either version 3 of the License, or
7920ce38 12 (at your option) any later version.
252b5132 13
7920ce38
NC
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
252b5132 18
7920ce38
NC
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
cd123cb7
NC
21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
22 MA 02110-1301, USA. */
252b5132 23
252b5132
RH
24#if __STDC__
25#include <stdarg.h>
26#endif
27
252b5132 28#include "sysdep.h"
3db64b00 29#include "bfd.h"
252b5132
RH
30#include "bfdlink.h"
31#include "libbfd.h"
4b544b64 32#include "safe-ctype.h"
252b5132 33
95e34ef7 34#ifdef VMS
953b49ed 35#define __NEW_STARLET
95e34ef7
TG
36#include <rms.h>
37#include <unixlib.h>
953b49ed 38#include <gen64def.h>
95e34ef7
TG
39#include <starlet.h>
40#define RME$C_SETRFM 0x00000001
41#include <unistd.h>
42#endif
43#include <time.h>
0c376465 44
95e34ef7
TG
45#include "vms.h"
46#include "vms/emh.h"
0c376465 47
252b5132 48#if VMS_DEBUG
7920ce38 49/* Debug functions. */
252b5132 50
0c376465
TG
51/* Debug function for all vms extensions evaluates environment
52 variable VMS_DEBUG for a numerical value on the first call all
53 error levels below this value are printed:
558e161f 54
0c376465 55 Levels:
252b5132
RH
56 1 toplevel bfd calls (functions from the bfd vector)
57 2 functions called by bfd calls
58 ...
59 9 almost everything
60
0c376465 61 Level is also indentation level. Indentation is performed
7920ce38 62 if level > 0. */
252b5132 63
252b5132
RH
64void
65_bfd_vms_debug (int level, char *format, ...)
66{
67 static int min_level = -1;
68 static FILE *output = NULL;
69 char *eptr;
70 va_list args;
7920ce38 71 int abslvl = (level > 0) ? level : - level;
252b5132
RH
72
73 if (min_level == -1)
74 {
7920ce38 75 if ((eptr = getenv ("VMS_DEBUG")) != NULL)
252b5132 76 {
7920ce38 77 min_level = atoi (eptr);
252b5132
RH
78 output = stderr;
79 }
80 else
81 min_level = 0;
82 }
83 if (output == NULL)
84 return;
85 if (abslvl > min_level)
86 return;
87
95e34ef7 88 while (--level > 0)
558e161f 89 fprintf (output, " ");
7920ce38 90 va_start (args, format);
558e161f 91 vfprintf (output, format, args);
7920ce38
NC
92 fflush (output);
93 va_end (args);
252b5132
RH
94}
95
7920ce38
NC
96/* A debug function
97 hex dump 'size' bytes starting at 'ptr'. */
252b5132
RH
98
99void
95e34ef7 100_bfd_hexdump (int level, unsigned char *ptr, int size, int offset)
252b5132
RH
101{
102 unsigned char *lptr = ptr;
103 int count = 0;
104 long start = offset;
105
106 while (size-- > 0)
107 {
95e34ef7 108 if ((count % 16) == 0)
252b5132
RH
109 vms_debug (level, "%08lx:", start);
110 vms_debug (-level, " %02x", *ptr++);
111 count++;
112 start++;
113 if (size == 0)
114 {
95e34ef7 115 while ((count % 16) != 0)
252b5132
RH
116 {
117 vms_debug (-level, " ");
118 count++;
119 }
120 }
95e34ef7 121 if ((count % 16) == 0)
252b5132
RH
122 {
123 vms_debug (-level, " ");
124 while (lptr < ptr)
125 {
95e34ef7 126 vms_debug (-level, "%c", (*lptr < 32) ? '.' : *lptr);
252b5132
RH
127 lptr++;
128 }
129 vms_debug (-level, "\n");
130 }
131 }
95e34ef7 132 if ((count % 16) != 0)
252b5132 133 vms_debug (-level, "\n");
252b5132
RH
134}
135#endif
252b5132 136\f
0c376465 137
8bdf0be1
NC
138/* Copy sized string (string with fixed size) to new allocated area.
139 Size is string size (size of record). */
252b5132
RH
140
141char *
37d2e9c7 142_bfd_vms_save_sized_string (bfd *abfd, unsigned char *str, size_t size)
252b5132 143{
37d2e9c7 144 char *newstr;
252b5132 145
37d2e9c7
AM
146 if (size == (size_t) -1)
147 {
148 bfd_set_error (bfd_error_no_memory);
149 return NULL;
150 }
151 newstr = bfd_alloc (abfd, size + 1);
252b5132 152 if (newstr == NULL)
7920ce38 153 return NULL;
37d2e9c7 154 memcpy (newstr, str, size);
252b5132
RH
155 newstr[size] = 0;
156
157 return newstr;
158}
159
8bdf0be1
NC
160/* Copy counted string (string with size at first byte) to new allocated area.
161 PTR points to size byte on entry. */
252b5132
RH
162
163char *
37d2e9c7 164_bfd_vms_save_counted_string (bfd *abfd, unsigned char *ptr, size_t maxlen)
252b5132 165{
0c70050a 166 unsigned int len;
252b5132 167
0c70050a
AM
168 if (maxlen == 0)
169 return NULL;
170 len = *ptr++;
171 if (len > maxlen - 1)
7adc0a81 172 return NULL;
37d2e9c7 173 return _bfd_vms_save_sized_string (abfd, ptr, len);
252b5132 174}
252b5132 175\f
95e34ef7 176/* Object output routines. */
252b5132 177
95e34ef7
TG
178/* Begin new record.
179 Write 2 bytes rectype and 2 bytes record length. */
252b5132
RH
180
181void
95e34ef7 182_bfd_vms_output_begin (struct vms_rec_wr *recwr, int rectype)
252b5132 183{
95e34ef7 184 vms_debug2 ((6, "_bfd_vms_output_begin (type %d)\n", rectype));
252b5132 185
95e34ef7
TG
186 /* Record must have been closed. */
187 BFD_ASSERT (recwr->size == 0);
252b5132 188
95e34ef7 189 _bfd_vms_output_short (recwr, (unsigned int) rectype);
252b5132 190
95e34ef7
TG
191 /* Placeholder for length. */
192 _bfd_vms_output_short (recwr, 0);
252b5132 193}
252b5132 194
95e34ef7
TG
195/* Begin new sub-record.
196 Write 2 bytes rectype, and 2 bytes record length. */
252b5132
RH
197
198void
95e34ef7 199_bfd_vms_output_begin_subrec (struct vms_rec_wr *recwr, int rectype)
252b5132 200{
95e34ef7 201 vms_debug2 ((6, "_bfd_vms_output_begin_subrec (type %d)\n", rectype));
252b5132 202
95e34ef7
TG
203 /* Subrecord must have been closed. */
204 BFD_ASSERT (recwr->subrec_offset == 0);
252b5132 205
95e34ef7
TG
206 /* Save start of subrecord offset. */
207 recwr->subrec_offset = recwr->size;
252b5132 208
95e34ef7
TG
209 /* Subrecord type. */
210 _bfd_vms_output_short (recwr, (unsigned int) rectype);
252b5132 211
7920ce38 212 /* Placeholder for length. */
95e34ef7 213 _bfd_vms_output_short (recwr, 0);
252b5132
RH
214}
215
7920ce38 216/* Set record/subrecord alignment. */
252b5132
RH
217
218void
95e34ef7 219_bfd_vms_output_alignment (struct vms_rec_wr *recwr, int alignto)
252b5132 220{
95e34ef7
TG
221 vms_debug2 ((6, "_bfd_vms_output_alignment (%d)\n", alignto));
222 recwr->align = alignto;
252b5132
RH
223}
224
95e34ef7
TG
225/* Align the size of the current record (whose length is LENGTH).
226 Warning: this obviously changes the record (and the possible subrecord)
227 length. */
252b5132 228
95e34ef7
TG
229static void
230_bfd_vms_output_align (struct vms_rec_wr *recwr, unsigned int length)
252b5132 231{
95e34ef7
TG
232 unsigned int real_size = recwr->size;
233 unsigned int aligncount;
252b5132 234
95e34ef7
TG
235 /* Pad with 0 if alignment is required. */
236 aligncount = (recwr->align - (length % recwr->align)) % recwr->align;
237 vms_debug2 ((6, "align: adding %d bytes\n", aligncount));
238 while (aligncount-- > 0)
239 recwr->buf[real_size++] = 0;
252b5132 240
95e34ef7 241 recwr->size = real_size;
252b5132
RH
242}
243
95e34ef7 244/* Ends current sub-record. Set length field. */
252b5132
RH
245
246void
95e34ef7 247_bfd_vms_output_end_subrec (struct vms_rec_wr *recwr)
252b5132 248{
95e34ef7 249 int real_size = recwr->size;
252b5132
RH
250 int length;
251
95e34ef7
TG
252 /* Subrecord must be open. */
253 BFD_ASSERT (recwr->subrec_offset != 0);
252b5132 254
95e34ef7 255 length = real_size - recwr->subrec_offset;
252b5132
RH
256
257 if (length == 0)
258 return;
252b5132 259
95e34ef7 260 _bfd_vms_output_align (recwr, length);
252b5132 261
7920ce38 262 /* Put length to buffer. */
95e34ef7 263 bfd_putl16 ((bfd_vma) (recwr->size - recwr->subrec_offset),
07d6d2b8 264 recwr->buf + recwr->subrec_offset + 2);
252b5132 265
95e34ef7
TG
266 /* Close the subrecord. */
267 recwr->subrec_offset = 0;
252b5132
RH
268}
269
95e34ef7 270/* Ends current record (and write it). */
252b5132
RH
271
272void
95e34ef7 273_bfd_vms_output_end (bfd *abfd, struct vms_rec_wr *recwr)
252b5132 274{
95e34ef7 275 vms_debug2 ((6, "_bfd_vms_output_end (size %u)\n", recwr->size));
252b5132 276
95e34ef7
TG
277 /* Subrecord must have been closed. */
278 BFD_ASSERT (recwr->subrec_offset == 0);
252b5132 279
95e34ef7
TG
280 if (recwr->size == 0)
281 return;
252b5132 282
95e34ef7
TG
283 _bfd_vms_output_align (recwr, recwr->size);
284
285 /* Write the length word. */
286 bfd_putl16 ((bfd_vma) recwr->size, recwr->buf + 2);
287
288 /* File is open in undefined (UDF) format on VMS, but ultimately will be
289 converted to variable length (VAR) format. VAR format has a length
290 word first which must be explicitly output in UDF format. */
291 /* So, first the length word. */
292 bfd_bwrite (recwr->buf + 2, 2, abfd);
293
294 /* Align. */
295 if (recwr->size & 1)
296 recwr->buf[recwr->size++] = 0;
297
298 /* Then the record. */
299 bfd_bwrite (recwr->buf, (size_t) recwr->size, abfd);
300
301 recwr->size = 0;
302}
303
304/* Check remaining buffer size. Return what's left. */
252b5132
RH
305
306int
95e34ef7 307_bfd_vms_output_check (struct vms_rec_wr *recwr, int size)
252b5132 308{
95e34ef7 309 vms_debug2 ((6, "_bfd_vms_output_check (%d)\n", size));
252b5132 310
95e34ef7 311 return (MAX_OUTREC_SIZE - (recwr->size + size + MIN_OUTREC_LUFT));
252b5132
RH
312}
313
7920ce38 314/* Output byte (8 bit) value. */
252b5132
RH
315
316void
95e34ef7 317_bfd_vms_output_byte (struct vms_rec_wr *recwr, unsigned int value)
252b5132 318{
95e34ef7 319 vms_debug2 ((6, "_bfd_vms_output_byte (%02x)\n", value));
252b5132 320
95e34ef7
TG
321 *(recwr->buf + recwr->size) = value;
322 recwr->size += 1;
252b5132
RH
323}
324
7920ce38 325/* Output short (16 bit) value. */
252b5132
RH
326
327void
95e34ef7 328_bfd_vms_output_short (struct vms_rec_wr *recwr, unsigned int value)
252b5132 329{
95e34ef7 330 vms_debug2 ((6, "_bfd_vms_output_short (%04x)\n", value));
252b5132 331
95e34ef7
TG
332 bfd_putl16 ((bfd_vma) value & 0xffff, recwr->buf + recwr->size);
333 recwr->size += 2;
252b5132
RH
334}
335
7920ce38 336/* Output long (32 bit) value. */
252b5132
RH
337
338void
95e34ef7 339_bfd_vms_output_long (struct vms_rec_wr *recwr, unsigned long value)
252b5132 340{
95e34ef7 341 vms_debug2 ((6, "_bfd_vms_output_long (%08lx)\n", value));
252b5132 342
95e34ef7
TG
343 bfd_putl32 ((bfd_vma) value, recwr->buf + recwr->size);
344 recwr->size += 4;
252b5132
RH
345}
346
7920ce38 347/* Output quad (64 bit) value. */
252b5132
RH
348
349void
95e34ef7 350_bfd_vms_output_quad (struct vms_rec_wr *recwr, bfd_vma value)
252b5132 351{
95e34ef7 352 vms_debug2 ((6, "_bfd_vms_output_quad (%08lx)\n", (unsigned long)value));
252b5132 353
95e34ef7
TG
354 bfd_putl64 (value, recwr->buf + recwr->size);
355 recwr->size += 8;
252b5132
RH
356}
357
7920ce38 358/* Output c-string as counted string. */
252b5132
RH
359
360void
81bb31c0 361_bfd_vms_output_counted (struct vms_rec_wr *recwr, const char *value)
252b5132 362{
7920ce38 363 int len;
252b5132 364
95e34ef7 365 vms_debug2 ((6, "_bfd_vms_output_counted (%s)\n", value));
252b5132
RH
366
367 len = strlen (value);
368 if (len == 0)
369 {
4eca0228 370 _bfd_error_handler (_("_bfd_vms_output_counted called with zero bytes"));
252b5132
RH
371 return;
372 }
373 if (len > 255)
374 {
4eca0228 375 _bfd_error_handler (_("_bfd_vms_output_counted called with too many bytes"));
252b5132
RH
376 return;
377 }
95e34ef7 378 _bfd_vms_output_byte (recwr, (unsigned int) len & 0xff);
81bb31c0 379 _bfd_vms_output_dump (recwr, (const unsigned char *)value, len);
252b5132
RH
380}
381
7920ce38 382/* Output character area. */
252b5132
RH
383
384void
81bb31c0 385_bfd_vms_output_dump (struct vms_rec_wr *recwr, const unsigned char *data, int len)
252b5132 386{
95e34ef7 387 vms_debug2 ((6, "_bfd_vms_output_dump (%d)\n", len));
252b5132 388
95e34ef7 389 if (len == 0)
252b5132
RH
390 return;
391
95e34ef7
TG
392 memcpy (recwr->buf + recwr->size, data, (size_t) len);
393 recwr->size += len;
252b5132
RH
394}
395
7920ce38 396/* Output count bytes of value. */
252b5132
RH
397
398void
95e34ef7 399_bfd_vms_output_fill (struct vms_rec_wr *recwr, int value, int count)
252b5132 400{
95e34ef7 401 vms_debug2 ((6, "_bfd_vms_output_fill (val %02x times %d)\n", value, count));
252b5132
RH
402
403 if (count == 0)
404 return;
95e34ef7
TG
405 memset (recwr->buf + recwr->size, value, (size_t) count);
406 recwr->size += count;
252b5132
RH
407}
408
95e34ef7
TG
409#ifdef VMS
410/* Convert the file to variable record length format. This is done
411 using undocumented system call sys$modify().
412 Pure VMS version. */
252b5132 413
bfea910e
TG
414static void
415vms_convert_to_var (char * vms_filename)
252b5132 416{
95e34ef7 417 struct FAB fab = cc$rms_fab;
252b5132 418
95e34ef7
TG
419 fab.fab$l_fna = vms_filename;
420 fab.fab$b_fns = strlen (vms_filename);
421 fab.fab$b_fac = FAB$M_PUT;
422 fab.fab$l_fop = FAB$M_ESC;
423 fab.fab$l_ctx = RME$C_SETRFM;
252b5132 424
95e34ef7 425 sys$open (&fab);
252b5132 426
95e34ef7 427 fab.fab$b_rfm = FAB$C_VAR;
252b5132 428
95e34ef7
TG
429 sys$modify (&fab);
430 sys$close (&fab);
252b5132
RH
431}
432
95e34ef7
TG
433static int
434vms_convert_to_var_1 (char *filename, int type)
252b5132 435{
95e34ef7 436 if (type != DECC$K_FILE)
0a1b45a2 437 return false;
95e34ef7 438 vms_convert_to_var (filename);
0a1b45a2 439 return true;
252b5132
RH
440}
441
95e34ef7
TG
442/* Convert the file to variable record length format. This is done
443 using undocumented system call sys$modify().
444 Unix filename version. */
252b5132 445
bfea910e
TG
446int
447_bfd_vms_convert_to_var_unix_filename (const char *unix_filename)
252b5132 448{
95e34ef7 449 if (decc$to_vms (unix_filename, &vms_convert_to_var_1, 0, 1) != 1)
0a1b45a2
AM
450 return false;
451 return true;
95e34ef7
TG
452}
453#endif /* VMS */
454
455/* Manufacture a VMS like time on a unix based system.
456 stolen from obj-vms.c. */
457
458unsigned char *
7fbd5f4e 459get_vms_time_string (unsigned char *tbuf)
95e34ef7 460{
95e34ef7
TG
461#ifndef VMS
462 char *pnt;
463 time_t timeb;
464
465 time (& timeb);
466 pnt = ctime (&timeb);
467 pnt[3] = 0;
468 pnt[7] = 0;
469 pnt[10] = 0;
470 pnt[16] = 0;
471 pnt[24] = 0;
472 sprintf ((char *) tbuf, "%2s-%3s-%s %s",
473 pnt + 8, pnt + 4, pnt + 20, pnt + 11);
474#else
475 struct
476 {
477 int Size;
478 unsigned char *Ptr;
479 } Descriptor;
480 Descriptor.Size = 17;
481 Descriptor.Ptr = tbuf;
482 SYS$ASCTIM (0, &Descriptor, 0, 0);
483#endif /* not VMS */
484
485 vms_debug2 ((6, "vmstimestring:'%s'\n", tbuf));
486
487 return tbuf;
252b5132 488}
4b544b64
TG
489
490/* Create module name from filename (ie, extract the basename and convert it
491 in upper cases). Works on both VMS and UNIX pathes.
492 The result has to be free(). */
493
494char *
0a1b45a2 495vms_get_module_name (const char *filename, bool upcase)
4b544b64
TG
496{
497 char *fname, *fptr;
498 const char *fout;
499
500 /* Strip VMS path. */
501 fout = strrchr (filename, ']');
502 if (fout == NULL)
503 fout = strchr (filename, ':');
504 if (fout != NULL)
505 fout++;
506 else
507 fout = filename;
953b49ed 508
4b544b64
TG
509 /* Strip UNIX path. */
510 fptr = strrchr (fout, '/');
511 if (fptr != NULL)
512 fout = fptr + 1;
953b49ed 513
4b544b64
TG
514 fname = strdup (fout);
515
516 /* Strip suffix. */
517 fptr = strrchr (fname, '.');
518 if (fptr != 0)
519 *fptr = 0;
953b49ed 520
4b544b64
TG
521 /* Convert to upper case and truncate at 31 characters.
522 (VMS object file format restricts module name length to 31). */
523 fptr = fname;
524 for (fptr = fname; *fptr != 0; fptr++)
525 {
526 if (*fptr == ';' || (fptr - fname) >= 31)
07d6d2b8
AM
527 {
528 *fptr = 0;
529 break;
530 }
4b544b64 531 if (upcase)
07d6d2b8 532 *fptr = TOUPPER (*fptr);
4b544b64
TG
533 }
534 return fname;
535}
536
953b49ed
TG
537/* Compared to usual UNIX time_t, VMS time has less limits:
538 - 64 bit (63 bits in fact as the MSB must be 0)
539 - 100ns granularity
540 - epoch is Nov 17, 1858.
541 Here has the constants and the routines used to convert VMS from/to UNIX time.
62a35308
TG
542 The conversion routines don't assume 64 bits arithmetic.
543
544 Here we assume that the definition of time_t is the UNIX one, ie integer
545 type, expressing seconds since the epoch. */
953b49ed
TG
546
547/* UNIX time granularity for VMS, ie 1s / 100ns. */
548#define VMS_TIME_FACTOR 10000000
549
550/* Number of seconds since VMS epoch of the UNIX epoch. */
551#define VMS_TIME_OFFSET 3506716800U
552
553/* Convert a VMS time to a unix time. */
4b544b64
TG
554
555time_t
556vms_time_to_time_t (unsigned int hi, unsigned int lo)
557{
4b544b64
TG
558 unsigned int tmp;
559 unsigned int rlo;
560 int i;
62a35308 561 time_t res;
4b544b64
TG
562
563 /* First convert to seconds. */
953b49ed
TG
564 tmp = hi % VMS_TIME_FACTOR;
565 hi = hi / VMS_TIME_FACTOR;
4b544b64
TG
566 rlo = 0;
567 for (i = 0; i < 4; i++)
568 {
569 tmp = (tmp << 8) | (lo >> 24);
570 lo <<= 8;
571
953b49ed
TG
572 rlo = (rlo << 8) | (tmp / VMS_TIME_FACTOR);
573 tmp %= VMS_TIME_FACTOR;
4b544b64
TG
574 }
575 lo = rlo;
576
577 /* Return 0 in case of overflow. */
62a35308
TG
578 if (hi > 1
579 || (hi == 1 && lo >= VMS_TIME_OFFSET))
953b49ed
TG
580 return 0;
581
582 /* Return 0 in case of underflow. */
62a35308 583 if (hi == 0 && lo < VMS_TIME_OFFSET)
4b544b64
TG
584 return 0;
585
62a35308
TG
586 res = lo - VMS_TIME_OFFSET;
587 if (res <= 0)
588 return 0;
589 return res;
953b49ed
TG
590}
591
592/* Convert a time_t to a VMS time. */
593
594void
595vms_time_t_to_vms_time (time_t ut, unsigned int *hi, unsigned int *lo)
596{
b4e125d9
AM
597 unsigned int val[4];
598 unsigned int tmp[4];
953b49ed
TG
599 unsigned int carry;
600 int i;
601
602 /* Put into val. */
603 val[0] = ut & 0xffff;
604 val[1] = (ut >> 16) & 0xffff;
81c5c866
JK
605 val[2] = sizeof (ut) > 4 ? (ut >> 32) & 0xffff : 0;
606 val[3] = sizeof (ut) > 4 ? (ut >> 48) & 0xffff : 0;
953b49ed
TG
607
608 /* Add offset. */
609 tmp[0] = VMS_TIME_OFFSET & 0xffff;
610 tmp[1] = VMS_TIME_OFFSET >> 16;
611 tmp[2] = 0;
612 tmp[3] = 0;
613 carry = 0;
614 for (i = 0; i < 4; i++)
615 {
616 carry += tmp[i] + val[i];
617 val[i] = carry & 0xffff;
618 carry = carry >> 16;
619 }
620
621 /* Multiply by factor, well first by 10000 and then by 1000. */
622 carry = 0;
623 for (i = 0; i < 4; i++)
624 {
625 carry += val[i] * 10000;
626 val[i] = carry & 0xffff;
627 carry = carry >> 16;
628 }
629 carry = 0;
630 for (i = 0; i < 4; i++)
631 {
632 carry += val[i] * 1000;
633 val[i] = carry & 0xffff;
634 carry = carry >> 16;
635 }
636
637 /* Write the result. */
638 *lo = val[0] | (val[1] << 16);
639 *hi = val[2] | (val[3] << 16);
4b544b64
TG
640}
641
642/* Convert a raw (stored in a buffer) VMS time to a unix time. */
643
644time_t
645vms_rawtime_to_time_t (unsigned char *buf)
646{
647 unsigned int hi = bfd_getl32 (buf + 4);
648 unsigned int lo = bfd_getl32 (buf + 0);
649
650 return vms_time_to_time_t (hi, lo);
651}
953b49ed
TG
652
653void
654vms_get_time (unsigned int *hi, unsigned int *lo)
655{
656#ifdef VMS
657 struct _generic_64 t;
658
659 sys$gettim (&t);
660 *lo = t.gen64$q_quadword;
661 *hi = t.gen64$q_quadword >> 32;
662#else
663 time_t t;
664
665 time (&t);
666 vms_time_t_to_vms_time (t, hi, lo);
667#endif
668}
669
670/* Get the current time into a raw buffer BUF. */
671
672void
673vms_raw_get_time (unsigned char *buf)
674{
675 unsigned int hi, lo;
676
677 vms_get_time (&hi, &lo);
678 bfd_putl32 (lo, buf + 0);
679 bfd_putl32 (hi, buf + 4);
680}