OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [newlib-1.17.0/] [newlib/] [libc/] [sys/] [mmixware/] [open.c] - Blame information for rev 455

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 148 jeremybenn
/* open for MMIXware.
2
 
3
   Copyright (C) 2001, 2002 Hans-Peter Nilsson
4
 
5
   Permission to use, copy, modify, and distribute this software is
6
   freely granted, provided that the above copyright notice, this notice
7
   and the following disclaimer are preserved with no changes.
8
 
9
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
10
   IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
11
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12
   PURPOSE.  */
13
 
14
#include <stdlib.h>
15
#include <fcntl.h>
16
#include <_ansi.h>
17
#include <sys/types.h>
18
#include <sys/stat.h>
19
#include "sys/syscall.h"
20
#include <errno.h>
21
 
22
/* Let's keep the filehandle array here, since this is a primary
23
   initializer of it.  */
24
unsigned char _MMIX_allocated_filehandle[32] =
25
 {
26
   1,
27
   1,
28
   1,
29
   0, 0, 0, 0, 0,
30
   0, 0, 0, 0, 0, 0, 0, 0,
31
   0, 0, 0, 0, 0, 0, 0, 0,
32
   0, 0, 0, 0, 0, 0, 0, 0
33
 };
34
 
35
int
36
_open (const char *path,
37
       int flags, ...)
