1/**************************************************************************** 2 * * 3 * GNAT RUN-TIME COMPONENTS * 4 * * 5 * C S T R E A M S * 6 * * 7 * Auxiliary C functions for Interfaces.C.Streams * 8 * * 9 * Copyright (C) 1992-2014, Free Software Foundation, Inc. * 10 * * 11 * GNAT is free software; you can redistribute it and/or modify it under * 12 * terms of the GNU General Public License as published by the Free Soft- * 13 * ware Foundation; either version 3, or (at your option) any later ver- * 14 * sion. GNAT is distributed in the hope that it will be useful, but WITH- * 15 * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * 16 * or FITNESS FOR A PARTICULAR PURPOSE. * 17 * * 18 * As a special exception under Section 7 of GPL version 3, you are granted * 19 * additional permissions described in the GCC Runtime Library Exception, * 20 * version 3.1, as published by the Free Software Foundation. * 21 * * 22 * You should have received a copy of the GNU General Public License and * 23 * a copy of the GCC Runtime Library Exception along with this program; * 24 * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see * 25 * <http://www.gnu.org/licenses/>. * 26 * * 27 * GNAT was originally developed by the GNAT team at New York University. * 28 * Extensive contributions were provided by Ada Core Technologies Inc. * 29 * * 30 ****************************************************************************/ 31 32/* Routines required for implementing routines in Interfaces.C.Streams. */ 33 34#ifndef _LARGEFILE_SOURCE 35#define _LARGEFILE_SOURCE 36#endif 37#define _FILE_OFFSET_BITS 64 38/* the define above will make off_t a 64bit type on GNU/Linux */ 39 40#include <stdio.h> 41#include <sys/types.h> 42 43#ifdef _AIX 44/* needed to avoid conflicting declarations */ 45#include <unistd.h> 46#include <sys/mman.h> 47#endif 48 49#ifdef __vxworks 50#include "vxWorks.h" 51#endif 52 53#ifdef IN_RTS 54#include "tconfig.h" 55#include "tsystem.h" 56#include <sys/stat.h> 57#else 58#include "config.h" 59#include "system.h" 60#endif 61 62#include "adaint.h" 63 64#ifdef __cplusplus 65extern "C" { 66#endif 67 68#ifdef VMS 69#include <unixlib.h> 70#endif 71 72#ifdef linux 73/* Don't use macros on GNU/Linux since they cause incompatible changes between 74 glibc 2.0 and 2.1 */ 75 76#ifdef stderr 77# undef stderr 78#endif 79#ifdef stdin 80# undef stdin 81#endif 82#ifdef stdout 83# undef stdout 84#endif 85 86#endif 87 88/* Don't use macros versions of this functions on VxWorks since they cause 89 imcompatible changes in some VxWorks versions */ 90#ifdef __vxworks 91#undef getchar 92#undef putchar 93#undef feof 94#undef ferror 95#undef fileno 96#endif 97 98/* The _IONBF value in MINGW32 stdio.h is wrong. */ 99#if defined (WINNT) || defined (_WINNT) 100#if OLD_MINGW 101#undef _IONBF 102#define _IONBF 0004 103#endif 104#endif 105 106int 107__gnat_feof (FILE *stream) 108{ 109 return (feof (stream)); 110} 111 112int 113__gnat_ferror (FILE *stream) 114{ 115 return (ferror (stream)); 116} 117 118int 119__gnat_fileno (FILE *stream) 120{ 121 return (fileno (stream)); 122} 123 124/* on some systems, the constants for seek are not defined, if so, then 125 provide the conventional definitions */ 126 127#ifndef SEEK_SET 128#define SEEK_SET 0 /* Set file pointer to offset */ 129#define SEEK_CUR 1 /* Set file pointer to its current value plus offset */ 130#define SEEK_END 2 /* Set file pointer to the size of the file plus offset */ 131#endif 132 133/* if L_tmpnam is not set, use a large number that should be safe */ 134#ifndef L_tmpnam 135#define L_tmpnam 256 136#endif 137 138int __gnat_constant_eof = EOF; 139int __gnat_constant_iofbf = _IOFBF; 140int __gnat_constant_iolbf = _IOLBF; 141int __gnat_constant_ionbf = _IONBF; 142int __gnat_constant_l_tmpnam = L_tmpnam; 143int __gnat_constant_seek_cur = SEEK_CUR; 144int __gnat_constant_seek_end = SEEK_END; 145int __gnat_constant_seek_set = SEEK_SET; 146 147FILE * 148__gnat_constant_stderr (void) 149{ 150 return stderr; 151} 152 153FILE * 154__gnat_constant_stdin (void) 155{ 156 return stdin; 157} 158 159FILE * 160__gnat_constant_stdout (void) 161{ 162 return stdout; 163} 164 165char * 166__gnat_full_name (char *nam, char *buffer) 167{ 168#ifdef RTSS 169 /* RTSS applications have no current-directory notion, so RTSS file I/O 170 requests must use fully qualified path names, such as: 171 c:\temp\MyFile.txt (for a file system object) 172 \\.\MyDevice0 (for a device object) 173 */ 174 if (nam[1] == ':' || nam[0] == '\\') 175 strcpy (buffer, nam); 176 else 177 buffer[0] = '\0'; 178 179#elif defined (__MINGW32__) 180 /* If this is a device file return it as is; 181 under Windows NT a device file ends with ":". */ 182 if (nam[strlen (nam) - 1] == ':') 183 strcpy (buffer, nam); 184 else 185 { 186 char *p; 187 188 _fullpath (buffer, nam, __gnat_max_path_len); 189 190 for (p = buffer; *p; p++) 191 if (*p == '/') 192 *p = '\\'; 193 } 194 195#elif defined (__FreeBSD__) 196 197 /* Use realpath function which resolves links and references to . and .. 198 on those Unix systems that support it. Note that GNU/Linux provides it but 199 cannot handle more than 5 symbolic links in a full name, so we use the 200 getcwd approach instead. */ 201 realpath (nam, buffer); 202 203#elif defined (VMS) 204 strncpy (buffer, __gnat_to_canonical_file_spec (nam), __gnat_max_path_len); 205 206 if (buffer[0] == '/' || strchr (buffer, '!')) /* '!' means decnet node */ 207 strncpy (buffer, __gnat_to_host_file_spec (buffer), __gnat_max_path_len); 208 else 209 { 210 char *nambuffer = alloca (__gnat_max_path_len); 211 212 strncpy (nambuffer, buffer, __gnat_max_path_len); 213 strncpy 214 (buffer, getcwd (buffer, __gnat_max_path_len, 0), __gnat_max_path_len); 215 strncat (buffer, "/", __gnat_max_path_len); 216 strncat (buffer, nambuffer, __gnat_max_path_len); 217 strncpy (buffer, __gnat_to_host_file_spec (buffer), __gnat_max_path_len); 218 } 219 220#elif defined (__vxworks) 221 222 /* On VxWorks systems, an absolute path can be represented (depending on 223 the host platform) as either /dir/file, or device:/dir/file, or 224 device:drive_letter:/dir/file. Use the __gnat_is_absolute_path 225 to verify it. */ 226 227 int length; 228 229 if (__gnat_is_absolute_path (nam, strlen (nam))) 230 strcpy (buffer, nam); 231 232 else 233 { 234 length = __gnat_max_path_len; 235 __gnat_get_current_dir (buffer, &length); 236 strncat (buffer, nam, __gnat_max_path_len - length - 1); 237 } 238 239#else 240 if (nam[0] != '/') 241 { 242 char *p = getcwd (buffer, __gnat_max_path_len); 243 244 if (p == 0) 245 { 246 buffer[0] = '\0'; 247 return 0; 248 } 249 250 251 /* If the name returned is an absolute path, it is safe to append '/' 252 to the path and concatenate the name of the file. */ 253 if (buffer[0] == '/') 254 strcat (buffer, "/"); 255 256 strcat (buffer, nam); 257 } 258 else 259 strcpy (buffer, nam); 260#endif 261 262 return buffer; 263} 264 265#ifdef _WIN32 266 /* On Windows we want to use the fseek/fteel supporting large files. This 267 issue is due to the fact that a long on Win64 is still a 32 bits value */ 268__int64 269__gnat_ftell64 (FILE *stream) 270{ 271 return _ftelli64 (stream); 272} 273 274int 275__gnat_fseek64 (FILE *stream, __int64 offset, int origin) 276{ 277 return _fseeki64 (stream, offset, origin); 278} 279 280#elif defined(linux) || defined(sun) \ 281 || defined (__FreeBSD__) || defined(__APPLE__) 282/* section for platforms having ftello/fseeko */ 283 284__int64 285__gnat_ftell64 (FILE *stream) 286{ 287 return (__int64)ftello (stream); 288} 289 290int 291__gnat_fseek64 (FILE *stream, __int64 offset, int origin) 292{ 293 /* make sure that the offset is not bigger than the OS off_t, if so return 294 with error as this mean that we are trying to handle files larger than 295 2Gb on a patform not supporting it. */ 296 if ((off_t)offset == offset) 297 return fseeko (stream, (off_t) offset, origin); 298 else 299 return -1; 300} 301 302#else 303 304__int64 305__gnat_ftell64 (FILE *stream) 306{ 307 return (__int64)ftell (stream); 308} 309 310int 311__gnat_fseek64 (FILE *stream, __int64 offset, int origin) 312{ 313 /* make sure that the offset is not bigger than the OS off_t, if so return 314 with error as this mean that we are trying to handle files larger than 315 2Gb on a patform not supporting it. */ 316 if ((off_t)offset == offset) 317 return fseek (stream, (off_t) offset, origin); 318 else 319 return -1; 320} 321#endif 322 323#ifdef __cplusplus 324} 325#endif 326