/* @(#)device.c 17.1.1.1 (ES0-DMD) 01/25/02 17:47:36 */ /*=========================================================================== Copyright (C) 1995 European Southern Observatory (ESO) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Massachusetss Ave, Cambridge, MA 02139, USA. Corresponding concerning ESO-MIDAS should be addressed as follows: Internet e-mail: midas@eso.org Postal address: European Southern Observatory Data Management Division Karl-Schwarzschild-Strasse 2 D 85748 Garching bei Muenchen GERMANY ===========================================================================*/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .TYPE Module .NAME device.c .LANGUAGE C .AUTHOR Francois Ochsenbein [ESO] .CATEGORY Interface to i/o on devices like tapes / OD / etc .ENVIRONMENT .COMMENTS The functions of this module are just an interface on top of osu routines. They directly call the osu routines and log error messages if any. .VERSION 1.0 02-May-1990: Creation -----------------------------------------------------------------------------*/ #define PM_LEVEL LEVEL_FI /* The Monitoring level for this file */ #include /* Function prototypes & Structures */ #include /* Symbols READ WRITE etc... */ #include /* os-level definitions */ #include /* standard macros */ #include #include #include #include char *osmsg(), *osuname(); static int dev_error (f) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Just report error .RETURNS NOK ----------------------------------------------------------------------*/ int f; /* IN: File number */ { char *p, *ers; char *ltoa(); ers = osmsg(); /* MUST BE DONE BEFORE osuname call */ if_not(p = osuname(f)) p = ltoa(f); ERR_ED_STRING(ers, p); return(NOK); } int dev_stat(f, stat) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Retrieve status of an opened unit .RETURNS OK / NOK ----------------------------------------------------------------------*/ int f; /* IN: The unit number */ struct devstat *stat; /* OUT: Status of the unit */ { int s; ENTER("dev_stat"); s = osustat(f); if (s < 0) s = dev_error(f); else s = OK; EXIT(s); } char *dev_name(f) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Retrieve name of an opened unit .RETURNS Name / NULL pointer if failed ----------------------------------------------------------------------*/ int f; /* IN: The unit number */ { char *p; ENTER("*dev_name"); if_not(p = osuname(f)) dev_error(f); EXITp(p); } long dev_feet(f) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Retrieve length of used tape .RETURNS Length in feet/1000 ----------------------------------------------------------------------*/ int f; /* IN: The unit number */ { long feet, osufeet(); ENTER(".dev_feet"); feet = osufeet(f); EXITl(feet); } int dev_bsize(f) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Get the block size of the unit. .RETURNS The size of blocks for block devices (1 for tapes) ----------------------------------------------------------------------*/ int f; /* IN: The unit number */ { int s; ENTER("dev_bsize"); s = osubsize(f); if (s < 0) dev_error(f); EXIT (s); } int dev_open (device, mode, den) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Assign (mount) a tape with a specified density .RETURNS The device number / NOK on error .REMARKS The default device class is "mt". The mount is performed here. If density is not specified or is zero, use DEFAULT_DENSITY for write-only; get the density otherwise. ----------------------------------------------------------------------*/ char *device; /* IN: The unit name, NULL or blank for NUL device */ int mode; /* IN: open mode: READ, WRITE, READ_WRITE, APPEND */ int den; /* IN: The density/blocksize; 0 if default */ { int f; char *name; ENTER("dev_open"); if_not(name = device) name = ""; if_not(*name) /* NULL device */ name = NULL_DEV; f = osuopen(name, mode, den); if (f <= 0) f = NOK, ERR_ED_STRING(osmsg(), name); EXIT(f); } int dev_close (f, opt) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Close (dismount) a tape / optical disk .RETURNS OK / NOK ----------------------------------------------------------------------*/ int f; /* IN: The unit to dismount */ int opt; /* IN: Option 1 to Dismount */ { int s; ENTER("dev_close"); s = osuclose(f, opt); if (s < 0) s = dev_error(f); else s = OK; EXIT(s); } int dev_read (f, buffer, length) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Read a block from magnetic tape / optical disk. .RETURNS Bytes read (>length if buffer too small) / EOF for error or EOF; .REMARKS The length MUST be a multiple of a sector size for optical disks. The returned length may be zero for virgin sectors. .REMARKS Reading consecutive file marks, it is posible to go further than two file marks. ----------------------------------------------------------------------*/ int f; /* IN: The file control block */ char *buffer; /* OUT: The buffer */ int length; /* IN: The length of the buffer */ { int s; ENTER("dev_read"); s = osuread(f, buffer, length); if (s < 0) dev_error(f); if (s == 0) s = EOF; EXIT(s); } int dev_write (f, buffer, length) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Write a block on magnetic tape / optical disk. .RETURNS Length written / EOF (error) .REMARKS ----------------------------------------------------------------------*/ int f; /* IN: The file control block */ char *buffer; /* IN: The buffer */ int length; /* IN: The length of the buffer */ { int s; ENTER("dev_write"); s = osuwrite(f, buffer, length); if (s < 0) dev_error(f); EXIT(s); } int dev_mark(f) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Close a File (Write a Tape-Mark on the tape) .RETURNS OK / NOK .REMARKS Tape mouvements are optimized. Does nothing if file opened for read-only (returns wihout error) ----------------------------------------------------------------------*/ int f; /* IN: The file control block */ { int s; ENTER("dev_mark"); s = osufclose(f); if (s < 0) s = dev_error(f); else s = OK; EXIT(s); } long dev_fseek (f, offset, mode) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE File seek (Move the tape, i.e. find tape-marks). Identical to osubseek for disks. .RETURNS New file number .REMARKS On return, the tape is always positioned at a file beginning. The tape move is always stopped when two consecutive tape-marks are encountered. ----------------------------------------------------------------------*/ int f; /* IN: Unit Number */ long offset; /* IN : Offset for displacement */ int mode; /* IN : mode of addressing */ { long s, osufseek(); ENTER(".dev_fseek"); s = osufseek(f, offset, mode); if (s < 0) dev_error(f); EXITl(s); } long dev_ftell (f) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Compute current file number .RETURNS Current file number .REMARKS For disks, identical to osubtell. ----------------------------------------------------------------------*/ int f; /* IN: Unit Number */ { long s, osuftell(); ENTER(".dev_ftell"); s = osuftell(f); if (s < 0) dev_error(f); EXITl(s); } long dev_bseek (f, offset, mode) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Block seek: Skip blocks on tape, skip sectors on optical disks. .RETURNS New block number / -1 if error or unknown block number. .REMARKS Seek is stopped by a tape-mark, BUT the tape-mark is skipped. Disk: Simply set the position. ----------------------------------------------------------------------*/ int f; /* IN: Unit Number */ long offset; /* IN : Offset for displacement */ int mode; /* IN : mode of addressing */ { long s, osubseek(); ENTER(".dev_bseek"); s = osubseek(f, offset, mode); if (s < 0) dev_error(f); EXITl(s); } long dev_btell (f) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Compute current block / sector number .RETURNS Current block number (in current file) .REMARKS ----------------------------------------------------------------------*/ int f; /* IN: Unit Number */ { long s, osubtell(); ENTER(".dev_btell"); s = osubtell(f); if (s < 0) dev_error(f); EXITl(s); }