00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 #include <mutex.h>
00041 #include <assert.h>
00042 #include <sys/types.h>
00043 #include <sys/stat.h>
00044 #include <fcntl.h>
00045 #include <unistd.h>
00046 #include <string.h>
00047 #include <errno.h>
00048 #include <cmplrs/fio.h>
00049 #include "fio_direct_io.h"
00050 #include <cmplrs/f_errno.h>
00051
00052 typedef struct {
00053
00054 XINT64 open_l_file;
00055
00056 XINT64 actual_l_file;
00057 XINT64 sector_l_file;
00058 unsigned long mode;
00059 char *buffer;
00060 XINT l_buffer;
00061
00062 XINT l_data;
00063
00064
00065 XINT64 l_disk;
00066 int flags;
00067 int sector;
00068 long lseek;
00069 long position;
00070 } file_info;
00071
00072
00073
00074
00075 #define _Open_l_file Direct[fd].open_l_file
00076 #define _Actual_l_file Direct[fd].actual_l_file
00077 #define _Sector_l_file Direct[fd].sector_l_file
00078 #define _Mode Direct[fd].mode
00079 #define _Buffer Direct[fd].buffer
00080 #define _L_buffer Direct[fd].l_buffer
00081 #define _L_data Direct[fd].l_data
00082 #define _L_disk Direct[fd].l_disk
00083 #define _Flags Direct[fd].flags
00084 #define _Sector Direct[fd].sector
00085 #define _Seek_pos Direct[fd].lseek
00086 #define _Current_pos Direct[fd].position
00087
00088 #define SMALL_DATA_ITEM 512
00089
00090 static file_info *Direct = NULL;
00091 static int Direct_size = 0;
00092
00093 enum {
00094 NEW,
00095 OLD,
00096 UNKNOWN
00097 };
00098
00099 enum {
00100 FALSE,
00101 TRUE
00102 };
00103
00104 #define EMPTY_BIT 0x1
00105 #define CLEAR_EMPTY_BIT {Direct[fd].flags &= (~EMPTY_BIT);}
00106 #define SET_EMPTY_BIT {Direct[fd].flags |= EMPTY_BIT;}
00107 #define IS_EMPTY (Direct[fd].flags & EMPTY_BIT)
00108
00109 #define FLUSH_BIT 0x2
00110 #define CLEAR_FLUSH_BIT {Direct[fd].flags &= (~FLUSH_BIT);}
00111 #define SET_FLUSH_BIT {Direct[fd].flags |= FLUSH_BIT;}
00112 #define MUST_FLUSH (Direct[fd].flags & FLUSH_BIT)
00113
00114 #define DIRECT_BIT 0x4
00115 #define CLEAR_DIRECT_BIT {Direct[fd].flags &= (~DIRECT_BIT);}
00116 #define SET_DIRECT_BIT {Direct[fd].flags |= DIRECT_BIT;}
00117 #define IS_DIRECT (Direct[fd].flags & DIRECT_BIT)
00118
00119 #define max(a,b) (((a)>(b))?(a):(b))
00120 #define min(a,b) (((a)<(b))?(a):(b))
00121 #define DEFAULT (64*1024)
00122
00123 static int d_mem;
00124 static int d_maxiosz;
00125
00126 #define MILLION (1024*1024)
00127 #define CEILING MILLION
00128
00129 #define CROSSOVER (MILLION/2)
00130
00131 #define LARGE_CHUNK (64*1024)
00132
00133
00134
00135
00136 XINT
00137 get_buffer_size()
00138 {
00139 int bufsiz;
00140 char *p;
00141
00142 bufsiz = DEFAULT;
00143 if ((p = getenv ("FORTRAN_BUFFER_SIZE")) != NULL) {
00144 bufsiz = atol (p)*4;
00145 }
00146 return (bufsiz);
00147 }
00148
00149
00150
00151 int _fio_du_open(char *file_name, char *type, int dupopen, int dup_fd )
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179 {
00180
00181 #define MILLION (1024*1024)
00182 #define CEILING MILLION
00183
00184
00185 int fd;
00186 struct dioattr dioattr;
00187 char *buffer;
00188 XINT l_buffer;
00189 int oflag;
00190 struct STAT_TAG stat;
00191
00192
00193
00194
00195
00196 if ((strcmp (type, "r") == 0) || (strcmp (type, "rb") == 0)) {
00197
00198
00199
00200
00201
00202
00203
00204 oflag = O_RDONLY;
00205
00206 } else if ((strcmp (type, "w") == 0) || (strcmp (type, "wb") == 0)) {
00207 oflag = O_WRONLY | O_CREAT;
00208
00209 } else if ((strcmp (type, "a") == 0) || (strcmp (type, "ab") == 0)) {
00210 oflag = O_APPEND | O_CREAT;
00211
00212 } else if ((strcmp (type, "r+") == 0) || (strcmp (type, "r+b") == 0)
00213 || (strcmp (type, "rb+"))) {
00214 oflag = O_RDWR | O_CREAT;
00215
00216 } else if ((strcmp (type, "w+") == 0) || (strcmp (type, "w+b") == 0)
00217 || (strcmp (type, "wb+"))) {
00218 oflag = O_TRUNC | O_WRONLY | O_CREAT;
00219
00220 } else if ((strcmp (type, "a+") == 0) || (strcmp (type, "a+b") == 0)
00221 || (strcmp (type, "ab+"))) {
00222 oflag = O_APPEND | O_WRONLY | O_CREAT;
00223
00224 } else {
00225 return (-1);
00226 }
00227
00228 l_buffer = get_buffer_size();
00229 if (l_buffer >= CROSSOVER)
00230 oflag |= O_DIRECT;
00231
00232
00233 if (!dupopen) {
00234 fd = open (file_name, oflag, 0666);
00235 if (fd == -1) {
00236
00237
00238
00239
00240
00241
00242
00243 oflag &= (~O_DIRECT);
00244 fd = open (file_name, oflag, 0666);
00245 if (fd == -1) return (fd);
00246 }
00247 }
00248 else
00249 fd = dup_fd;
00250
00251 if (!Direct) {
00252 if ((Direct = malloc( sizeof(*Direct) * mxunit )) == NULL) {
00253 errno = 113;
00254 return(-1);
00255 }
00256 memset(Direct,0,(size_t)(sizeof(*Direct) * mxunit ));
00257 Direct_size = mxunit;
00258 }
00259 else if (fd >= Direct_size) {
00260 if (Direct_size < mxunit) {
00261 if ((Direct = realloc( Direct, sizeof(*Direct)* mxunit )) == NULL) {
00262 errno = 113;
00263 return(-1);
00264 }
00265 memset((Direct+Direct_size),0,(size_t)(sizeof(*Direct) * (mxunit - Direct_size)));
00266 Direct_size = mxunit;
00267 } else {
00268
00269
00270
00271
00272 if ((Direct = realloc( Direct, sizeof(*Direct)*(Direct_size += mxunit) )) == NULL) {
00273 errno = 113;
00274 return(-1);
00275 }
00276 }
00277 }
00278
00279
00280
00281
00282
00283 if (FSTAT(fd, &stat) == -1) {
00284
00285 close (fd);
00286 return (-1);
00287 } else {
00288 _Mode = stat.st_mode;
00289 _Open_l_file = stat.st_size;
00290 _Actual_l_file = stat.st_size;
00291 _Sector_l_file = 0;
00292 _Current_pos = 0;
00293 }
00294
00295
00296
00297
00298
00299 _Sector = 512;
00300 d_maxiosz = CROSSOVER;
00301 CLEAR_DIRECT_BIT;
00302 if (oflag & O_DIRECT) {
00303 if (fcntl (fd, F_DIOINFO, &dioattr) != -1) {
00304
00305
00306
00307 SET_DIRECT_BIT;
00308 assert(dioattr.d_miniosz > 0);
00309 assert(dioattr.d_maxiosz > 0);
00310
00311 assert(dioattr.d_maxiosz>=dioattr.d_miniosz);
00312 d_mem = dioattr.d_mem;
00313 _Sector = (int) dioattr.d_miniosz;
00314 d_maxiosz = (int) dioattr.d_maxiosz;
00315 }
00316 }
00317 if (_Sector > d_mem)
00318 d_mem = _Sector;
00319
00320 if (l_buffer > d_maxiosz) l_buffer = d_maxiosz;
00321 if (l_buffer < _Sector) l_buffer = _Sector;
00322
00323
00324
00325 if (oflag & O_DIRECT)
00326 l_buffer = (l_buffer / (int) _Sector) * (int) _Sector;
00327
00328
00329
00330 if ((buffer = (char *) memalign (d_mem, l_buffer)) == NULL) {
00331 errno = 113;
00332 return(-1);
00333 }
00334
00335
00336
00337 _Buffer = buffer;
00338 _L_buffer = l_buffer;
00339 SET_EMPTY_BIT;
00340 return (fd);
00341 }
00342
00343
00344
00345 int _fio_du_write(unit *ftnunit, char *data, XINT n_data, XINT64 disk_loc, int fd)
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 {
00371
00372 XINT n_data_to_move;
00373 char *loc_in_buffer;
00374 XINT sector_up;
00375
00376 if (ftnunit->uacc != DIRECT) return(-1);
00377 if (!(_Mode & S_IWUSR)) return (-1);
00378
00379 if (disk_loc+n_data > _Actual_l_file)
00380 _Actual_l_file = disk_loc+n_data;
00381
00382 while (n_data > 0) {
00383 if (IS_DIRECT) {
00384
00385
00386
00387 int dirty_buff = !IS_EMPTY && (disk_loc < _L_disk + _L_data)
00388 && (disk_loc + n_data >= _L_disk);
00389
00390 if (((long)data % d_mem) == 0
00391 && (disk_loc % _Sector) == 0
00392 && (n_data >= CROSSOVER
00393 || (n_data >= LARGE_CHUNK && !dirty_buff)))
00394 {
00395 int oddbytes;
00396 if (dirty_buff) {
00397 if (disk_loc >= _L_disk && disk_loc < _L_disk + _L_buffer) {
00398
00399 int ncopy = _L_disk + _L_buffer - disk_loc;
00400 if (ncopy > n_data)
00401 ncopy = n_data;
00402 memcpy( _Buffer + disk_loc - _L_disk, data, ncopy );
00403 if (_L_data < disk_loc -_L_disk + ncopy)
00404 _L_data = disk_loc - _L_disk + ncopy;
00405 data += ncopy;
00406 n_data -= ncopy;
00407 disk_loc += ncopy;
00408 SET_FLUSH_BIT;
00409 }
00410 else if (disk_loc + n_data >= _L_disk && disk_loc + n_data < _L_disk + _L_buffer) {
00411
00412 int ncopy = disk_loc + n_data - _L_disk;
00413 memcpy( _Buffer, data + _L_disk - disk_loc, ncopy );
00414 if (_L_data < ncopy)
00415 _L_data = ncopy;
00416 n_data -= ncopy;
00417 SET_FLUSH_BIT;
00418 }
00419 else {
00420 SET_EMPTY_BIT;
00421 }
00422 }
00423 oddbytes = n_data % _Sector;
00424 if (-1 == LSEEK (fd, disk_loc, SEEK_SET)) return (-1);
00425 while (n_data >= d_maxiosz) {
00426 if (d_maxiosz != write (fd, data, d_maxiosz))
00427 return(-1);
00428 data += d_maxiosz;
00429 n_data -= d_maxiosz;
00430 disk_loc += d_maxiosz;
00431 }
00432 if (n_data > oddbytes) {
00433 int nwrite = n_data - oddbytes;
00434 if (nwrite != write (fd, data, nwrite))
00435 return(-1);
00436 data += nwrite;
00437 disk_loc += nwrite;
00438 }
00439 n_data = oddbytes;
00440 _Current_pos = disk_loc;
00441 continue;
00442 }
00443 if (IS_EMPTY) {
00444
00445
00446
00447 _L_disk = (disk_loc / _Sector) * _Sector;
00448 if (-1 == LSEEK (fd, _L_disk, SEEK_SET)) return (-1);
00449 _L_data = read (fd, _Buffer, _L_buffer);
00450 if (_L_data == -1) {
00451
00452
00453
00454
00455
00456
00457
00458 if (-1 == LSEEK (fd, _L_disk, SEEK_SET)) return (-1);
00459 if (-1 == fcntl(fd, F_SETFL, (fcntl(fd, F_GETFL)&(~FDIRECT))))
00460 return (-1);
00461 if (-1 == (_L_data = read (fd, _Buffer, _L_buffer))) return(-1);
00462 if (-1 == fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | FDIRECT))
00463 return (-1);
00464 } else if (disk_loc > _Open_l_file) {
00465
00466
00467
00468
00469
00470 n_data_to_move = disk_loc - (_L_data + _L_disk);
00471 memset( _Buffer+_L_data, 0, n_data_to_move );
00472 }
00473 CLEAR_EMPTY_BIT;
00474 }
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484 if ((disk_loc >= _L_disk) && (disk_loc < _L_disk + _L_buffer)) {
00485 n_data_to_move = (_L_disk + _L_buffer) - disk_loc;
00486 n_data_to_move = (n_data < n_data_to_move) ? n_data : n_data_to_move;
00487 loc_in_buffer = _Buffer + (disk_loc - _L_disk);
00488 memcpy (loc_in_buffer, data, n_data_to_move);
00489 _L_data = (((disk_loc + n_data_to_move) - _L_disk) > _L_data) ?
00490 (disk_loc + n_data_to_move) - _L_disk :
00491 _L_data;
00492 data += n_data_to_move;
00493 n_data -= n_data_to_move;
00494 disk_loc += n_data_to_move;
00495 _Current_pos = disk_loc;
00496 if (n_data == 0) {
00497 CLEAR_EMPTY_BIT;
00498 SET_FLUSH_BIT;
00499 } else {
00500
00501 if (-1 == LSEEK (fd, _L_disk, SEEK_SET)) return (-1);
00502 sector_up = ((_L_data + _Sector - 1) / _Sector) * _Sector;
00503 if (sector_up != write (fd, _Buffer, sector_up)) return (-1);
00504 while (n_data > _L_buffer) {
00505 memcpy( _Buffer, data, _L_buffer);
00506 if (_L_buffer != write (fd, _Buffer, _L_buffer)) return (-1);
00507 n_data -= _L_buffer;
00508 data += _L_buffer;
00509 disk_loc += _L_buffer;
00510 }
00511 _Current_pos = disk_loc;
00512 CLEAR_FLUSH_BIT;
00513 }
00514 } else {
00515 if (MUST_FLUSH) {
00516 _fio_du_flush( fd );
00517 }
00518 else
00519 SET_EMPTY_BIT;
00520 }
00521 }
00522 else if (n_data > LARGE_CHUNK && (IS_EMPTY || ((disk_loc < _L_disk) || (disk_loc > _L_disk + _L_data)))) {
00523
00524 if (-1 == _fio_du_flush (fd)) return (-1);
00525
00526
00527
00528
00529 if (ftnunit->f77recpos == n_data)
00530
00531
00532
00533
00534 if (-1 == LSEEK (fd, disk_loc, SEEK_SET)) return (-1);
00535 if (n_data != write (fd, data, n_data)) return (-1);
00536 n_data = 0;
00537 SET_EMPTY_BIT;
00538 CLEAR_FLUSH_BIT;
00539 }
00540 else {
00541
00542
00543
00544
00545 if (IS_EMPTY) {
00546
00547 int nwrite = (n_data < _L_buffer) ? n_data : _L_buffer;
00548 memcpy (_Buffer, data, nwrite);
00549 _L_disk = disk_loc;
00550 _L_data = nwrite;
00551 disk_loc += nwrite;
00552 _Current_pos = disk_loc;
00553 n_data -= nwrite;
00554 if (n_data != 0) {
00555
00556 if (-1 == LSEEK (fd, _L_disk, SEEK_SET))
00557 return (-1);
00558 if (_L_data != write (fd, _Buffer, _L_data))
00559 return (-1);
00560 CLEAR_FLUSH_BIT;
00561 SET_EMPTY_BIT;
00562 } else {
00563 SET_FLUSH_BIT;
00564 CLEAR_EMPTY_BIT;
00565 }
00566 } else if ((disk_loc >= _L_disk) && (disk_loc <= _L_disk + _L_data)) {
00567
00568 n_data_to_move = (_L_disk + _L_buffer) - disk_loc;
00569 n_data_to_move = (n_data < n_data_to_move) ? n_data : n_data_to_move;
00570 loc_in_buffer = _Buffer + (disk_loc - _L_disk);
00571 memcpy (loc_in_buffer, data, n_data_to_move);
00572 _L_data = (((disk_loc + n_data_to_move) - _L_disk) > _L_data) ?
00573 (disk_loc + n_data_to_move) - _L_disk : _L_data;
00574 data += n_data_to_move;
00575 n_data -= n_data_to_move;
00576 disk_loc += n_data_to_move;
00577 _Current_pos = disk_loc;
00578 if (n_data != 0) {
00579
00580 if (-1 == LSEEK (fd, _L_disk, SEEK_SET))
00581 return (-1);
00582 if (_L_data != write (fd, _Buffer, _L_data))
00583 return (-1);
00584 CLEAR_FLUSH_BIT;
00585 SET_EMPTY_BIT;
00586 } else {
00587 SET_FLUSH_BIT;
00588 CLEAR_EMPTY_BIT;
00589 }
00590 } else {
00591
00592
00593
00594 if (MUST_FLUSH) {
00595 if (-1 == LSEEK (fd, _L_disk, SEEK_SET)) return (-1);
00596 if (_L_data != write (fd, _Buffer, _L_data)) return (-1);
00597 CLEAR_FLUSH_BIT;
00598 }
00599 SET_EMPTY_BIT;
00600 }
00601 }
00602 }
00603 return (fd);
00604 }
00605
00606
00607
00608 int _fio_du_flush(fd)
00609 int fd;
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631 {
00632
00633 XINT sector_up;
00634
00635 if (IS_EMPTY) return (fd);
00636
00637 if (MUST_FLUSH) {
00638 if (!(_Mode & S_IWUSR)) return (-1);
00639 if (-1 == LSEEK (fd, _L_disk, SEEK_SET))
00640 return (-1);
00641 if (IS_DIRECT) {
00642 sector_up = ((_L_data + _Sector - 1) / _Sector) * _Sector;
00643 if (sector_up != write (fd, _Buffer, sector_up))
00644 return (-1);
00645 if (_L_disk + sector_up > _Actual_l_file) {
00646 _Sector_l_file = _L_disk + sector_up;
00647 }
00648 } else {
00649 if (_L_data != write (fd, _Buffer, _L_data))
00650 return (-1);
00651 }
00652 SET_EMPTY_BIT;
00653 CLEAR_FLUSH_BIT;
00654 }
00655 return (fd);
00656
00657 }
00658
00659
00660
00661 int _fio_du_read(unit *ftnunit, char *data, XINT n_data, XINT64 disk_loc, int fd)
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686 {
00687
00688 char *loc_in_buffer;
00689 XINT n_data_to_move;
00690 XINT sector_up;
00691
00692 if (ftnunit->uacc != DIRECT) {
00693 errno = F_ERNODIO;
00694 return(-1);
00695 }
00696
00697
00698
00699
00700 if (!(_Mode & S_IRUSR)) {
00701 errno = EBADF;
00702 return (-1);
00703 }
00704
00705
00706
00707
00708
00709 if ((disk_loc + n_data > _Open_l_file) &&
00710 (disk_loc + n_data > _Actual_l_file)) {
00711 errno = F_ERINVRECNO;
00712 return (-1);
00713 }
00714
00715 while (n_data > 0) {
00716 if (IS_DIRECT) {
00717 int hit_buff = !IS_EMPTY && (disk_loc >= _L_disk) && (disk_loc < _L_disk + _L_data);
00718
00719
00720
00721
00722
00723 if (((long)data % d_mem) == 0
00724 && (disk_loc % _Sector) == 0
00725 && n_data >= LARGE_CHUNK
00726 && !hit_buff
00727 && (IS_EMPTY
00728 || disk_loc != _L_disk + _L_data
00729 || n_data > _L_buffer/4))
00730 {
00731 int oddbytes = n_data % _Sector;
00732 int maxread;
00733
00734 if ( !IS_EMPTY && (disk_loc + n_data) >= _L_disk && disk_loc < _L_disk)
00735
00736
00737
00738 maxread = disk_loc - _L_disk;
00739 else
00740 maxread = n_data - oddbytes;
00741
00742 n_data -= maxread;
00743 if (-1 == LSEEK (fd, disk_loc, SEEK_SET)) return (-1);
00744 while (maxread >= d_maxiosz) {
00745 if (d_maxiosz != read (fd, data, d_maxiosz))
00746 return(-1);
00747 data += d_maxiosz;
00748 maxread -= d_maxiosz;
00749 disk_loc += d_maxiosz;
00750 }
00751 if (maxread) {
00752 if (maxread != read (fd, data, maxread))
00753 return(-1);
00754 data += maxread;
00755 disk_loc += maxread;
00756 }
00757 _Current_pos = disk_loc;
00758 continue;
00759 }
00760 if (IS_EMPTY) {
00761 if (disk_loc < _L_disk) {
00762 int n_remain = ftnunit->url - ftnunit->f77recpos + n_data;
00763
00764
00765
00766
00767 _L_disk = ((disk_loc+n_remain)/_Sector + 1) * _Sector - _L_buffer;
00768 if (_L_disk < 0)
00769 _L_disk = 0;
00770 else if (disk_loc < _L_disk)
00771
00772
00773
00774
00775 _L_disk = (disk_loc / _Sector) * _Sector;
00776 } else
00777 _L_disk = (disk_loc / _Sector) * _Sector;
00778 if (-1 == LSEEK (fd, _L_disk, SEEK_SET)) return (-1);
00779 if (-1 == (_L_data = read (fd, _Buffer, _L_buffer))) {
00780
00781
00782
00783
00784
00785
00786
00787 if (-1 == LSEEK (fd, _L_disk, SEEK_SET)) return (-1);
00788 if (-1 == fcntl(fd, F_SETFL, (fcntl(fd, F_GETFL)&(~FDIRECT))))
00789 return (-1);
00790 if (-1 == (_L_data = read (fd, _Buffer, _L_buffer))) return(-1);
00791 if (-1 == fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | FDIRECT))
00792 return (-1);
00793 }
00794 CLEAR_EMPTY_BIT;
00795
00796
00797
00798 if (_L_data < _L_buffer) {
00799 if (disk_loc + n_data > _L_disk + _L_data) {
00800 errno = -1;
00801 return (-1);
00802 }
00803 }
00804 }
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814 if ((disk_loc >= _L_disk) && (disk_loc < _L_disk + _L_buffer)) {
00815 n_data_to_move = (_L_disk + _L_buffer) - disk_loc;
00816 n_data_to_move = (n_data < n_data_to_move) ? n_data : n_data_to_move;
00817 loc_in_buffer = _Buffer + (disk_loc - _L_disk);
00818 memcpy (data, loc_in_buffer, n_data_to_move);
00819 data += n_data_to_move;
00820 n_data -= n_data_to_move;
00821 disk_loc += n_data_to_move;
00822 _Current_pos = disk_loc;
00823 } else {
00824 if (MUST_FLUSH) {
00825 _fio_du_flush( fd );
00826 }
00827 else
00828 SET_EMPTY_BIT;
00829 }
00830
00831 } else if (n_data > _L_buffer) {
00832
00833
00834
00835 if (MUST_FLUSH) {
00836 if (-1 == LSEEK (fd, _L_disk, SEEK_SET))
00837 return (-1);
00838 if (_L_data != write (fd, _Buffer, _L_data))
00839 return (-1);
00840 CLEAR_FLUSH_BIT;
00841 }
00842 if (-1 == LSEEK (fd, disk_loc, SEEK_SET))
00843 return (-1);
00844 if (n_data != read (fd, data, n_data))
00845 return(-1);
00846 n_data = 0;
00847 } else if (IS_EMPTY) {
00848
00849 if (disk_loc < _L_disk) {
00850 int n_remain = ftnunit->url - ftnunit->f77recpos + n_data;
00851
00852
00853
00854
00855 _L_disk = (disk_loc+n_remain) - _L_buffer;
00856 if (_L_disk < 0)
00857 _L_disk = 0;
00858
00859
00860
00861
00862 else if (disk_loc < _L_disk)
00863 _L_disk = disk_loc;
00864 } else
00865 _L_disk = disk_loc;
00866 if (-1 == LSEEK (fd, _L_disk, SEEK_SET))
00867 return (-1);
00868 if (-1 == (_L_data = read (fd, _Buffer, _L_buffer))) {
00869 errno = F_ERNODIO;
00870 return (-1);
00871 }
00872 CLEAR_EMPTY_BIT;
00873 } else if ((disk_loc >= _L_disk) && (disk_loc < _L_disk + _L_data)) {
00874 n_data_to_move = (_L_disk + _L_data) - disk_loc;
00875 n_data_to_move = (n_data < n_data_to_move) ? n_data : n_data_to_move;
00876 loc_in_buffer = _Buffer + (disk_loc - _L_disk);
00877 memcpy (data, loc_in_buffer, n_data_to_move);
00878 data += n_data_to_move;
00879 n_data -= n_data_to_move;
00880 disk_loc += n_data_to_move;
00881 _Current_pos = disk_loc;
00882 } else {
00883
00884
00885
00886 if (-1 == _fio_du_flush (fd)) return (-1);
00887 SET_EMPTY_BIT;
00888 }
00889 }
00890 return (fd);
00891
00892 }
00893
00894
00895
00896 int _fio_du_close(int fd)
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918 {
00919 int istat;
00920 int lastpage;
00921
00922 assert (fd >= 0);
00923
00924
00925
00926
00927
00928 if (-1 == _fio_du_flush (fd)) return (-1);
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941 if (_Sector_l_file > _Actual_l_file) {
00942
00943
00944
00945
00946 ftruncate (fd, _Actual_l_file);
00947 }
00948
00949
00950
00951
00952
00953
00954 free (_Buffer);
00955 _Open_l_file = 0;
00956 _Actual_l_file = 0;
00957 _Sector_l_file = 0;
00958 _Mode = 0;
00959 _Buffer = 0;
00960 _L_buffer = 0;
00961 _L_data = 0;
00962 _L_disk = 0;
00963 _Flags = 0;
00964
00965
00966 istat = close (fd);
00967 if (istat == -1) return (-1);
00968 return (fd);
00969
00970 }
00971
00972
00973 void
00974 _fio_set_seek( int fd, long int offset, int from)
00975 {
00976 if (from == 0) {
00977 _Seek_pos = offset;
00978 } else if (from == 1) {
00979 _Seek_pos = _Current_pos + offset;
00980 } else {
00981 _Seek_pos = _Actual_l_file + offset;
00982 }
00983 _Current_pos = _Seek_pos;
00984 }
00985
00986 long
00987 _fio_get_pos( int fd )
00988 {
00989 return( _Current_pos );
00990 }
00991
00992 void
00993 _fio_seq_pos( int fd, unit *ftnunit )
00994 {
00995 if (ftnunit->url != 1)
00996 if (_Seek_pos) {
00997 ftnunit->uirec = (_Seek_pos / ftnunit->url) + 1;
00998 ftnunit->f77recpos = _Seek_pos % ftnunit->url;
00999 } else
01000 ftnunit->uirec++;
01001 else if (_Seek_pos)
01002 ftnunit->uirec = _Seek_pos;
01003
01004
01005
01006 _Seek_pos = 0;
01007 }
01008