00001 /*-------------------------------------------------------- 00002 * / 00003 * / apeNEXT fcntl.h for OS1 00004 * / 00005 * / $Id: fcntl_os1.h,v 1.8 2005/10/27 20:04:57 morinl Exp $ 00006 * / 00007 * /--------------------------------------------------------*/ 00008 #ifndef __ANEXT_OS1_FCNTL_H__ 00009 #define __ANEXT_OS1_FCNTL_H__ 00010 00011 #include <nlibc.h> 00012 00013 #include <stddef.h> 00014 #include <sys/types.h> 00015 #include <sys/stat.h> 00016 #include <os1/defs_os1.h> 00017 #include <errno.h> 00018 00019 // open/fcntl mode values 00020 // (same as in glibc 2.3) 00021 #define O_RDONLY 00 00022 #define O_WRONLY 01 00023 #define O_RDWR 02 00024 #define O_CREAT 0100 00025 #define O_TRUNC 01000 00026 #define O_APPEND 02000 00027 00028 typedef int ssize_t; 00029 00030 /*---------------------------------------------------------------------- 00031 | NAME 00032 | 00033 | open, creat - open and possibly create a file or device 00034 | 00035 | SYNOPSIS 00036 | 00037 | 00038 | #include <sys/types.h> 00039 | #include <sys/stat.h> 00040 | #include <fcntl.h> 00041 | 00042 | int open(const char *pathname, int flags); 00043 | int open(const char *pathname, int flags, mode_t mode); 00044 | int creat(const char *pathname, mode_t mode); 00045 | 00046 | 00047 | DESCRIPTION 00048 | 00049 | The open() system call is used to convert a pathname into a file 00050 | descriptor (a small, non-negative integer for use in subsequent I/O as 00051 | with read, write, etc.). When the call is successful, the file 00052 | descriptor returned will be the lowest file descriptor not currently 00053 | open for the process. This call creates a new open file, not shared 00054 | with any other process. (But shared open files may arise via the 00055 | fork(2) system call.) The file offset is set to the 00056 | beginning of the file. 00057 | 00058 | The parameter flags is one of O_RDONLY, O_WRONLY or O_RDWR which 00059 | request opening the file read-only, write-only or read/write, 00060 | respectively. When opening a file for writing, the flag O_APPEND 00061 | will cause the file pointer to be positioned at the end of the 00062 | file. 00063 | 00064 | apeNEXT-specific changes: 00065 | - The flag O_CREAT is silently ignored. 00066 | - The mode parameter is silently ignored. 00067 | 00068 | creat() is equivalent to open with flags equal to 00069 | O_CREAT|O_WRONLY|O_TRUNC. 00070 +----------------------------------------------------------------------*/ 00071 #ifndef __HAS_MAIN 00072 extern int open(const char *pathname, int flags, ...); 00073 #else 00074 #if !defined(__cflow_processed) || defined(_uses_open_fcntl_os1_h) 00075 int open(const char *pathname, int flags, ...) 00076 { int modebits = 0, fi, fileno; 00077 #pragma localmem 00078 00079 asm("\t!! start open()\n"); 00080 /* check if number of open files exceeded */ 00081 if( __n_files == __NLCC_OS1_MAX_FILES__ ) { 00082 errno = EMFILE; 00083 return -1; 00084 } 00085 for( fi=0; fi<__NLCC_OS1_MAX_FILES__; fi++ ) { 00086 if( __files[fi].fd == 0 ) { 00087 fileno = __NLCC_BASE_FD + fi; 00088 break; 00089 } 00090 } 00091 // unless we miscounted, fi _is_ now < __NLCC_OS1_MAX_FILES__ 00092 00093 // convert mode flags into OS1 mode value 00094 // return -1 for invalid mode 00095 { int flags3 = (flags & 0x3); 00096 where( flags3==O_RDONLY ) 00097 asm("\t$io_setmode(%0, $SYS_IOMODE_R)" : "=r" (modebits) ); 00098 where( flags3==O_WRONLY ) { 00099 where( flags & O_APPEND ) { 00100 asm("\t$io_setmode(%0, $SYS_IOMODE_A)" : "=r" (modebits) ); 00101 } else { 00102 asm("\t$io_setmode(%0, $SYS_IOMODE_W)" : "=r" (modebits) ); 00103 } 00104 } 00105 where( flags3==O_RDWR ) { 00106 where( flags & O_APPEND ) { 00107 asm("\t$io_setmode(%0, $SYS_IOMODE_APLUS)" : "=r" (modebits) ); 00108 } else { 00109 asm("\t$io_setmode(%0, $SYS_IOMODE_WPLUS)" : "=r" (modebits) ); 00110 } 00111 } 00112 } 00113 00114 if( ! modebits ) { 00115 errno = EINVAL; 00116 return (-1); 00117 } 00118 00119 00120 asm("\t$io_start\n"); 00121 asm("\t$io_fopenp( 0.%0, %1, 0.%2, $SYS_IODEV_MEM , \"\")\n" 00122 : : "r" (fileno), "r" (modebits), "r" (pathname) ); 00123 asm("\t$io_end\n"); 00124 00125 // check OS return code and set errno if necessary 00126 { vector int sys_rval; 00127 00128 asm("\tlmtr %0 $MEM_SYS_RVAL\n" : "=r" (sys_rval) ); 00129 asm("\t!! end open()\n"); 00130 if( sys_rval.lo ) { 00131 errno = sys_rval.hi; 00132 return (-1); 00133 } else { 00134 __n_files++; 00135 __files[fi].fd = fileno; 00136 __files[fi].mode = modebits; 00137 return fileno; 00138 } 00139 } 00140 } 00141 #endif // open() 00142 #endif 00143 00144 #if !defined(__cflow_processed) || defined(_uses_creat_fcntl_os1_h) 00145 inline 00146 int creat(const char *pathname, mode_t mode) 00147 { 00148 return open(pathname, O_CREAT|O_WRONLY|O_TRUNC ); 00149 } 00150 #endif // creat() 00151 00152 /*--------------------------------------------------------------------- 00153 | NAME 00154 | read - read from a file descriptor 00155 | 00156 | SYNOPSIS 00157 | #include <unistd.h> 00158 | 00159 | ssize_t read(int fd, void *buf, size_t count); 00160 | 00161 | DESCRIPTION 00162 | read() attempts to read up to count bytes from file 00163 | descriptor fd into the buffer starting at buf. 00164 | 00165 | If count is zero, read() returns zero and has no other 00166 | results. If count is greater than SSIZE_MAX, the result 00167 | is unspecified. 00168 | 00169 | 00170 | RETURN VALUE 00171 | On success, the number of bytes read is returned (zero 00172 | indicates end of file), and the file position is advanced 00173 | by this number. It is not an error if this number is 00174 | smaller than the number of bytes requested; this may hap- 00175 | pen for example because fewer bytes are actually available 00176 | right now (maybe because we were close to end-of-file, or 00177 | because we are reading from a pipe, or from a terminal), 00178 | or because read() was interrupted by a signal. On error, 00179 | -1 is returned, and errno is set appropriately. In this 00180 | case it is left unspecified whether the file position (if 00181 | any) changes. 00182 | 00183 | ERRORS 00184 | EINTR The call was interrupted by a signal before any 00185 | data was read. 00186 | 00187 | EAGAIN Non-blocking I/O has been selected using O_NONBLOCK 00188 | and no data was immediately available for reading. 00189 | 00190 | EIO I/O error. This will happen for example when the 00191 | process is in a background process group, tries to 00192 | read from its controlling tty, and either it is 00193 | ignoring or blocking SIGTTIN or its process group 00194 | is orphaned. It may also occur when there is a 00195 | low-level I/O error while reading from a disk or 00196 | tape. 00197 | 00198 | EISDIR fd refers to a directory. 00199 | 00200 | EBADF fd is not a valid file descriptor or is not open 00201 | for reading. 00202 | 00203 | EINVAL fd is attached to an object which is unsuitable for 00204 | reading. 00205 | 00206 | EFAULT buf is outside your accessible address space. 00207 | 00208 | Other errors may occur, depending on the object connected 00209 | to fd. POSIX allows a read that is interrupted after 00210 | reading some data to return -1 (with errno set to EINTR) 00211 | or to return the number of bytes already read. 00212 +----------------------------------------------------------------------*/ 00213 #ifndef __HAS_MAIN 00214 extern ssize_t read(int fd, void *buf, size_t count); 00215 #else 00216 #if !defined(__cflow_processed) || defined(_uses_read_fcntl_os1_h) 00217 ssize_t read(int fd, void *buf, size_t count) 00218 { 00219 vector int sys_rval; 00220 ssize_t result; 00221 00222 asm("\t!! start read()\n"); 00223 00224 asm("\t$io_start\n" 00225 "\t\\equ $cmd $SYS_IOCMD_BRD\n" 00226 "\t\\equ $fmt $SYS_IOFMT_BIN\n" 00227 "\t\\equ $sep $SYS_IOPSEP_NOP\n" 00228 "\t\\equ $rdflg $SYS_IORDFLG_NOP\n" 00229 "\t\\equ $dev $SYS_IODEV_MEM\n" 00230 "\t\\equ $l %1>>4\n" 00231 "\t\\equ $bs $SYS_IOBS_V\n" 00232 "\t$io_fd( 0.%2 )\n" 00233 "\t$io_slice_all\n" 00234 "\t$io_packet($cmd, <$fmt .or. $sep>, $rdflg, $dev, $l, $bs, 0.%3)\n" 00235 "\t$io_end\n" 00236 "\tlmtr %0 $MEM_SYS_RVAL\n" 00237 "\t!! end read()\n" 00238 : "=r" (sys_rval) 00239 : "r" (count), "r" (fd), "r" (buf) ); 00240 00241 result = sys_rval.hi << 4; // number of bytes 00242 where (sys_rval.lo) { 00243 errno = sys_rval.hi; 00244 result = -1; 00245 } 00246 00247 return result; 00248 } 00249 #endif // read() 00250 #endif // Has Main 00251 /*--------------------------------------------------------------------- 00252 | NAME 00253 | write - write to a file descriptor 00254 | 00255 | SYNOPSIS 00256 | #include <unistd.h> 00257 | 00258 | ssize_t write(int fd, const void *buf, size_t count); 00259 | 00260 | DESCRIPTION 00261 | write writes up to count bytes to the file referenced by 00262 | the file descriptor fd from the buffer starting at buf. 00263 | POSIX requires that a read() which can be proved to occur 00264 | after a write() has returned returns the new data. Note 00265 | that not all file systems are POSIX conforming. 00266 | 00267 | RETURN VALUE 00268 | On success, the number of bytes written are returned (zero 00269 | indicates nothing was written). On error, -1 is returned, 00270 | and errno is set appropriately. If count is zero and the 00271 | file descriptor refers to a regular file, 0 will be 00272 | returned without causing any other effect. For a special 00273 | file, the results are not portable. 00274 | 00275 | ERRORS 00276 | EBADF fd is not a valid file descriptor or is not open 00277 | for writing. 00278 | 00279 | EINVAL fd is attached to an object which is unsuitable for 00280 | writing. 00281 | 00282 | EFAULT buf is outside your accessible address space. 00283 | 00284 | EPIPE fd is connected to a pipe or socket whose reading 00285 | end is closed. When this happens the writing pro- 00286 | cess will receive a SIGPIPE signal; if it catches, 00287 | blocks or ignores this the error EPIPE is returned. 00288 | 00289 | EAGAIN Non-blocking I/O has been selected using O_NONBLOCK 00290 | and the write would block. 00291 | 00292 | EINTR The call was interrupted by a signal before any 00293 | data was written. 00294 | 00295 | ENOSPC The device containing the file referred to by fd 00296 | has no room for the data. 00297 | 00298 | EIO A low-level I/O error occurred while modifying the 00299 | inode. 00300 | 00301 | Other errors may occur, depending on the object connected 00302 | to fd. 00303 +----------------------------------------------------------------------*/ 00304 00305 #ifndef __HAS_MAIN 00306 extern ssize_t write(int fd, void *buf, size_t count); 00307 #else 00308 #if !defined(__cflow_processed) || defined(_uses_write_fcntl_os1_h) 00309 ssize_t write(int fd, void *buf, size_t count) 00310 { 00311 vector int sys_rval; 00312 ssize_t result; 00313 00314 asm("\t!! start write()\n"); 00315 00316 asm("\t$io_start\n" 00317 "\t\\equ $cmd $SYS_IOCMD_GWR\n" 00318 "\t\\equ $fmt $SYS_IOFMT_BIN\n" 00319 "\t\\equ $sep $SYS_IOPSEP_NOP\n" 00320 "\t\\equ $rdflg $SYS_IORDFLG_NOP\n" 00321 "\t\\equ $dev $SYS_IODEV_MEM\n" 00322 "\t\\equ $l %1>>4\n" 00323 "\t\\equ $bs $SYS_IOBS_V\n" 00324 "\t$io_fd( 0.%2 )\n" 00325 "\t$io_slice_all\n" 00326 "\t$io_packet($cmd, <$fmt .or. $sep>, $rdflg, $dev, $l, $bs, 0.%3)\n" 00327 "\t$io_end\n" 00328 "\tlmtr %0 $MEM_SYS_RVAL\n" 00329 "\t!! end write()\n" 00330 : "=r" (sys_rval) 00331 : "r" (count), "r" (fd), "r" (buf) ); 00332 00333 result = sys_rval.hi << 4; // number of bytes 00334 where (sys_rval.lo) { 00335 errno = sys_rval.hi; 00336 result = -1; 00337 } 00338 00339 return result; 00340 } 00341 #endif // write() 00342 #endif // Has Main 00343 00344 00345 /*---------------------------------------------------------------------- 00346 | NAME 00347 | close - close a file descriptor 00348 | 00349 | SYNOPSIS 00350 | #include <unistd.h> 00351 | 00352 | int close(int fd); 00353 | 00354 | DESCRIPTION 00355 | close closes a file descriptor, so that it no longer 00356 | refers to any file and may be reused. Any locks held on 00357 | the file it was associated with, and owned by the process, 00358 | are removed (regardless of the file descriptor that was 00359 | used to obtain the lock). 00360 | 00361 | If fd is the last copy of a particular file descriptor the 00362 | resources associated with it are freed; if the descriptor 00363 | was the last reference to a file which has been removed 00364 | using unlink(2) the file is deleted. 00365 | 00366 | RETURN VALUE 00367 | close returns zero on success, or -1 if an error occurred. 00368 | 00369 | ERRORS 00370 | EBADF fd isn't a valid open file descriptor. 00371 | 00372 | EINTR The close() call was interrupted by a signal. 00373 | 00374 | EIO An I/O error occurred. 00375 | 00376 +-----------------------------------------------------------------------*/ 00377 #ifndef __HAS_MAIN 00378 extern int close( int fd ); 00379 #else 00380 #if !defined(__cflow_processed) || defined(_uses_close_fcntl_os1_h) 00381 int close( int fd ) 00382 { 00383 int nf; 00384 vector int sys_rval; 00385 00386 for(nf=0; nf<__NLCC_OS1_MAX_FILES__; nf++ ) { 00387 if( __files[nf].fd == fd ) 00388 break; 00389 } 00390 if( nf == __NLCC_OS1_MAX_FILES__ ) { 00391 errno = EBADF; 00392 return -1; 00393 } 00394 00395 asm("\t$io_start\n" 00396 "\t$io_fclose(0.%1)\n" 00397 "\t$io_end\n" 00398 "\tlmtr %0 $MEM_SYS_RVAL\n" 00399 : "=r" (sys_rval) : "r" (fd)); 00400 00401 if (sys_rval.lo) { 00402 errno = sys_rval.hi; 00403 return -1; 00404 } 00405 00406 __files[nf].fd = 0; 00407 return 0; 00408 } 00409 #endif // close() 00410 #endif // Has Main 00411 00412 /*---------------------------------------------------------------------- 00413 | NAME 00414 | lseek - reposition read/write file offset 00415 | 00416 | SYNOPSIS 00417 | #include <sys/types.h> 00418 | #include <unistd.h> 00419 | 00420 | off_t lseek(int fildes, off_t offset, int whence); 00421 | 00422 | DESCRIPTION 00423 | The lseek function repositions the offset of the file 00424 | descriptor fildes to the argument offset according to the 00425 | directive whence as follows: 00426 | 00427 | SEEK_SET 00428 | The offset is set to offset bytes. 00429 | 00430 | SEEK_CUR 00431 | The offset is set to its current location plus off- 00432 | set bytes. 00433 | 00434 | SEEK_END 00435 | The offset is set to the size of the file plus off- 00436 | set bytes. 00437 | 00438 | The lseek function allows the file offset to be set beyond 00439 | the end of the existing end-of-file of the file. If data 00440 | is later written at this point, subsequent reads of the 00441 | data in the gap return bytes of zeros (until data is actu- 00442 | ally written into the gap). 00443 | 00444 | RETURN VALUE 00445 | Upon successful completion, lseek returns the resulting 00446 | offset location as measured in bytes from the beginning of 00447 | the file. Otherwise, a value of (off_t)-1 is returned and 00448 | errno is set to indicate the error. 00449 | 00450 | ERRORS 00451 | EBADF Fildes is not an open file descriptor. 00452 | 00453 | ESPIPE Fildes is associated with a pipe, socket, or FIFO. 00454 | 00455 | EINVAL Whence is not a proper value. 00456 +----------------------------------------------------------------------*/ 00457 // The possibilities for the third argument to `fseek'. 00458 // These values should not be changed. 00459 #ifndef SEEK_SET 00460 #define SEEK_SET 0 /* Seek from beginning of file. */ 00461 #define SEEK_CUR 1 /* Seek from current position. */ 00462 #define SEEK_END 2 /* Seek from end of file. */ 00463 #endif 00464 00465 #if !defined(__cflow_processed) || defined(_uses_lseek_fcntl_os1_h) 00466 inline off_t lseek(int fildes, off_t offset, int whence) 00467 { 00468 int sys_whence; 00469 vector int sys_rval; 00470 off_t result; 00471 00472 asm("\t!! begin lseek()\n"); 00473 00474 if (fildes < 0 || fildes > __NLCC_OS1_MAX_FILES__+40) { 00475 errno = EBADF; 00476 return (off_t) -1; 00477 } 00478 00479 sys_whence = -2; 00480 where (whence == SEEK_SET) 00481 asm("$sys_setwhence(%0, $SYS_FSE_SET)\n" : "=r" (sys_whence) ); 00482 where (whence == SEEK_CUR) 00483 asm("$sys_setwhence(%0, $SYS_FSE_CUR)\n" : "=r" (sys_whence) ); 00484 where (whence == SEEK_END) 00485 asm("$sys_setwhence(%0, $SYS_FSE_END)\n" : "=r" (sys_whence) ); 00486 if (sys_whence < 0) { 00487 errno = EINVAL; 00488 return (off_t) -1; 00489 } 00490 00491 asm("\t$sys_fseek( 0.%0, 0.%1, %2 )\n" 00492 : : "r" (fildes), "r" (offset), "r" (sys_whence)); 00493 asm("\tlmtr %0 $MEM_SYS_RVAL\n" : "=r" (sys_rval)); 00494 asm("\t!! end lseek()\n"); 00495 00496 result = sys_rval.hi; 00497 where ( sys_rval.lo ) { 00498 errno = sys_rval.hi; 00499 result = (off_t) -1; 00500 } 00501 00502 return result; 00503 } 00504 #endif // lseek() 00505 00506 00507 00508 #endif // __ANEXT_OS1_FCNTL_H__