|
Sybernet / Supplied Packages Reference
Release 3.00 Jul 18, 2006 |
|
The STDIO package provides subprograms for operating on unix files. With it, you can use PL/SQL to open a file for reading or writing, read from or write to that file, and close that file. Although similar to Oracle's UTL_FILE package, the STDIO package is a different implementation.
Unlike Oracle's UTL_FILE package which limits users to a particular path or paths, no such restrictions are imposed by this package. If you have access to this package, you can read or write from or to any directory that is allowed by the username for your Oracle instance. That is, if Oracle is running from username oracle, then you are restricted by the limitations of that username.
There are more functions available than are explained in this document. If a function is not documented, refer to the package specification. If the function exists, either you already know how to use it or you can request its man page. The man pages are also useful if you need more information than is provided in this guide.
STDIO defines the following constants:
/* ** open() */ O_RDONLY constant int:= 0; -- Open for reading only. O_WRONLY constant int:= 1; -- Open for writing only. O_RDWR constant int:= 2; -- Open for reading and writing. O_APPEND constant int:= 8; -- append (writes guaranteed at the end) O_NONBLOCK constant int:= 128; -- non-blocking I/O (POSIX) O_CREAT constant int:= 256; -- open with file create (uses third arg) O_TRUNC constant int:= 512; -- open with truncation O_EXCL constant int:= 1024; -- exclusive open O_NOCTTY constant int:= 2048; -- don't allocate controlling tty (POSIX) /* ** lseek() */ SEEK_SET constant int:= 0; -- Set file pointer to "offset" SEEK_CUR constant int:= 1; -- Set file pointer to current plus "offset" SEEK_END constant int:= 2; -- Set file pointer to EOF plus "offset" /* ** stat() */ S_IFMT constant int:=61440; -- type of file S_IAMB constant int:= 511; -- access mode bits S_IFIFO constant int:= 4096; -- fifo S_IFCHR constant int:= 8192; -- character special S_IFDIR constant int:=16384; -- directory S_IFNAM constant int:=20480; -- XENIX special named file S_INSEM constant int:= 1; -- XENIX semaphore subtype of IFNAM S_INSHD constant int:= 2; -- XENIX shared data subtype of IFNAM S_IFBLK constant int:=24576; -- block special S_IFREG constant int:=32768; -- regular S_IFLNK constant int:=40960; -- symbolic link S_IFSOCK constant int:=49152; -- socket S_IFDOOR constant int:=53248; -- door S_ISUID constant int:= 2048; -- set user id on execution S_ISGID constant int:= 1024; -- set group id on execution S_ISVTX constant int:= 512; -- save swapped text even after use S_IREAD constant int:= 1024; -- read permission, owner S_IWRITE constant int:= 512; -- write permission, owner S_IEXEC constant int:= 256; -- execute/search permission, owner S_ENFMT constant int:= 1024; -- record locking enforcement flag /* ** chmod() and open() */ S_IRWXU constant int:= 448; -- Read, write, execute by owner S_IRUSR constant int:= 256; -- Read by owner S_IWUSR constant int:= 128; -- Write by owner S_IXUSR constant int:= 64; -- Execute (search if a directory) by owner S_IRWXG constant int:= 56; -- Read, write, execute by group S_IRGRP constant int:= 32; -- Read by group S_IWGRP constant int:= 16; -- Write by group S_IXGRP constant int:= 8; -- Execute by group S_IRWXO constant int:= 7; -- Read, write, execute (search) by others S_IROTH constant int:= 4; -- Read by others S_IWOTH constant int:= 2; -- Write by others S_IXOTH constant int:= 1; -- Execute by others /* ** fcntl() */ F_DUPFD constant int:= 0; -- Duplicate fildes F_GETFD constant int:= 1; -- Get fildes flags F_SETFD constant int:= 2; -- Set fildes flags F_GETFL constant int:= 3; -- Get file flags F_SETFL constant int:= 4; -- Set file flags F_O_GETLK constant int:= 5; -- SVR3 Get file lock (need for rfs, across F_CHKFL constant int:= 8; -- Unused F_DUP2FD constant int:= 9; -- Duplicate fildes at third arg F_ALLOCSP constant int:= 10; -- Reserved F_ISSTREAM constant int:= 13; -- Is the file desc. a stream ? F_PRIV constant int:= 15; -- Turn on private access to file F_NPRIV constant int:= 16; -- Turn off private access to file F_QUOTACTL constant int:= 17; -- UFS quota call F_BLOCKS constant int:= 18; -- Get number of BLKSIZE blocks allocated F_BLKSIZE constant int:= 19; -- Get optimal I/O block size F_GETOWN constant int:= 23; -- Get owner (socket emulation) F_SETOWN constant int:= 24; -- Set owner (socket emulation) F_REVOKE constant int:= 25; -- C2 Security. Revoke access to file desc. F_HASREMOTELOCKS constant int:= 26; -- Does vp have NFS locks; private to lock manager F_SETLK constant int:= 6; -- Set file lock F_SETLKW constant int:= 7; -- Set file lock and wait F_FREESP constant int:= 11; -- Free file space F_GETLK constant int:= 14; -- Get file lock F_SETLK64 constant int:= 34; -- Set file lock F_SETLKW64 constant int:= 35; -- Set file lock and wait F_FREESP64 constant int:= 27; -- Free file space F_GETLK64 constant int:= 33; -- Get file lock F_SETLK64 constant int:= 6; -- Set file lock F_SETLKW64 constant int:= 7; -- Set file lock and wait F_FREESP64 constant int:= 11; -- Free file space F_GETLK64 constant int:= 14; -- Get file lock F_SHARE constant int:= 40; -- Set a file share reservation F_UNSHARE constant int:= 41; -- Remove a file share reservation
STDIO defines the following global variables:
type struct_stat is record
(
st_dev number -- device of inode.
, st_ino number -- inode number.
, st_mode number -- mode bits.
, st_nlink number -- number of links to file.
, st_uid number -- owner's user id.
, st_gid number -- owner's group id.
, st_rdev number -- for special files.
, st_size number -- file size in characters.
, st_atime date -- time last accessed.
, st_mtime date -- time last modified.
, st_ctime date -- time inode last changed.
) ;
type dirent is record
(
d_ino number -- inode number of entry.
, d_off number -- offset of disk directory entry.
, d_reclen number -- length of this record.
, d_name varchar(1024) -- name of file.
) ;
| Subprogram | Description |
|---|---|
CHDIR function |
Set working directory. |
CHMOD function |
Sets access mode on a file. |
CLOSE function |
Closes a file. |
CLOSEDIR function |
Closes a directory. |
ERRNO function |
Retrieves the global errno value. |
FCHDIR function |
Set working directory. |
FCHMOD function |
Sets access mode on a file. |
FPRINTF function |
Places formatted output on the specified fildes. | FSTAT function |
Gets the status of a file. |
GETC function |
Retrieves a character (an int) from a file. |
GETS function |
Retrieves one line from a file. |
LSEEK function |
Positions a file. |
LSTAT function |
Gets the status of a file. |
OPEN function |
Opens a file. |
OPENDIR function |
Opens a directory. |
PCLOSE function |
Closes a pipe. |
PGETS function |
Reads one line from a pipe. |
POPEN function |
Opens a pipe. |
READ function |
Reads bytes from a file. |
READDIR function |
Reads a directory. |
RENAME function |
Renames a file. |
SEARCH procedure |
Recursively lists all files and directories. |
STAT function |
Gets the status of a file. |
STRERROR function |
Maps the error number in errnum to an error message. |
SYSTEM procedure |
Initiates a command. |
UNLINK function |
Removes a file. |
WRITE function |
Writes bytes to a file. |
This function opens a file and returns a file descriptor (fildes) to your PL/SQL block. You use this file descriptor to read, write, and close this file. Unlike UTL_FILE where you are restricted to a particular path, STDIO has no such restrictions, and it will create directory nodes where none existed before (as long as you have permission to do so).
When you call OPEN, the specified file is opened. If successful, the file descriptor is returned. If unsuccessful, -1 is returned.
In all cases it is your responsibility to close the file. If an exception is raised and not caught and you do not close the file, you run the risk of using up the pool of available file descriptors.
FUNCTION HTTP.STDIO.OPEN
(
PATH IN VARCHAR2
, OFLAG IN BINARY_INTEGER
)
RETURN BINARY_INTEGER;
| Parameter | Description |
|---|---|
path |
Absolute path and file name of the file you wish to open |
oflag |
The mode (O_RDONLY for read, O_WRONLY for write, O_RDWR for read and write). |
FUNCTION HTTP.STDIO.OPEN
(
PATH IN VARCHAR2
, OFLAG IN BINARY_INTEGER
, MODE IN BINARY_INTEGER
)
RETURN BINARY_INTEGER;
| Parameter | Description |
|---|---|
path |
Absolute path and file name of the file you wish to open |
oflag |
The mode (O_RDONLY for read, O_WRONLY for write, O_RDWR for read and write). |
mode |
Sets permissions on the file if O_WRONLY or O_CREAT. |
HTTP.STDIO.OPEN
(
path IN VARCHAR2
, mode IN VARCHAR2
)
RETURN BINARY_INTEGER;
| Parameter | Description |
|---|---|
path |
Absolute path and file name of the file you wish to open |
mode |
The mode ('r' for read, 'w' for write, 'a' for append) |
OPEN returns the corresponding status code for this OPEN. If the call to OPEN is successful, the file designator (fildes) will be greater than 0, which means you can use this package to manipulate this information. A result of -1 means the file was not opened (because it doesn't exist or because it could not be created).
The following block opens a file, reads that file and displays it on your browser, then closes the file.
declare
fildes int;
buf varchar(1024);
status int;
begin
fildes := http.stdio.open('/opt/home/denis/oracle/develop/secproc.c','r');
if (fildes = -1) then
http.writeln(http.stdio.strerror(http.stdio.errno));
else
loop
status := http.stdio.read(fildes,buf);
exit when status < 1;
http.write(buf);
end loop;
if (status != 0) then
http.writeln(http.stdio.strerror(http.stdio.errno));
end if;
status:=http.stdio.close(fildes);
if (status != 0) then
http.writeln(http.stdio.strerror(http.stdio.errno));
end if;
end if;
end;
This function closes the file designator returned by calling OPEN.
In all cases it is your responsibility to close the file. If an exception is raised and not caught and you do not close the file, you run the risk of using up the pool of available file descriptors.
FUNCTION HTTP.STDIO.CLOSE ( FILDES BINARY_INTEGER ) RETURN BINARY_INTEGER;
| Parameter | Description |
|---|---|
fildes |
The file descriptor returned by CREAT, DUP, DUP2, and OPEN. |
0 if successful; -1 if not successful.
The following block opens a file, reads that file and displays it on your browser, then closes the file.
declare
fildes int;
buf varchar(1024);
status int;
begin
fildes := http.stdio.open('/opt/home/denis/oracle/develop/secproc.c','r');
if (fildes = -1) then
http.writeln(http.stdio.strerror(http.stdio.errno));
else
loop
status := http.stdio.read(fildes,buf);
exit when status < 1;
http.write(buf);
end loop;
if (status != 0) then
http.writeln(http.stdio.strerror(http.stdio.errno));
end if;
status:=http.stdio.close(fildes);
if (status != 0) then
http.writeln(http.stdio.strerror(http.stdio.errno));
end if;
end if;
end;
This function retrieves the next character from an opened file. Because you are reading one character at a time, GETC() is slower than READ() when READ passes a reasonable buffer size.
FUNCTION HTTP.STDIO.GETC(FILDES BINARY_INTEGER) RETURN BINARY_INTEGER;
| Parameter | Description |
|---|---|
fildes |
The file descriptor returned by CREAT, DUP, DUP2, and OPEN. |
GETC returns the next character as an int from the specified file descriptor. -1 is returned if end-of-file (EOF) is detected.
The following block opens a file, reads that file and displays it on your browser, then closes the file. Since each character returned is actually an int, one must pass this to Oracle's chr() function to convert it from integer to char.
declare
fildes int;
c int;
status int;
begin
fildes := http.stdio.open('/opt/home/denis/oracle/develop/secproc.c','r');
if (fildes = -1) then
http.writeln(http.stdio.strerror(http.stdio.errno));
else
loop
c := http.stdio.getc(fildes);
exit when c < 1;
http.write(chr(c));
end loop;
status:=http.stdio.close(fildes);
if (status != 0) then
http.writeln(http.stdio.strerror(http.stdio.errno));
end if;
end if;
end;
This GETS() function reads characters from the file pointed to by fildes into buf until a newline character is read or an end-of-file condition is encountered.
This is slightly different from the standard gets() function used with stream files. The newline character (if it exists) is not stripped. It will also raise an exception (ORA-19011) when the string (buf) is not large enough to hold the next line. You can catch and ignore the exception, but it appears Oracle returns the prior string instead of the string that caused the error. Subsequent calls to GETS() will, however, read the next line in your file.
The second form of GETS() returns a varchar and resembles the gets() function you are used to. It can return a line as long as 32,767. Since it calls the first form of GETS(), it is subject to any limitations imposed by that function.
In all cases it is your responsibility to close the file. If an exception is raised and not caught and you do not close the file, you run the risk of using up the pool of available file descriptors.
HTTP.STDIO.GETS
(
FILDES IN BINARY_INTEGER
, BUF OUT STRUCT_STAT
)
RETURN BINARY_INTEGER;
| Parameter | Description |
|---|---|
fildes |
The file descriptor returned by CREAT, DUP, DUP2, and OPEN. |
buf |
The buffer area where GETS() places its next input. |
The number of bytes read or -1 if an error occured.
HTTP.STDIO.GETS
(
FILDES IN BINARY_INTEGER
)
RETURN VARCHAR2;
| Parameter | Description |
|---|---|
fildes |
The file descriptor returned by CREAT, DUP, DUP2, and OPEN. |
NULL if end-of-file or a a non-null string.
| Exception | Description |
|---|---|
ORA-19011 |
Character string buffer too small. |
The following block illustrates how to read lines from a text file:
declare
status int;
fildes int;
buf varchar(1024);
begin
fildes:=http.stdio.open('/opt/home/denis/oracle/develop/secproc.c','r');
if (fildes != -1) then
loop
status:=http.stdio.gets(fildes,buf);
exit when status < 1;
http.write(buf);
end loop;
status:=http.stdio.close(fildes);
else
write(http.stdio.strerror(http.stdio.errno));
end if;
end;
The following block illustrates how to read lines from a text file:
declare
status int;
fildes int;
buf varchar(1024);
begin
fildes:=http.stdio.open('/opt/home/denis/oracle/develop/secproc.c','r');
if (fildes != -1) then
loop
buf:=http.stdio.gets(fildes);
exit when buf is null;
http.write(buf);
end loop;
status:=http.stdio.close(fildes);
else
write(http.stdio.strerror(http.stdio.errno));
end if;
end;
This functions reads from the file specified by fildes. Your output parameter (buf) determines how many characters are retrieved. The larger buf is declared, the more efficient READ is. A buffer size of 1 is tantamount (speed wise) to calling GETC().
There are two forms of READ. The first form is safe to use for all files of type text. The second form works with both text and binary files. If you are in doubt, always use the second form.
FUNCTION HTTP.STDIO.READ
(
FILDES IN BINARY_INTEGER
, BUF OUT VARCHAR2
)
RETURN PLS_INTEGER;
| Parameter | Description |
|---|---|
fildes |
The file descriptor returned by CREAT, DUP, DUP2, and OPEN. |
buf |
The buffer area where READ() places its next input. |
FUNCTION HTTP.STDIO.READ
(
FILDES IN BINARY_INTEGER
, BUF OUT RAW
, NBYTES IN BINARY_INTEGER
)
RETURN PLS_INTEGER;
| Parameter | Description |
|---|---|
fildes |
The file descriptor returned by CREAT, DUP, DUP2, and OPEN. |
buf |
The buffer area where READ() places its next input. |
nbytes |
The number of bytes to read. |
The number of bytes read or -1 if an error occured.
The following block opens a file, reads that file and displays it on your browser, then closes the file.
declare
fildes int;
buf varchar(1024);
status int;
begin
fildes := http.stdio.open('/opt/home/denis/oracle/develop/secproc.c','r');
if (fildes = -1) then
http.writeln(http.stdio.strerror(http.stdio.errno));
else
loop
status := http.stdio.read(fildes,buf);
exit when status < 1;
http.write(buf);
end loop;
if (status != 0) then
http.writeln(http.stdio.strerror(http.stdio.errno));
end if;
status:=http.stdio.close(fildes);
if (status != 0) then
http.writeln(http.stdio.strerror(http.stdio.errno));
end if;
end if;
end;
The following example is similar to the above except that the buffer size is a char which means it reads one character at a time. It is also slower because it requires more calls to the external stdio package. It is also void of error checking.
declare
fildes int;
buf char;
status int;
begin
fildes := http.stdio.open('/opt/home/denis/oracle/develop/secproc.c','r');
loop
status := http.stdio.read(fildes,buf);
exit when status < 1;
http.write(buf);
end loop;
status:=http.stdio.close(fildes);
end;
This function writes a string to fildes. Your input parameter (buf) determines how many characters are written. The larger your buf size, the more efficient WRITE is.
There are two forms of WRITE. The first form is safe to use for all files of type text. The second form works with both text and binary files. If you are in doubt, always use the second form.
FUNCTION HTTP.STDIO.WRITE
(
FILDES IN BINARY_INTEGER
, BUF IN VARCHAR2
)
RETURN PLS_INTEGER;
| Parameter | Description |
|---|---|
fildes |
The file descriptor returned by CREAT, DUP, DUP2, and OPEN. |
buf |
The buffer area that WRITE() writes to your file. |
FUNCTION HTTP.STDIO.WRITE
(
FILDES IN BINARY_INTEGER
, BUF IN VARCHAR2
, NBYTES IN BINARY_INTEGER
)
RETURN PLS_INTEGER;
| Parameter | Description |
|---|---|
fildes |
The file descriptor returned by CREAT, DUP, DUP2, and OPEN. |
buf |
The buffer area that WRITE() writes to your file. |
nbytes |
The number of raw bytes that should be written to your file. |
The number of bytes writeen or -1 if an error occured.
The following example illustrates how to append data to a file. It opens the file for append or creates the file if it does not exist. Using addition instead of a bitwise or is sinful, but used here because there are no collisions.
declare
fildes int;
status int;
begin
fildes := http.stdio.open
(
'/opt/home/oracle/example4'
, http.stdio.O_WRONLY + http.stdio.O_CREAT + http.stdio.O_APPEND
) ;
status:=http.stdio.write(fildes,'Hello World' || chr(10));
status:=http.stdio.write(fildes,'How Are you?' || chr(10));
status:=http.stdio.close(fildes);
end;
The following example illustrates how to append data to a file:
declare
fildes int;
status int;
begin
fildes := http.stdio.open('/opt/home/oracle/example4','a');
status:=http.stdio.write(fildes,'Hello World' || chr(10));
status:=http.stdio.write(fildes,'How Are you?' || chr(10));
status:=http.stdio.close(fildes);
end;
The following example illustrates how to copy a text file:
declare
fd1 int;
fd2 int;
buf varchar(1024);
status int;
begin
fd1:=http.stdio.open('/opt/home/denis/oracle/develop/secproc.c','r');
fd2:=http.stdio.open('/opt/home/denis/oracle/develop/secproc.x','w');
loop
status:=http.stdio.read(fd1,buf);
exit when status < 1;
status:=http.stdio.write(fd2,buf);
end loop;
status:=http.stdio.close(fd1);
status:=http.stdio.close(fd2);
end;
The following example illustrates how to copy a binary file. Close examination reveals that there is no difference between this example and the example above except for the input and output filenames. Both use the second form of READ() and WRITE() which explicitly specify the number of bytes to read and the number of bytes to write.
declare
fd1 int;
fd2 int;
buf varchar(1024);
status int;
begin
fd1 := http.stdio.open('/opt/home/denis/oracle/develop/secproc.so','r');
fd2 := http.stdio.open('/opt/home/denis/oracle/develop/secproc.sx','w');
loop
status := http.stdio.read(fd1,buf,1024);
exit when status < 1;
status:=http.stdio.write(fd2,buf,status);
end loop;
status:=http.stdio.close(fd1);
status:=http.stdio.close(fd2);
end;
This function performs a unix stat() on the specified path. It returns as an output parameter a struct stat with the exception that time variables are converted to Oracle's DATE values. To determine the filetype of a file you must perform a HTTP.BITAND against ST_MODE and S_IFMT and compare that to one of the valid values in this package constants (S_IFDIR, S_IFREG, S_IFLNK for example).
FUNCTION HTTP.STDIO.STAT
(
PATH IN VARCHAR2
, BUF OUT STRUCT_STAT
)
RETURN BINARY_INTEGER;
| Parameter | Description |
|---|---|
path |
The fully qualified path and filename you want to stat. |
buf |
A record of type STRUCT_STAT. |
0 if success; -1 if the specified file or directory does not exist. If -1 is returned (and you don't bother to check), all fields in struct stat are set to null.
The following example illustrates how to call stat:
declare
buf stdio.struct_stat;
status binary_integer;
format varchar(30);
begin
status := http.stdio.stat('/opt/home/denis/oracle/develop/secproc.so',buf);
if (status = -1) then
http.writeln('oops!');
end if;
select decode
(
http.bitand(http.stdio.S_IFMT,buf.st_mode)
, http.stdio.S_IFREG, 'file'
, http.stdio.S_IFDIR, 'directory'
, http.stdio.S_IFLNK, 'symbolic link'
, http.stdio.S_IFSOCK, 'socket'
, http.stdio.S_IFDOOR, 'door'
, 'other'
)
into format
from dual;
http.writeln('st_dev = ' || buf.st_dev);
http.writeln('st_ino = ' || buf.st_ino);
http.writeln('st_mode = ' || substr(to_char(buf.st_mode,'XXXX'),2) || ' (' || format || ')');
http.writeln('st_nlink = ' || buf.st_nlink);
http.writeln('st_uid = ' || buf.st_uid);
http.writeln('st_gid = ' || buf.st_gid);
http.writeln('st_rdev = ' || buf.st_rdev);
http.writeln('st_size = ' || buf.st_size);
http.writeln('st_atime = ' || buf.st_atime);
http.writeln('st_mtime = ' || buf.st_mtime);
http.writeln('st_ctime = ' || buf.st_ctime);
end;
The output resembles this:
st_dev = 8388615 st_ino = 558772 st_mode = 81ED (file) st_nlink = 1 st_uid = 14568 st_gid = 100 st_rdev = 0 st_size = 86124 st_atime = Sep 18 2002 09:45PM st_mtime = Sep 18 2002 05:13PM st_ctime = Sep 18 2002 05:13PM
The lstat() function obtains file attributes similar to stat(), except when the named file is a symbolic link; in that case lstat() returns information about the link, while stat() returns information about the file the link references.
FUNCTION HTTP.STDIO.LSTAT
(
PATH IN VARCHAR2
, BUF OUT STRUCT_STAT
)
RETURN BINARY_INTEGER;
| Parameter | Description |
|---|---|
path |
The fully qualified path and filename you want to stat. |
buf |
A record of type STRUCT_STAT. |
Upon successful completion, 0 is returned. Otherwise, -1 is returned and errno is set to indicate the error.
The following example illustrates how to call stat:
declare
buf stdio.struct_stat;
status binary_integer;
format varchar(30);
begin
status := http.stdio.lstat('/opt/home/denis/oracle/develop/secproc.so',buf);
if (status = -1) then
http.writeln('oops!');
end if;
select decode
(
http.bitand(http.stdio.S_IFMT,buf.st_mode)
, http.stdio.S_IFREG, 'file'
, http.stdio.S_IFDIR, 'directory'
, http.stdio.S_IFLNK, 'symbolic link'
, http.stdio.S_IFSOCK, 'socket'
, http.stdio.S_IFDOOR, 'door'
, 'other'
)
into format
from dual;
http.writeln('st_dev = ' || buf.st_dev);
http.writeln('st_ino = ' || buf.st_ino);
http.writeln('st_mode = ' || substr(to_char(buf.st_mode,'XXXX'),2) || ' (' || format || ')');
http.writeln('st_nlink = ' || buf.st_nlink);
http.writeln('st_uid = ' || buf.st_uid);
http.writeln('st_gid = ' || buf.st_gid);
http.writeln('st_rdev = ' || buf.st_rdev);
http.writeln('st_size = ' || buf.st_size);
http.writeln('st_atime = ' || buf.st_atime);
http.writeln('st_mtime = ' || buf.st_mtime);
http.writeln('st_ctime = ' || buf.st_ctime);
end;
The fprintf() function writes formatted output on the specified fildes and returns the number of bytes written to this file.
The format (FMT) is composed of zero or more directives: ordinary characters, which are simply copied to the output stream and conversion specifications, each of which results in the fetching of zero or more arguments. The results are undefined if there are insufficient arguments for the format. If the format is exhausted while arguments remain, the excess arguments are evaluated but are otherwise ignored.
Patterned after its C namesake, the reader should refer to its man page for further documentation.
Function SPRINTF
(
FILDES IN BINARY_INTEGER
, FMT IN VARCHAR2
, ... IN VARCHAR2
)
RETURN BINARY_INTEGER;
| Parameter | Description |
|---|---|
fildes |
The file descriptor returned by CREAT, DUP, DUP2, and OPEN. |
fmt |
Format. |
... |
Zero or more parameters. |
The number of bytes written or -1 if an error occured.
The following example illustrates how to call fprintf:
declare
fildes int;
status int;
nbytes int;
begin
fildes:=http.stdio.open('/opt/home/nobody/nothing','w');
if (fildes = -1) then
http.writeln(http.stdio.strerror(http.stdio.errno));
end if;
nbytes:=http.stdio.fprintf(fildes,'%s\n','Hello World');
if (nbytes = -1) then
http.writeln(http.stdio.strerror(http.stdio.errno));
end if;
status:=http.stdio.close(fildes);
end;
The fstat() function obtains information about an open file known by the file descriptor fildes, obtained from a successful open(), creat(), dup(), fcntl(), or pipe() function.
FUNCTION HTTP.STDIO.FSTAT
(
PATH IN BINARY_INTEGER
, BUF OUT STRUCT_STAT
)
RETURN BINARY_INTEGER;
| Parameter | Description |
|---|---|
fildes |
The file descriptor returned by CREAT, DUP, DUP2, and OPEN. |
buf |
A record of type STRUCT_STAT. |
Upon successful completion, 0 is returned. Otherwise, -1 is returned and errno is set to indicate the error.
The following example illustrates how to call fstat:
declare
buf stdio.struct_stat;
status binary_integer;
format varchar(30);
fildes int;
begin
fildes := http.stdio.open('/opt/home/denis/oracle/develop/secproc.so','r');
if (fildes = -1) then
http.writeln('oops!');
end if;
status := http.stdio.fstat(fildes,buf);
if (status = -1) then
http.writeln('oops!');
end if;
select decode
(
http.bitand(http.stdio.S_IFMT,buf.st_mode)
, http.stdio.S_IFREG, 'file'
, http.stdio.S_IFDIR, 'directory'
, http.stdio.S_IFLNK, 'symbolic link'
, http.stdio.S_IFSOCK, 'socket'
, http.stdio.S_IFDOOR, 'door'
, 'other'
)
into format
from dual;
http.writeln('st_dev = ' || buf.st_dev);
http.writeln('st_ino = ' || buf.st_ino);
http.writeln('st_mode = ' || substr(to_char(buf.st_mode,'XXXX'),2) || ' (' || format || ')');
http.writeln('st_nlink = ' || buf.st_nlink);
http.writeln('st_uid = ' || buf.st_uid);
http.writeln('st_gid = ' || buf.st_gid);
http.writeln('st_rdev = ' || buf.st_rdev);
http.writeln('st_size = ' || buf.st_size);
http.writeln('st_atime = ' || buf.st_atime);
http.writeln('st_mtime = ' || buf.st_mtime);
http.writeln('st_ctime = ' || buf.st_ctime);
end;
This function returns the global error number errno, which is set when errors occur (usually detected by a return result of -1) but not cleared when non-erroneous calls are made.
FUNCTION HTTP.STDIO.ERRNO RETURN BINARY_INTEGER;
errno.
The following block illustrates how to display errno.
begin
http.writeln(http.stdio.errno());
end;
The strerror() function maps the error number in errnum to an error message string, and returns a pointer to that string. It uses the same set of error messages as perror(3C).
FUNCTION HTTP.STDIO.STRERROR
(
ERRNUM IN NUMBER
)
RETURN BINARY_INTEGER;
| Parameter | Description |
|---|---|
errnum |
The error number you are interested in. |
The strerror() function returns NULL if errnum is out-of-range.
The following example illustrates how to interrogate the error message after an error (-1) is returned from OPEN.
declare
fildes int;
status int;
begin
fildes:=http.stdio.open('/opt/home/nobody/nothing','r');
if (fildes = -1) then
http.writeln(http.stdio.strerror(http.stdio.errno));
end if;
status:=http.stdio.close(fildes);
end;
Assuming there was an error, the output would resemble this:
No such file or directory
The lseek() function sets the file pointer associated with the open file descriptor specified by fildes as follows:
The symbolic constants SEEK_SET, SEEK_CUR, and SEEK_END are defined in this package.
Some devices are incapable of seeking. The value of the file pointer associated with such a device is undefined.
The lseek() function allows the file pointer to be set beyond the existing data in the file. If data are later written at this point, subsequent reads in the gap between the previous end of data and the newly written data will return bytes of value 0 until data are written into the gap.
FUNCTION HTTP.STDIO.LSEEK
(
FILDES IN BINARY_INTEGER
, OFFSET IN BINARY_INTEGER
, WHENCE IN BINARY_INTEGER
)
RETURN BINARY_INTEGER;
| Parameter | Description |
|---|---|
fildes |
The file descriptor returned by CREAT, DUP, DUP2, and OPEN. |
offset |
Offset in file. |
whence |
Determines how to position the file. |
Upon successful completion, the resulting offset, as measured in bytes from the beginning of the file, is returned; otherwise, -1 is returned, the file offset remains unchanged, and errno is set to indicate the error.
The following example illustrates how to read the same block indefinitely:
declare
fildes int;
buf varchar(1024);
status int;
begin
fildes:=http.stdio.open('/opt/home/denis/oracle/develop/secproc.c','r');
loop
status := http.stdio.read(fildes,buf);
exit when status < 1;
http.write(buf);
status:=http.stdio.lseek(fildes,0,http.stdio.SEEK_SET));
end loop;
status:=http.stdio.close(fildes);
end;
The unlink() function removes a link to a file. If path names a symbolic link, unlink() removes the symbolic link named by path and does not affect any file or directory named by the contents of the symbolic link. Otherwise, unlink() removes the link named by the pathname pointed to by path and decrements the link count of the file referenced by the link.
FUNCTION HTTP.STDIO.UNLINK
(
PATH IN VARCHAR2
)
RETURN BINARY_INTEGER;
| Parameter | Description |
|---|---|
path |
A fully qualfied path and filename. |
Upon successful completion, 0 is returned; otherwise, -1 is returned, errno is set to indicate the error, and the file is not unlinked.
The following block illustrates how to remove a file:
declare
status int;
begin
status:=unlink('/opt/home/denis/oracle/develop/secproc.c');
if (status = 0) then
http.writeln('Success!');
else
http.writeln('Oops!');
end if;
end;
The rename() function changes the name of a file. The old argument points to the pathname of the file to be renamed. The new argument points to the new pathname of the file.
FUNCTION HTTP.STDIO.RENAME
(
OLD IN VARCHAR2
, NEW IN VARCHAR2
)
RETURN BINARY_INTEGER;
| Parameter | Description |
|---|---|
old |
Absolute path and filename to be changed. |
new |
Absolute path and filename of the new name. |
Upon successful completion, 0 is returned. Otherwise, -1 is returned and errno is set to indicate an error.
The following example illustrates how to rename a file.
declare
status int;
begin
status:=http.stdio.rename('/opt/home/denis/oracle/develop/secproc.c','/opt/home/oracle/secproc.c');
if (status = 0) then
http.writeln('Success!');
else
http.writeln('Oops!');
end if;
end;
This procedure recursively lists all files and directories. It is similar to the -R option of ls.
PROCEDURE HTTP.STDIO.SEARCH
(
PATHNAME IN VARCHAR2
) ;
| Parameter | Description |
|---|---|
pathname |
The directory name to perform this search. |
N/A
The following block illustrate how to call SEARCH.
http.stdio.search('/export/home/psoft');
This procedure is similar to its unix name-sake except that it does not return a result, and instead writes the output of stdout to your browser or the error message returned from pclose.
PROCEDURE HTTP.STDIO.SYSTEM
(
CMD IN VARCHAR2
) ;
| Parameter | Description |
|---|---|
cmd |
The command to execute. |
N/A
The following block illustrate how to issue a ls command:
http.stdio.system('ls -l');
The chmod() and fchmod() functions set the access permission portion of the mode of the file whose name is given by path or referenced by the open file descriptor fildes to the bit pattern contained in mode. Access permission bits are defined in this package. Modes are constructed by the bitwise OR operation of the access permission bits.
FUNCTION HTTP.STDIO.CHMOD
(
PATH IN VARCHAR2
, MODE OUT BINARY_INTEGER
)
RETURN BINARY_INTEGER;
| Parameter | Description |
|---|---|
path |
The absolate path and file name. |
mode |
The mode to change to. |
Upon successful completion, 0 is returned. Otherwise, -1 is returned, the file mode is unchanged, and errno is set to indicate the error.
The following blocks illustrates how to set the permissions on a file:
declare
status int;
begin
status:=http.stdio.chmod
(
'/opt/home/denis/oracle/develop/secproc.c'
, http.stdio.S_IRWXU -- Read, write, execute by owner
+ http.stdio.S_IRWXG -- Read, write, execute by group
+ http.stdio.S_IXOTH -- Execute by others
) ;
if (status = 0) then
http.writeln('Success!');
else
http.writeln('Oops!');
end if;
end;
The chmod() and fchmod() functions set the access permission portion of the mode of the file whose name is given by path or referenced by the open file descriptor fildes to the bit pattern contained in mode. Access permission bits are defined in this package. Modes are constructed by the bitwise OR operation of the access permission bits.
FUNCTION HTTP.STDIO.CHMOD
(
FILDES IN BINARY_INTEGER
, MODE OUT BINARY_INTEGER
)
RETURN BINARY_INTEGER;
| Parameter | Description |
|---|---|
fildes |
The file descriptor returned by CREAT, DUP, DUP2, and OPEN. |
mode |
The mode to change to. |
Upon successful completion, 0 is returned. Otherwise, -1 is returned, the file mode is unchanged, and errno is set to indicate the error.
The following illustrates how to change the permissions on an open file descriptor:
declare
status int;
fildes int;
begin
fildes:=http.stdio.open
(
'/opt/home/denis/oracle/develop/secproc.c'
, 'r'
) ;
status:=http.stdio.fchmod
(
fildes
, http.stdio.S_IRWXU -- Read, write, execute by owner
+ http.stdio.S_IRWXG -- Read, write, execute by group
+ http.stdio.S_IXOTH -- Execute by others
) ;
if (status = 0) then
http.writeln('Success!');
else
http.writeln('Oops!');
end if;
status:=http.stdio.close(fildes);
end;
The chdir() and fchdir() functions cause a directory pointed to by path or fildes to become the current working direc- tory. The starting point for path searches for path names not beginning with / (slash). The path argument points to the path name of a directory. The fildes argument is an open file descriptor of a directory.
FUNCTION HTTP.STDIO.CHDIR
(
PATH IN VARCHAR2
)
RETURN BINARY_INTEGER;
| Parameter | Description |
|---|---|
path |
Path name to change to. |
Upon successful completion, 0 is returned. Otherwise, -1 is returned, the current working directory is unchanged, and errno is set to indicate the error.
The following block illustrates how to change your current working directory:
declare
status int;
begin
status:=http.stdio.chdir('/opt/home/denis');
if (status = 0) then
http.writeln('Success!');
else
http.writeln('Oops!');
end if;
end;
The chdir() and fchdir() functions cause a directory pointed to by path or fildes to become the current working direc- tory. The starting point for path searches for path names not beginning with / (slash). The path argument points to the path name of a directory. The fildes argument is an open file descriptor of a directory.
FUNCTION HTTP.STDIO.FCHDIR
(
FILDES IN BINARY_INTEGER
)
RETURN BINARY_INTEGER;
| Parameter | Description |
|---|---|
fildes |
The file descriptor returned by CREAT, DUP, DUP2, and OPEN. |
Upon successful completion, 0 is returned. Otherwise, -1 is returned, the current working directory is unchanged, and errno is set to indicate the error.
The following block illustrates how to change your working directory with a file descriptor.
declare
status int;
fildes int;
begin
fildes:=http.stdio.open('/opt/home/oracle','r');
if (status = -1) then
http.writeln('Oops!');
else
status:=http.stdio.fchdir(fildes);
if (status = 0) then
http.writeln('Success!');
else
http.writeln('Oops!');
end if;
status:=http.stdio.close(fildes);
end if;
end;
The POPEN() function creates a pipe between the calling program and the command to be executed. In unix-land popen() returns a stream file. Since stream files are not supported by this package, popen() returns a file descriptor as described by OPEN
HTTP.STDIO.POPEN
(
cmd IN VARCHAR2
, mode IN VARCHAR2
)
RETURN BINARY_INTEGER;
| Parameter | Description |
|---|---|
cmd |
Absolute path and file name of the command you wish to invoke. |
mode |
The mode ('r' for read, 'w' for write, 'a' for append) |
Upon successful completion, the popen() function opens the pipe and returns a non-negative integer representing the lowest numbered unused file descriptor. Otherwise, -1 is returned, errno is set to indicate the error, and no files are created or modified.
The following block illustrates how to open a pipe, read that pipe and close the pipe:
declare
stdout varchar2(1024);
status int;
fildes int;
nbytes int;
begin
fildes:=http.stdio.popen('ls -l','r');
if (fildes > 0) then
loop
nbytes:=http.stdio.pgets(fildes,stdout);
exit when nbytes < 1;
http.write(stdout);
end loop;
status:=http.stdio.pclose(fildes);
if (status!=0) then
http.write(http.stdio.strerror(status));
end if;
else
http.write(http.stdio.strerror(http.stdio.errno));
end if;
end;
A stream opened by popen() should be closed by pclose(), which closes the pipe, and waits for the associated process to terminate and returns the termination status of the process running the command language interpreter.
FUNCTION HTTP.STDIO.PCLOSE ( FILDES BINARY_INTEGER ) RETURN BINARY_INTEGER;
| Parameter | Description |
|---|---|
fildes |
The file descriptor returned POPEN. |
-1 if an error occured; otherwise, the exit status of the command you are invoking.
The following block illustrates how to open a pipe, read that pipe and close the pipe:
declare
stdout varchar2(1024);
status int;
fildes int;
nbytes int;
begin
fildes:=http.stdio.popen('ls -l','r');
if (fildes > 0) then
loop
nbytes:=http.stdio.pgets(fildes,stdout);
exit when nbytes < 1;
http.write(stdout);
end loop;
status:=http.stdio.pclose(fildes);
if (status!=0) then
http.write(http.stdio.strerror(status));
end if;
else
http.write(http.stdio.strerror(http.stdio.errno));
end if;
end;
This PGETS() function reads characters from the pipe pointed to by fildes into buf until a newline character is read or an end-of-file condition is encountered.
HTTP.STDIO.PGETS
(
FILDES IN BINARY_INTEGER
, BUF OUT STRUCT_STAT
)
RETURN BINARY_INTEGER;
| Parameter | Description |
|---|---|
fildes |
The file descriptor returned by POPEN. |
buf |
The buffer area where PGETS() places its next input. |
The number of bytes read or -1 if an error occured.
| Exception | Description |
|---|---|
ORA-19011 |
Character string buffer too small. |
The following block illustrates how to open a pipe, read that pipe and close the pipe:
declare
stdout varchar2(1024);
status int;
fildes int;
nbytes int;
begin
fildes:=http.stdio.popen('ls -l','r');
if (fildes > 0) then
loop
nbytes:=http.stdio.pgets(fildes,stdout);
exit when nbytes < 1;
http.write(stdout);
end loop;
status:=http.stdio.pclose(fildes);
if (status!=0) then
http.write(http.stdio.strerror(status));
end if;
else
http.write(http.stdio.strerror(http.stdio.errno));
end if;
end;
The opendir() function opens a directory stream corresponding to the directory named by the dirname argument.
FUNCTION HTTP.STDIO.OPENDIR
(
DIRNAME VARCHAR2
)
RETURN PLS_INTEGER;
| Parameter | Description |
|---|---|
dirname |
The name of the directory to open. |
0 if an error occured; otherwise, a pointer to an object of type DIR.
The following block illustrates how to open a directory, read that directory, and close that directory:
declare
status binary_integer;
dfd binary_integer;
dp http.stdio.dirent;
begin
dfd:=http.stdio.opendir('/export/home/psoft');
if (dfd = 0) then
http.writeln(http.stdio.strerror(http.stdio.errno));
return;
end if;
loop
dp:=http.stdio.readdir(dfd);
exit when http.stdio.isnull(dp);
http.writeln(dp.d_name);
end loop;
status:=http.stdio.closedir(dfd);
if (dfd = -1) then
http.writeln(http.stdio.strerror(http.stdio.errno));
return;
end if;
end;
The closedir() function closes the directory stream referred to by the argument dirp.
FUNCTION HTTP.STDIO.CLOSEDIR
(
DIRP NUMBER
)
RETURN PLS_INTEGER;
| Parameter | Description |
|---|---|
dirp |
The descriptor returned OPENDIR. |
Upon successful completion, closedir() returns 0. Otherwise, -1 is returned and errno is set to indicate the error.
The following block illustrates how to open a directory, read that directory, and close that directorq:
declare
status binary_integer;
dfd binary_integer;
dp http.stdio.dirent;
begin
dfd:=http.stdio.opendir('/export/home/psoft');
if (dfd = 0) then
http.writeln(http.stdio.strerror(http.stdio.errno));
return;
end if;
loop
dp:=http.stdio.readdir(dfd);
exit when http.stdio.isnull(dp);
http.writeln(dp.d_name);
end loop;
status:=http.stdio.closedir(dfd);
if (dfd = -1) then
http.writeln(http.stdio.strerror(http.stdio.errno));
return;
end if;
end;
The readdir() function returns a pointer to a record representing the directory entry at the current position in the directory stream specified by the argument dirp, and positions the directory stream at the next entry. It returns a null pointer upon reaching the end of the directory stream.
FUNCTION HTTP.STDIO.READIR
(
DIRP NUMBER
)
RETURN DIRENT;
| Parameter | Description |
|---|---|
dirp |
The descriptor returned OPENDIR. |
Upon successful completion, readdir() returns a record of type struct dirent. When an error is encountered, a null pointer is returned and errno is set to indicate the error. When the end of the directory is encountered, a null pointer is returned and errno is not changed.
The following block illustrates how to open a directory, read that directory, and close that directory:
declare
status binary_integer;
dfd binary_integer;
dp http.stdio.dirent;
begin
dfd:=http.stdio.opendir('/export/home/psoft');
if (dfd = 0) then
http.writeln(http.stdio.strerror(http.stdio.errno));
return;
end if;
loop
dp:=http.stdio.readdir(dfd);
exit when http.stdio.isnull(dp);
http.writeln(dp.d_name);
end loop;
status:=http.stdio.closedir(dfd);
if (dfd = -1) then
http.writeln(http.stdio.strerror(http.stdio.errno));
return;
end if;
end;
This library is supported by the external process called stdio.so. This example illustrate how to copy the development version on oradev to oraprod.
declare
fd1 int;
fd2 int;
status int;
buf varchar(4096);
begin
/*
** STEP 1 - save a copy of stdio.so
*/
status:=http.stdio.rename@oraprod
(
'/opt/home/oracle/oracle/stdio.so'
, '/opt/home/oracle/oracle/stdio.so.' || to_char(sysdate,'MMDDYYYY')
) ;
/*
** STEP 2 - open stdio.so
*/
fd1:=http.stdio.open
(
'/opt/home/denis/oracle/develop/stdio.so'
, 'r'
) ;
fd2:=http.stdio.open@oraprod
(
'/opt/home/oracle/oracle/stdio.so'
, 'w'
) ;
/*
** STEP 3 - copy
*/
loop
status := http.stdio.read(fd1,buf,1024);
exit when status < 1;
status:=http.stdio.write@oraprod(fd2,buf,status);
end loop;
/*
** STEP 4 - close the files.
*/
status:=http.stdio.close(fd1);
status:=http.stdio.close(fd2);
/*
** STEP 5 - set the permissions
*/
status:=http.stdio.chmod@oraprod
(
'/opt/home/oracle/oracle/stdio.so'
, http.stdio.S_IRWXU -- Read, write, execute by owner
+ http.stdio.S_IRWXG -- Read, write, execute by group
+ http.stdio.S_IXOTH -- Execute by others
) ;
end;
Since there is no error checking, this is a terrible example. A stored procedure would be a better example that not only catches these errors, but also restores the binary, would be more ideal.