]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/te-vms.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / gas / config / te-vms.c
CommitLineData
b11d79f2 1/* te-vms.c -- Utilities for VMS.
250d07de 2 Copyright (C) 2009-2021 Free Software Foundation, Inc.
01e1a5bc
NC
3
4 Written by Douglas B Rupp <rupp@gnat.com>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
19
b11d79f2
TG
20#include "as.h"
21#include "te-vms.h"
01e1a5bc 22
33eaf5de 23/* The purpose of the two alternate versions below is to have one that
efde2f2c
NC
24 works for native VMS and one that works on an NFS mounted filesystem
25 (Unix Server/VMS client). The main issue being to generate the special
26 VMS file timestamps for the debug info. */
27
01e1a5bc
NC
28#ifdef VMS
29#define __NEW_STARLET 1
30#include <vms/starlet.h>
31#include <vms/rms.h>
32#include <vms/atrdef.h>
33#include <vms/fibdef.h>
34#include <vms/stsdef.h>
35#include <vms/iodef.h>
36#include <vms/fatdef.h>
37#include <errno.h>
38#include <vms/descrip.h>
39#include <string.h>
40#include <unixlib.h>
41
42#define MAXPATH 256
43
44/* Descrip.h doesn't have everything... */
45typedef struct fibdef * __fibdef_ptr32 __attribute__ (( mode (SI) ));
46
47struct dsc$descriptor_fib
48{
49 unsigned int fib$l_len;
50 __fibdef_ptr32 fib$l_addr;
51};
52
53/* I/O Status Block. */
54struct IOSB
55{
56 unsigned short status, count;
57 unsigned int devdep;
58};
59
60static char *tryfile;
61
62/* Variable length string. */
63struct vstring
64{
65 short length;
66 char string[NAM$C_MAXRSS+1];
67};
68
69static char filename_buff [MAXPATH];
70static char vms_filespec [MAXPATH];
71
72/* Callback function for filespec style conversion. */
73
74static int
75translate_unix (char *name, int type ATTRIBUTE_UNUSED)
76{
77 strncpy (filename_buff, name, MAXPATH);
78 filename_buff [MAXPATH - 1] = (char) 0;
79 return 0;
80}
81
82/* Wrapper for DECC function that converts a Unix filespec
83 to VMS style filespec. */
84
85static char *
86to_vms_file_spec (char *filespec)
87{
88 strncpy (vms_filespec, "", MAXPATH);
89 decc$to_vms (filespec, translate_unix, 1, 1);
90 strncpy (vms_filespec, filename_buff, MAXPATH);
91
92 vms_filespec [MAXPATH - 1] = (char) 0;
93
94 return vms_filespec;
95}
96
efde2f2c
NC
97#else /* not VMS */
98
99#define _BSD_SOURCE 1
01e1a5bc
NC
100#include <sys/stat.h>
101#include <time.h>
efde2f2c
NC
102
103#define VMS_EPOCH_OFFSET 35067168000000000LL
104#define VMS_GRANULARITY_FACTOR 10000000
105
106#endif /* VMS */
01e1a5bc
NC
107
108/* Return VMS file date, size, format, version given a name. */
109
b11d79f2
TG
110static int
111vms_file_stats_name (const char *dirname,
112 const char *filename,
01e1a5bc
NC
113 long long *cdt,
114 long *siz,
115 char *rfo,
116 int *ver)
117{
e1fa0163
NC
118 char * fullname;
119
01e1a5bc
NC
120#ifdef VMS
121 struct FAB fab;
122 struct NAM nam;
123
124 unsigned long long create;
125 FAT recattr;
126 char ascnamebuff [256];
127
128 ATRDEF atrlst[]
129 = {
130 { ATR$S_CREDATE, ATR$C_CREDATE, &create },
131 { ATR$S_RECATTR, ATR$C_RECATTR, &recattr },
132 { ATR$S_ASCNAME, ATR$C_ASCNAME, &ascnamebuff },
133 { 0, 0, 0}
134 };
135
136 FIBDEF fib;
137 struct dsc$descriptor_fib fibdsc = {sizeof (fib), (void *) &fib};
138
139 struct IOSB iosb;
140
141 long status;
142 unsigned short chan;
143
144 struct vstring file;
145 struct dsc$descriptor_s filedsc
146 = {NAM$C_MAXRSS, DSC$K_DTYPE_T, DSC$K_CLASS_S, (void *) file.string};
147 struct vstring device;
148 struct dsc$descriptor_s devicedsc
149 = {NAM$C_MAXRSS, DSC$K_DTYPE_T, DSC$K_CLASS_S, (void *) device.string};
150 struct vstring result;
151 struct dsc$descriptor_s resultdsc
152 = {NAM$C_MAXRSS, DSC$K_DTYPE_VT, DSC$K_CLASS_VS, (void *) result.string};
153
154 if (strcmp (filename, "<internal>") == 0
155 || strcmp (filename, "<built-in>") == 0)
156 {
157 if (cdt)
158 *cdt = 0;
159
160 if (siz)
161 *siz = 0;
162
163 if (rfo)
164 *rfo = 0;
165
166 if (ver)
167 *ver = 0;
168
169 return 0;
170 }
171
e1fa0163 172 fullname = concat (dirname, filename, NULL);
b11d79f2 173 tryfile = to_vms_file_spec (fullname);
01e1a5bc
NC
174
175 /* Allocate and initialize a FAB and NAM structures. */
176 fab = cc$rms_fab;
177 nam = cc$rms_nam;
178
179 nam.nam$l_esa = file.string;
180 nam.nam$b_ess = NAM$C_MAXRSS;
181 nam.nam$l_rsa = result.string;
182 nam.nam$b_rss = NAM$C_MAXRSS;
183 fab.fab$l_fna = tryfile;
184 fab.fab$b_fns = strlen (tryfile);
185 fab.fab$l_nam = &nam;
186
187 /* Validate filespec syntax and device existence. */
188 status = SYS$PARSE (&fab, 0, 0);
189 if ((status & 1) != 1)
e1fa0163
NC
190 {
191 free (fullname);
192 return 1;
193 }
01e1a5bc
NC
194
195 file.string[nam.nam$b_esl] = 0;
196
197 /* Find matching filespec. */
198 status = SYS$SEARCH (&fab, 0, 0);
199 if ((status & 1) != 1)
e1fa0163
NC
200 {
201 free (fullname);
202 return 1;
203 }
01e1a5bc
NC
204
205 file.string[nam.nam$b_esl] = 0;
206 result.string[result.length=nam.nam$b_rsl] = 0;
207
208 /* Get the device name and assign an IO channel. */
209 strncpy (device.string, nam.nam$l_dev, nam.nam$b_dev);
210 devicedsc.dsc$w_length = nam.nam$b_dev;
211 chan = 0;
212 status = SYS$ASSIGN (&devicedsc, &chan, 0, 0, 0);
213 if ((status & 1) != 1)
e1fa0163
NC
214 {
215 free (fullname);
216 return 1;
217 }
01e1a5bc
NC
218
219 /* Initialize the FIB and fill in the directory id field. */
220 memset (&fib, 0, sizeof (fib));
221 fib.fib$w_did[0] = nam.nam$w_did[0];
222 fib.fib$w_did[1] = nam.nam$w_did[1];
223 fib.fib$w_did[2] = nam.nam$w_did[2];
224 fib.fib$l_acctl = 0;
225 fib.fib$l_wcc = 0;
226 strcpy (file.string, (strrchr (result.string, ']') + 1));
227 filedsc.dsc$w_length = strlen (file.string);
228 result.string[result.length = 0] = 0;
229
230 /* Open and close the file to fill in the attributes. */
231 status
232 = SYS$QIOW (0, chan, IO$_ACCESS|IO$M_ACCESS, &iosb, 0, 0,
233 &fibdsc, &filedsc, &result.length, &resultdsc, &atrlst, 0);
234 if ((status & 1) != 1)
e1fa0163
NC
235 {
236 free (fullname);
237 return 1;
238 }
239
01e1a5bc 240 if ((iosb.status & 1) != 1)
e1fa0163
NC
241 {
242 free (fullname);
243 return 1;
244 }
01e1a5bc
NC
245
246 result.string[result.length] = 0;
247 status = SYS$QIOW (0, chan, IO$_DEACCESS, &iosb, 0, 0, &fibdsc, 0, 0, 0,
248 &atrlst, 0);
249 if ((status & 1) != 1)
e1fa0163
NC
250 {
251 free (fullname);
252 return 1;
253 }
254
01e1a5bc 255 if ((iosb.status & 1) != 1)
e1fa0163
NC
256 {
257 free (fullname);
258 return 1;
259 }
01e1a5bc
NC
260
261 /* Deassign the channel and exit. */
262 status = SYS$DASSGN (chan);
263 if ((status & 1) != 1)
e1fa0163
NC
264 {
265 free (fullname);
266 return 1;
267 }
01e1a5bc
NC
268
269 if (cdt) *cdt = create;
270 if (siz) *siz = (512 * 65536 * recattr.fat$w_efblkh) +
271 (512 * (recattr.fat$w_efblkl - 1)) +
272 recattr.fat$w_ffbyte;
273 if (rfo) *rfo = recattr.fat$v_rtype;
efde2f2c
NC
274 if (ver) *ver = strtol (strrchr (ascnamebuff, ';') + 1, 0, 10);
275#else /* not VMS */
01e1a5bc 276
01e1a5bc 277 struct stat buff;
efde2f2c
NC
278 struct tm *ts;
279 long long gmtoff, secs, nsecs;
01e1a5bc 280
e1fa0163 281 fullname = concat (dirname, filename, NULL);
b11d79f2
TG
282
283 if ((stat (fullname, &buff)) != 0)
e1fa0163
NC
284 {
285 free (fullname);
286 return 1;
287 }
01e1a5bc
NC
288
289 if (cdt)
290 {
efde2f2c
NC
291 ts = localtime (& buff.st_mtime);
292
293#ifdef HAVE_TM_GMTOFF
294 gmtoff = ts->tm_gmtoff;
295#else
296 {
297 extern long timezone;
298
299 if (ts->tm_isdst == 1)
300 gmtoff = - (timezone - 3600);
301 else
302 gmtoff = - timezone;
303 }
304#endif
305
306#ifdef HAVE_ST_MTIM_TV_SEC
307 secs = buff.st_mtim.tv_sec;
308#else
309 secs = buff.st_mtime;
310#endif
311
312#ifdef HAVE_ST_MTIM_TV_NSEC
313 nsecs = buff.st_mtim.tv_nsec;
314#else
315 nsecs = 0;
316#endif
317
318 /* VMS timestamps are stored in local time to 100 nsec accuracy, but by
319 experiment I found timestamps truncated to (at least) microseconds
320 on an NFS mounted filesystem, hence the adjustment below. DBR. */
321 *cdt = ((secs + gmtoff) * VMS_GRANULARITY_FACTOR)
322 + (nsecs / 1000 * 10) + VMS_EPOCH_OFFSET;
01e1a5bc
NC
323 }
324
325 if (siz)
326 *siz = buff.st_size;
327
328 if (rfo)
329 *rfo = 2; /* Stream LF format. */
330
efde2f2c
NC
331 /* Returning a file version of 0 is never correct for debug info, version 1
332 will be correct if file editing is done only on the Unix side. If editing
333 is done on the VMS side, then its TBD. */
01e1a5bc 334 if (ver)
efde2f2c
NC
335 *ver = 1;
336#endif /* VMS */
01e1a5bc 337
e1fa0163 338 free (fullname);
01e1a5bc 339 return 0;
01e1a5bc
NC
340}
341
b11d79f2
TG
342bfd_uint64_t
343vms_dwarf2_file_time_name (const char *filename, const char *dirname)
344{
345 long long cdt;
346
347 if (vms_file_stats_name (dirname, filename, &cdt, 0, 0, 0) == 0)
348 return cdt;
349 else
350 return 0;
351}
352
353long
354vms_dwarf2_file_size_name (const char *filename, const char *dirname)
355{
356 long siz;
357
358 if (vms_file_stats_name (dirname, filename, 0, &siz, 0, 0) == 0)
359 return siz;
360 else
361 return 0;
362}
363
364/* VMS debugger needs the filename with version appended. */
365/* Longest filename on VMS is 255 characters. Largest version is 32768. */
366char *
367vms_dwarf2_file_name (const char *filename, const char *dirname)
368{
369 int ver;
370 static char buff [255 + 7];
371
372 vms_file_stats_name (dirname, filename, 0, 0, 0, &ver);
3739860c 373 snprintf (buff, 255 + 7, "%s;%d", filename, ver);
b11d79f2
TG
374 return buff;
375}