/***********************************************************************/ /* Open Visualization Data Explorer */ /* (C) Copyright IBM Corp. 1989,1999 */ /* ALL RIGHTS RESERVED */ /* This code licensed under the */ /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */ /***********************************************************************/ #include #include #include #ifdef DXD_HAS_WINSOCKETS #include #else #include #endif #include "diskio.h" #ifdef DXD_WIN #include #include #include "dx/arch.h" #endif #if DXD_HAS_LIBIOP #include /* partition file system */ #include /* movie library support */ static int _dxfiobuf_allocate(int nblks, Pointer *base, Pointer *mem); static int partial_read(char *name, uint addr, uint offset, uint cnt, uint bytes); static int partial_write(char *name, uint addr, uint offset, uint cnt, uint bytes); #endif /* other prototypes (the rest are in diskio.h) */ static Error movie_init(); static Error file_init(); static Error file_exit(); static int name_to_fd(char *name, int *socket); static int fd_socketsize(int fd, int *rdsize, int *wrsize); /* if not using array disk, this data struct mimics the same calling * sequence (e.g. read/write by name), using normal unix files. */ #include #define NSLOTS 16 /* was 32 */ #define SOCK_BUFSIZE 32768 /* table of names to file descriptors. * unused slots have -1 as the file descriptor * the fname length is 256 to match the pfsmgr limit * socket should be set if the fd is a socket where you aren't able * to preallocate space, you can't seek back and forth, and there is * a limit to the max number of bytes you can read/write at once. */ static struct openfiles { char fname[256]; int fd; int socket; int sndbytes; int rcvbytes; } *of; static int name_to_fd(char *name, int *socket) { int i; for (i=0; i= 0) { rc = pfs_drive_list(i, dname); if (rc < 0) continue; strcat(dname, ":"); rc = pfs_free(dname, &size); if (rc < 0) continue; /* valid pfs partition */ break; } /* you get here if there are drives defined but none of them are valid. */ if (i < 0) DXUIMessage("ERROR", "Array disk not available; execution continues"); #endif endarray: of = (struct openfiles *)DXAllocateZero(sizeof(struct openfiles) * NSLOTS); if (!of) return ERROR; for (i=0; ifd from table */ fd = name_to_fd(name, &issocket); if (fd < 0) { DXSetError(ERROR_BAD_PARAMETER, "can't open dataset '%s'", name); return ERROR; } if (!issocket && nblocks > 0) { lseek(fd, nblocks*ONEBLK - sizeof(int), 0); write(fd, &fd, sizeof(int)); lseek(fd, 0, 0); } return OK; } Error _dxffile_read(char *name, int offset, int count, char *addr, int bytes) { int cnt, fd, rc, left; int issocket = 0; int maxio; int oneblock; if (!name) { DXSetError(ERROR_BAD_PARAMETER, "no filename"); return ERROR; } if (!addr) { DXSetError(ERROR_BAD_PARAMETER, "bad memory address 0"); return ERROR; } #if DXD_HAS_LIBIOP if (pfsname(name)) { /* check alignment of addr */ if (LEFTOVER_BYTES(addr, ONEK)) { DXSetError(ERROR_INVALID_DATA, "buffer must be 1K alligned"); return ERROR; } /* check for partial blocks */ if (bytes != 0) /* copy the partial last block into a complete block and read */ rc = partial_read(name, (uint)addr, (uint)offset, (uint)count, (uint)bytes); else rc = pfs_read(name, (void *)addr, (uint)offset, (uint)count); if (rc < 0) { DXSetError(ERROR_INVALID_DATA, pfs_errmsg(rc)); return ERROR; } return OK; } #endif /* find name->fd from table */ fd = name_to_fd(name, &issocket); if (fd < 0) { DXSetError(ERROR_BAD_PARAMETER, "can't open dataset '%s'", name); return ERROR; } if(issocket) oneblock = HALFK; else oneblock = ONEBLK; cnt = count*oneblock; if (bytes != 0) cnt += bytes - oneblock; if (!issocket) { lseek(fd, offset*oneblock, 0); maxio = cnt; } else { if (fd_socketsize(fd, &maxio, NULL) != 1) return ERROR; } left = cnt; while (left > 0) { cnt = left > maxio ? maxio : left; if ((rc = read(fd, addr, cnt)) <= 0) { DXSetError(ERROR_INVALID_DATA, "can't read dataset '%s'", name); return ERROR; } left -= rc; addr += rc; } return OK; } Error _dxffile_write(char *name, int offset, int count, char *addr, int bytes) { int cnt, fd, rc, left; int issocket = 0; int maxio; int oneblock; if (!name) { DXSetError(ERROR_BAD_PARAMETER, "no filename"); return ERROR; } if (!addr) { DXSetError(ERROR_BAD_PARAMETER, "bad memory address 0"); return ERROR; } #if DXD_HAS_LIBIOP if (pfsname(name)) { char *base, *align; int i, size; /* check alignment of addr */ if (LEFTOVER_BYTES(addr, ONEK)) { size = count * 64 * 1024 + bytes; base = (char *)DXAllocate(size + 1024); align = (char *)(((int)base + 1023) & ~1023); bcopy(addr, align, size); if (bytes != 0) rc = partial_write(name, (uint)align, (uint)offset, (uint)count, (uint)bytes); else rc = pfs_write(name, (void *)align, (uint)offset, (uint)count); DXFree((Pointer)base); if (rc < 0) { DXSetError(ERROR_INVALID_DATA, pfs_errmsg(rc)); return ERROR; } return OK; } /* check for partial last block */ if (bytes != 0) rc = partial_write(name, (uint)addr, (uint)offset, (uint)count, (uint)bytes); else rc = pfs_write(name, (void *)addr, (uint)offset, (uint)count); if (rc < 0) { DXSetError(ERROR_INVALID_DATA, pfs_errmsg(rc)); return ERROR; } return OK; } #endif /* find name->fd from table */ fd = name_to_fd(name, &issocket); if (fd < 0) { DXSetError(ERROR_BAD_PARAMETER, "can't open dataset '%s'", name); return ERROR; } if(issocket) oneblock = HALFK; else oneblock = ONEBLK; cnt = count*oneblock; if (bytes != 0) cnt += bytes - oneblock; if (!issocket) { lseek(fd, offset*oneblock, 0); maxio = cnt; } else { if (fd_socketsize(fd, NULL, &maxio) != 1) return ERROR; } left = cnt; while (left > 0) { cnt = left > maxio ? maxio : left; if ((rc = write(fd, addr, cnt)) <= 0) { DXSetError(ERROR_BAD_PARAMETER, "can't write dataset '%s'", name); return ERROR; } left -= rc; addr += rc; } return OK; } Error _dxffile_close(char *name) { int i; if (!name) { DXSetError(ERROR_BAD_PARAMETER, "no filename"); return ERROR; } #if DXD_HAS_LIBIOP if (pfsname(name)) return OK; #endif /* find name->fd in table */ for (i=0; ifd in table */ for (i=0; i 0) { rc = pfs_read(name, (void *)addr, offset, cnt); if (rc < 0) return -1; addr += cnt * ONEBLK; offset += cnt; } rc = pfs_read(name, (void *)frag_mem, offset, 1); if (rc < 0) { DXFree(frag_base); return rc; } memcpy(addr, frag_mem, bytes); DXFree(frag_base); return 0; } static int partial_write(char *name, uint addr, uint offset, uint cnt, uint bytes) { int rc; Pointer frag_base = NULL, frag_mem = NULL; if (bytes == 0) return pfs_write(name, (void *)addr, offset, cnt); if (_dxfiobuf_allocate(1, &frag_base, &frag_mem) == 0) return -1; cnt--; if (cnt > 0) { rc = pfs_write(name, (void *)addr, offset, cnt); if (rc < 0) return -1; addr += cnt * ONEBLK; offset += cnt; } memcpy(frag_mem, addr, bytes); rc = pfs_write(name, (void *)frag_mem, offset, 1); DXFree(frag_base); return rc; } /* allocates the requested number of 64K blocks. base is the value * to be DXFree'd when finished; mem is the pointer aligned on an even * 1K memory boundary. */ static int _dxfiobuf_allocate(int blocks, Pointer *base, Pointer *mem) { *base = DXAllocate(blocks * ONEBLK + ONEK); *mem = (Pointer)ROUNDUP_BYTES(*base, ONEK); return (*base ? OK : ERROR); } #endif /*DXD_HAS_LIBIOP*/ /* from here down, the routines are unused, as far as i know */ #if 0 /* unused, as far as i know */ static Error file_info(char *name, struct dinfo *dip) { if (!name) { DXSetError(ERROR_BAD_PARAMETER, "no filename"); return ERROR; } if (!dip) { DXSetError(ERROR_BAD_PARAMETER, "bad info address 0"); return ERROR; } #if DXD_HAS_LIBIOP if (pfsname(name)) { pfs_stat_t ps; return ((pfs_stat(name, &ps) == 0) ? OK : ERROR); } #endif /* do a stat on the filename, and fill in the dip struct */ return OK; } /* unused, as far as i know */ static Error file_list(int i, char **name, struct dinfo *dip) { if (!name) { DXSetError(ERROR_BAD_PARAMETER, "no filename"); return ERROR; } if (!dip) { DXSetError(ERROR_BAD_PARAMETER, "bad info address 0"); return ERROR; } if (i < 0) { DXSetError(ERROR_BAD_PARAMETER, "bad info number"); return ERROR; } #if DXD_HAS_LIBIOP if (pfsname(*name)) { pfs_stat_t ps; return ((pfs_stat(*name, &ps) == 0) ? OK : ERROR); } #endif /* well? what here? stat *.bin and take the Nth one? */ return OK; } /* debug */ static void file_dirprint() { int i, n; char buf[256]; char *gm_buf = NULL; #if DXD_HAS_LIBIOP n = pfs_count(NULL); if (n <= 0) return; gm_buf = (char *)DXAllocate(n * PFS_NAME_LEN); if (!gm_buf) return; pfs_list(NULL, gm_buf, 0, &n); for(i=0; i