38
{
39
  long fileno;
40
  unsigned char mode;
41
  long append_contents = 0;
42
  unsigned long prev_contents_size = 0;
43
  char *prev_contents = NULL;
44
  long ret;
45
 
46
  for (fileno = 0;
47
       fileno < (sizeof (_MMIX_allocated_filehandle) /
48
                 sizeof (_MMIX_allocated_filehandle[0]));
49
       fileno++)
50
    if (_MMIX_allocated_filehandle[fileno] == 0)
51
      break;
52
 
53
  if (fileno == (sizeof (_MMIX_allocated_filehandle) /
54
                 sizeof (_MMIX_allocated_filehandle[0])))
55
    {
56
      errno = EMFILE;
57
      return -1;
58
    }
59
 
60
  /* We map this to a fopen call.  The flags parameter is stymied because
61
     we don't support other than these flags.  */
62
  if (flags & ~(O_RDONLY | O_WRONLY | O_RDWR | O_CREAT | O_APPEND | O_TRUNC))
63
    {
64
      UNIMPLEMENTED (("path: %s, flags: %d", path, flags));
65
      errno = ENOSYS;
66
      return -1;
67
    }
68
 
69
  if ((flags & O_ACCMODE) == O_RDONLY)
70
    mode = BinaryRead;
71
  else if ((flags & (O_WRONLY | O_APPEND)) == (O_WRONLY | O_APPEND))
72
    {
73
      mode = BinaryReadWrite;
74
      append_contents = 1;
75
    }
76
  else if ((flags & (O_RDWR | O_APPEND)) == (O_RDWR | O_APPEND))
77
    {
78
      mode = BinaryReadWrite;
79
      append_contents = 1;
80
    }
81
  else if ((flags & (O_WRONLY | O_CREAT)) == (O_WRONLY | O_CREAT)
82
           || (flags & (O_WRONLY | O_TRUNC)) == (O_WRONLY | O_TRUNC))
83
    mode = BinaryWrite;
84
  else if ((flags & (O_RDWR | O_CREAT)) == (O_RDWR | O_CREAT))
85
    mode = BinaryReadWrite;
86
  else if (flags & O_RDWR)
87
    mode = BinaryReadWrite;
88
  else
89
    {
90
      errno = EINVAL;
91
      return -1;
92
    }
93
 
94
  if (append_contents)
95
    {
96
      /* BinaryReadWrite is equal to "w+", so it truncates the file rather
97
         than keeping the contents, as can be imagined if you're looking
98
         for append functionality.  The only way we can keep the contents
99
         so we can append to it, is by first reading in and saving the
100
         contents, then re-opening the file as BinaryReadWrite and write
101
         the previous contents.  This seems to work for the needs of
102
         simple test-programs.  */
103
      long openexist = TRAP3f (SYS_Fopen, fileno, path, BinaryRead);
104
      if (openexist == 0)
105
        {
106
          /* Yes, this file exists, now opened, so let's read it and keep
107
             the contents.  Better have the memory around for this to
108
             work.  */
109
          long seekval = TRAP2f (SYS_Fseek, fileno, -1);
110
 
111
          if (seekval == 0)
112
            {
113
              prev_contents_size = TRAP1f (SYS_Ftell, fileno);
114
 
115
              /* If the file has non-zero size, we have something to
116
                 append to.  */
117
              if (prev_contents_size != 0)
118
                {
119
                  /* Start reading from the beginning.  Ignore the return
120
                     value from this call: we'll notice if we can't read
121
                     as much as we want.  */
122
                  TRAP2f (SYS_Fseek, fileno, 0);
123
 
124
                  prev_contents = malloc (prev_contents_size);
125
                  if (prev_contents != 0)
126
                    {
127
                      /* I don't like the thought of trying to read the
128
                         whole file all at once, disregarding the size,
129
                         because the host system might not support that
130
                         and we'd get funky errors.  Read in 32k at a
131
                         time.  */
132
                      char *ptr = prev_contents;
133
                      unsigned long read_more = prev_contents_size;
134
                      unsigned long chunk_size = 1 << 15;
135
 
136
                      while (read_more >= chunk_size)
137
                        {
138
                          long readval
139
                            = TRAP3f (SYS_Fread, fileno, ptr, chunk_size);
140
 
141
                          if (readval != 0)
142
                            {
143
                              free (prev_contents);
144
                              TRAP1f (SYS_Fclose, fileno);
145
                              errno = EIO;
146
                              return -1;
147
                            }
148
                          read_more -= chunk_size;
149
                          ptr += chunk_size;
150
                        }
151
 
152
                      if (read_more != 0)
153
                        {
154
                          long readval
155
                            = TRAP3f (SYS_Fread, fileno, ptr, read_more);
156
                          if (readval != 0)
157
                            {
158
                              free (prev_contents);
159
                              TRAP1f (SYS_Fclose, fileno);
160
                              errno = EIO;
161
                              return -1;
162
                            }
163
                        }
164
                    }
165
                  else
166
                    {
167
                      /* Malloc of area to copy to failed.  The glibc
168
                         manpage says its open can return ENOMEM due to
169
                         kernel memory failures, so let's do that too
170
                         here.  */
171
                      errno = ENOMEM;
172
                      return -1;
173
                    }
174
                }
175
            }
176
          else
177
            {
178
              /* Seek failed.  Gotta be some I/O error.  */
179
              errno = EIO;
180
              return -1;
181
            }
182
 
183
          TRAP1f (SYS_Fclose, fileno);
184
        }
185
    }
186
 
187
  ret = TRAP3f (SYS_Fopen, fileno, path, mode);
188
  if (ret < 0)
189
    {
190
      /* It's totally unknown what the error was.  We'll just take our
191
         chances and assume ENOENT.  */
192
      errno = ENOENT;
193
      return -1;
194
    }
195
 
196
  if (prev_contents_size != 0)
197
    {
198
      /* Write out the previous contents, a chunk at a time.  Leave the
199
         file pointer at the end of the file.  */
200
      unsigned long write_more = prev_contents_size;
201
      unsigned long chunk_size = 1 << 15;
202
      char *ptr = prev_contents;
203
 
204
      while (write_more >= chunk_size)
205
        {
206
          long writeval
207
            = TRAP3f (SYS_Fwrite, fileno, ptr, chunk_size);
208
          if (writeval != 0)
209
            {
210
              free (prev_contents);
211
              TRAP1f (SYS_Fclose, fileno);
212
              errno = EIO;
213
              return -1;
214
            }
215
          write_more -= chunk_size;
216
          ptr += chunk_size;
217
        }
218
      if (write_more != 0)
219
        {
220
          long writeval
221
            = TRAP3f (SYS_Fwrite, fileno, ptr, write_more);
222
          if (writeval != 0)
223
            {
224
              free (prev_contents);
225
              TRAP1f (SYS_Fclose, fileno);
226
              errno = EIO;
227
              return -1;
228
            }
229
        }
230
 
231
      free (prev_contents);
232
    }
233
 
234
  _MMIX_allocated_filehandle[fileno] = 1;
235
 
236
  return fileno;
237
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.