📄 api.c
字号:
DROBJ *pobj;
DROBJ *parent_obj;
char path[EMAXPATH];
char filename[FILENAMESIZE]; /* VFAT */
char fileext[4];
BOOLEAN ret_val;
int driveno;
int p_errno;
CHECK_MEM(BOOLEAN, 0) /* Make sure memory is initted */
OS_FS_ENTER()
ret_val = FALSE;
parent_obj = 0;
pobj = 0;
p_errno = PENOENT;
/* Get the drive and make sure it is mounted */
driveno = check_drive(name);
if (driveno < 0)
{
OS_FS_EXIT()
return(FALSE);
}
OS_CLAIM_LOGDRIVE(driveno) /* Register drive in use */
/* Get out the filename and d:parent */
if (!pc_parsepath(path,filename,fileext,name))
goto errex;
#if (VFAT)
if (!validate_filename(filename, tc_strlen(filename)))
goto errex;
#else
if (!validate_filename(filename, 8))
goto errex;
if (!validate_filename(fileext, 3))
goto errex;
#endif
/* Find the parent and make sure it is a directory \ */
parent_obj = pc_fndnode(path);
if (!parent_obj)
goto errex;
/* Lock the parent */
if (!pc_isadir(parent_obj) || pc_isavol(parent_obj))
goto errex;
/* Fail if the directory exists */
pobj = pc_get_inode(0, parent_obj, (byte*)filename,(byte*) fileext, FALSE);
if (pobj)
{
p_errno = PEEXIST; /* Exclusive fail */
}
else
{
pobj = pc_mknode( parent_obj, filename, fileext, ADIRENT);
if (pobj)
{
p_errno = 0;
ret_val = TRUE;
}
else
{
p_errno = PENOSPC;
goto errex;
}
}
errex:
if (pobj)
pc_freeobj(pobj);
if (parent_obj)
{
pc_freeobj(parent_obj);
}
OS_RELEASE_LOGDRIVE(driveno)
/* Restore the kernel state */
set_errno(p_errno);
OS_FS_EXIT()
return(ret_val);
}
#endif /* Subdirs */
#endif /* Write */
/****************************************************************************
PO_OPEN - Open a file.
Description
Open the file for access as specified in flag. If creating use mode to
set the access permissions on the file.
Flag values are
PO_BINARY - Ignored. All file access is binary
PO_char - Ignored
PO_RDONLY - Open for read only
PO_RDWR - Read/write access allowed.
PO_WRONLY - Open for write only
PO_CREAT - Create the file if it does not exist. Use mode to
specify the permission on the file.
PO_EXCL - If flag contains (PO_CREAT | PO_EXCL) and the file already
exists fail and set xn_getlasterror() to EEXIST
PO_TRUNC - Truncate the file if it already exists
PO_NOSHAREANY - Fail if the file is already open. If the open succeeds
no other opens will succeed until it is closed.
PO_NOSHAREWRITE- Fail if the file is already open for write. If the open
succeeds no other opens for write will succeed until it
is closed.
Mode values are
PS_IWRITE - Write permitted
PS_IREAD - Read permitted. (Always true anyway)
Returns
Returns a non-negative integer to be used as a file descriptor for
calling read/write/seek/close otherwise it returns -1 and xn_getlasterror() is set to
one of these values
PENOENT - File not found or path to file not found
PEMFILE - No file descriptors available (too many files open)
PEEXIST - Exclusive access requested but file already exists.
PEACCESS - Attempt to open a read only file or a special (directory)
file.
PENOSPC - Create failed
PESHARE - Already open in exclusive mode or we want exclusive
and its already open
****************************************************************************/
PCFD po_open(char *name, word flag, word mode) /*__fn__*/
{
PCFD fd;
PC_FILE *pfile;
CLUSTERTYPE cluster; /* FAT32 */
DROBJ *parent_obj;
DROBJ *pobj;
char path[EMAXPATH];
char filename[FILENAMESIZE]; /* VFAT */
char fileext[4];
int driveno;
BOOLEAN open_for_write;
#if (RTFS_SHARE)
BOOLEAN sharing_error;
#endif
dword ltemp;
int p_errno;
CHECK_MEM(PCFD, -1) /* Make sure memory is initted */
OS_FS_ENTER()
#if (RTFS_SHARE)
sharing_error = FALSE;
#endif
parent_obj = 0;
open_for_write = FALSE;
#if (RTFS_WRITE)
/* We'll need to know this in a few places. */
if(flag & (PO_WRONLY|PO_RDWR))
open_for_write = TRUE;
#endif
/* Get the drive and make sure it is mounted */
driveno = check_drive(name);
if (driveno < 0)
{
OS_FS_EXIT()
return(-1);
}
if ( (fd = pc_allocfile()) < 0 ) /* Grab a file */
{
p_errno = PEMFILE;
goto errex1;
}
/* Get the FILE. This will never fail */
pfile = pc_fd2file(fd, 0);
/* Paranoia. Set the obj to null until we have one */
pfile->pobj = 0;
OS_CLAIM_LOGDRIVE(driveno) /* Register drive in use */
p_errno = PENOENT;
/* Get out the filename and d:parent */
if (!pc_parsepath(path,filename,fileext,name))
goto errex;
#if (VFAT)
if (!validate_filename(filename, tc_strlen(filename)))
goto errex;
#else
if (!validate_filename(filename, 8))
goto errex;
if (!validate_filename(fileext, 3))
goto errex;
#endif
/* Find the parent */
parent_obj = pc_fndnode(path);
if (!parent_obj)
goto errex;
if (!pc_isadir(parent_obj) || pc_isavol(parent_obj))
goto errex;
pobj = pc_get_inode(0, parent_obj,(byte*)filename,(byte*)fileext, FALSE);
if (pobj)
{
/* If we goto exit: we want them linked so we can clean up */
pfile->pobj = pobj; /* Link the file to the object */
#if (RTFS_SHARE)
/* check the sharing conditions */
sharing_error = FALSE;
if (pobj->finode->opencount != 1)
{
/* The file is already open by someone. Lets see if we are
compatible */
/* 1. We don't want to share with anyone */
if (flag & PO_NOSHAREANY)
sharing_error = TRUE;
/* 2. Someone else doesn't want to share */
if (pobj->finode->openflags & OF_EXCLUSIVE)
sharing_error = TRUE;
/* 3. We want exclusive write but already open for write */
if ( open_for_write && (flag & PO_NOSHAREWRITE) &&
(pobj->finode->openflags & OF_WRITE))
sharing_error = TRUE;
/* 4. We want open for write but it's already open for
exclusive */
if ( (open_for_write) &&
(pobj->finode->openflags & OF_WRITEEXCLUSIVE))
sharing_error = TRUE;
/* 5. Open for trunc when already open */
if (flag & PO_TRUNC)
sharing_error = TRUE;
}
if (sharing_error)
{
p_errno = PESHARE;
goto errex;
}
#endif /* RTFS_SHARE */
if( pc_isadir(pobj) || pc_isavol(pobj) )
{
p_errno = PEACCES; /* is a directory */
goto errex;
}
#if (RTFS_WRITE)
if ( (flag & (PO_EXCL|PO_CREAT)) == (PO_EXCL|PO_CREAT) )
{
p_errno = PEEXIST; /* Exclusive fail */
goto errex;
}
if(open_for_write && (pobj->finode->fattribute & ARDONLY) )
{
p_errno = PEACCES; /* read only file */
goto errex;
}
if (flag & PO_TRUNC)
{
cluster = pc_finode_cluster(pobj->pdrive,pobj->finode); /* FAT32 */
ltemp = pobj->finode->fsize;
pc_pfinode_cluster(pobj->pdrive,pobj->finode,0); /* FAT32 */
pobj->finode->fsize = 0L;
/* Convert to native. Overwrite the existing inode.Set archive/date */
/* Bug fix was:
if (!pc_update_inode(pobj, TRUE, TRUE))
*/
if (pc_update_inode(pobj, TRUE, TRUE))
{
/* And clear up the space */
pc_freechain(pobj->pdrive,cluster);
pc_flushfat(pobj->pdrive->driveno);
}
else
{
pc_pfinode_cluster(pobj->pdrive,pobj->finode,cluster); /* FAT32 */
pobj->finode->fsize = ltemp;
p_errno = PEACCES;
goto errex;
}
}
#endif
}
else /* File not found */
{
#if (RTFS_WRITE)
if (!(flag & PO_CREAT))
{
p_errno = PENOENT; /* File does not exist */
goto errex;
}
/* Do not allow create if write bits not set */
if(!open_for_write)
{
p_errno = PEACCES; /* read only file */
goto errex;
}
/* Create for read only if write perm not allowed */
pobj = pc_mknode( parent_obj, filename, fileext, (byte) ((mode == PS_IREAD) ? ARDONLY : 0));
if (!pobj)
{
p_errno = PENOSPC;
goto errex;
}
pfile->pobj = pobj; /* Link the file to the object */
#else /* Write not built in. Get out */
p_errno = PENOENT; /* File does not exist */
goto errex;
#endif
}
/* Set the file sharing flags in the shared finode structure */
/* clear flags if we just opened it . */
if (pobj->finode->opencount == 1)
pobj->finode->openflags = 0;
#if (RTFS_WRITE)
if (open_for_write)
{
pobj->finode->openflags |= OF_WRITE;
if (flag & PO_NOSHAREWRITE)
pobj->finode->openflags |= OF_WRITEEXCLUSIVE;
}
if (flag & PO_NOSHAREANY)
pobj->finode->openflags |= OF_EXCLUSIVE;
#endif
pfile->flag = flag; /* Access flags */
pfile->fptr = 0L; /* File pointer */
/* Set the cluster and block file pointers */
_synch_file_ptrs(pfile);
p_errno = 0;
if (parent_obj)
{
pc_freeobj(parent_obj);
}
OS_RELEASE_LOGDRIVE(driveno)
/* Restore the kernel state */
set_errno(p_errno);
OS_FS_EXIT()
return(fd);
errex:
pc_freefile(fd);
if (parent_obj)
{
pc_freeobj(parent_obj);
}
OS_RELEASE_LOGDRIVE(driveno)
errex1:
/* Restore the kernel state */
set_errno(p_errno);
OS_FS_EXIT()
return(-1);
}
/****************************************************************************
PO_READ - Read from a file.
Description
Attempt to read count bytes from the current file pointer of file at fd
and put them in buf. The file pointer is updated.
Returns
Returns the number of bytes read or -1 on error.
If the return value is ((word) ~0) (word) -1 xn_getlasterror() will be set
with one of the following:
PENBADF - File descriptor invalid
PENOSPC - File IO error
*****************************************************************************/
//DM: added: po_read() shell and renamed original to _po_read()
/****************************************************************************
AM: To fix for 32 bit compile, created a shell which returns an int value so
that a comparison to -1 will work under 32 bits. Renamed original to _po_read.
*****************************************************************************/
word _po_read(PCFD fd, byte *buf, word count);
int po_read(PCFD fd, byte *buf, word count) /*__fn__*/
{
word return_value;
return_value = _po_read(fd, buf, count);
if (return_value == 0xFFFF)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -