📄 nu_file.c
字号:
* Returns a non-negative integer to be used as a file descriptor.
* Returns a negative integer indicates an error as follows.
* NUF_BAD_USER Not a file user.
* NUF_BADDRIVE Invalid drive specified.
* NUF_NOSPC No space to create directory
* NUF_LONGPATH Path or directory name too
* long.
* NUF_INVNAME Path or filename includes
* invalid character.
* NUF_INVPARM Invalid Flag/Mode is specified.
* NUF_INVPARCMB Invalid Flag/Mode combination
* NUF_PEMFILE No file descriptors.
* available.
* (too many files open)
* NUF_ACCES You can't open the file
* which has Directory or
* VOLLABEL attributes.
* NUF_NOSPC No space to create directory
* in this disk.
* NUF_SHARE The access conflict from
* multiple task to a specific
* file.
* NUF_NOFILE The specified file not
* found.
* NUF_EXIST The directory already exists.
* NUF_NO_BLOCK No block buffer available.
* NUF_NO_FINODE No FINODE buffer available.
* NUF_NO_DROBJ No DROBJ buffer available.
* NUF_IO_ERROR IO error occured.
* NUF_INTERNAL Nucleus FILE internal error.
*
* fs_user->p_errno 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.
* PEACCES 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.
*
*************************************************************************/
INT NU_Open(CHAR *name, UINT16 flag, UINT16 mode)
{
INT fd;
PC_FILE *pfile;
UINT32 cluster;
DROBJ *parent_obj;
DROBJ *pobj;
VOID *path;
VOID *filename;
VOID *fileext;
INT16 driveno;
INT open_for_write;
INT sharing_error;
STATUS ret_stat;
PC_FS_ENTER() /* Must be last line in declarations */
CHECK_USER(INT, NUF_BAD_USER) /* Check if a valid user if multitasking */
sharing_error = NO;
parent_obj = NULL;
pobj = NULL;
/* We'll need to know this in a few places. */
if ( flag & (PO_WRONLY | PO_RDWR ) )
open_for_write = YES;
else
open_for_write = NO;
fs_user->p_errno = 0;
/* Get the drive number */
pc_parsedrive(&driveno, (UINT8 *)name);
if( flag & (~(PO_WRONLY|PO_RDWR|PO_APPEND|
PO_CREAT|PO_TRUNC|PO_EXCL|PO_TEXT|
PO_BINARY|PO_NOSHAREANY|PO_NOSHAREWRITE)))
{
/* Invalid parameter is specified. */
fd = NUF_INVPARM;
}
else if ((flag & PO_TRUNC) && (! open_for_write))
{
/* Invalid parameter combination is specified. */
fd = NUF_INVPARCMB;
}
else if ((flag & PO_APPEND) && (!open_for_write))
{
/* Invalid parameter combination is specified. */
fd = NUF_INVPARCMB;
}
else if ((flag & PO_EXCL) && (!(flag & PO_CREAT)))
{
/* Invalid parameter combination is specified. */
fd = NUF_INVPARCMB;
}
else if ((flag & PO_WRONLY) && (flag & PO_RDWR))
{
/* Invalid parameter combination is specified. */
fd = NUF_INVPARCMB;
}
else if ((flag & PO_TRUNC) && (flag & PO_APPEND))
{
/* Invalid parameter combination is specified. */
fd = NUF_INVPARCMB;
}
else if((mode & (~(PS_IWRITE|PS_IREAD)))||(!(mode)))
{
/* Invalid parameter is specified. */
fd = NUF_INVPARM;
}
else if ((fd = pc_allocfile()) < 0) /* Grab a file */
{
/* File descriptor is not available */
fs_user->p_errno = PEMFILE;
fd = NUF_PEMFILE;
}
else
{
/* Get the FILE. This will never fail */
pfile = pc_fd2file(fd);
/* Paranoia. Set the obj to null until we have one */
pfile->pobj = NULL;
/* Clear the File update flag */
pfile->fupdate = NO;
PC_DRIVE_ENTER(driveno, NO) /* Register drive in use */
/* Get out the filename and d:parent */
ret_stat = pc_parsepath(&path, &filename, &fileext, (UINT8 *)name);
if (ret_stat != NU_SUCCESS)
{
fs_user->p_errno = PENOENT;
pc_freefile(fd);
fd = (INT)ret_stat;
}
else
{
/* Find the parent */
ret_stat = pc_fndnode(driveno, &parent_obj, (UINT8 *)path);
if (ret_stat != NU_SUCCESS)
{
fs_user->p_errno = PENOENT;
pc_freefile(fd);
fd = (INT)ret_stat;
}
else if ( (!pc_isadir(parent_obj)) || (pc_isavol(parent_obj)) )
{
fs_user->p_errno = PENOENT;
pc_freefile(fd);
fd = NUF_ACCES;
pc_freeobj(parent_obj);
}
else
{
PC_INODE_ENTER(parent_obj->finode, YES)
pobj = NULL;
ret_stat = pc_get_inode(&pobj, parent_obj, (UINT8 *)filename);
if (ret_stat == NU_SUCCESS)
{
/* If we goto exit: we want them linked so we can clean up */
pfile->pobj = pobj; /* Link the file to the object */
/* The file is already open by someone. Lets see if we are
compatible */
sharing_error = NO;
/* Check the sharing conditions */
if (pobj->finode->opencount != 1)
{
/* 1. We don't want to share with anyone */
if (flag & PO_NOSHAREANY)
sharing_error = YES;
/* 2. Someone else doesn't want to share */
if (pobj->finode->openflags & OF_EXCLUSIVE)
sharing_error = YES;
/* 3. We want exclusive write but already open for write */
if ( open_for_write && (flag & PO_NOSHAREWRITE) &&
(pobj->finode->openflags & OF_WRITE) )
sharing_error = YES;
/* 4. We want open for write but it's already open for
exclusive */
if ( (open_for_write) &&
(pobj->finode->openflags & OF_WRITEEXCLUSIVE) )
sharing_error = YES;
/* 5. Open for trunc when already open */
if (flag & PO_TRUNC)
sharing_error = YES;
}
if (sharing_error)
{
fs_user->p_errno = PESHARE;
pc_freefile(fd);
fd = NUF_SHARE;
}
else if ( pc_isadir(pobj) || pc_isavol(pobj) )
{
fs_user->p_errno = PEACCES; /* is a directory */
pc_freefile(fd);
fd = NUF_ACCES;
}
else if ( (flag & (PO_EXCL | PO_CREAT)) == (PO_EXCL | PO_CREAT) )
{
fs_user->p_errno = PEEXIST; /* Exclusive fail */
pc_freefile(fd);
fd = NUF_EXIST;
}
else if (flag & PO_TRUNC)
{
cluster = pobj->finode->fcluster;
pobj->finode->fcluster = 0L;
pobj->finode->fsize = 0L;
/* Update an inode to disk. */
ret_stat = pc_update_inode(pobj, DSET_UPDATE);
if (ret_stat == NU_SUCCESS)
{
/* And clear up the space */
PC_FAT_ENTER(pobj->pdrive->driveno)
ret_stat = pc_freechain(pobj->pdrive,cluster);
if (ret_stat == NU_SUCCESS)
ret_stat = pc_flushfat(pobj->pdrive);
PC_FAT_EXIT(pobj->pdrive->driveno)
}
}
if (ret_stat != NU_SUCCESS)
{
fs_user->p_errno = PEACCES;
pc_freefile(fd);
fd = (INT)ret_stat;
}
}
else if (ret_stat == NUF_NOFILE) /* File not found */
{
if (!(flag & PO_CREAT))
{
fs_user->p_errno = PENOENT; /* File does not exist */
pc_freefile(fd);
fd = NUF_NOFILE;
}
/* Do not allow create if write bits not set */
else if (!open_for_write)
{
fs_user->p_errno = PEACCES; /* read only file */
pc_freefile(fd);
fd = NUF_ACCES;
}
else
{
/* Create for read only if write perm not allowed */
ret_stat = pc_mknode(&pobj, parent_obj, (UINT8 *)filename, (UINT8 *)fileext,
(UINT8) ((mode == PS_IREAD) ? (ARDONLY | ARCHIVE) : ARCHIVE));
if (ret_stat == NU_SUCCESS)
{
pfile->pobj = pobj; /* Link the file to the object */
}
else
{
fs_user->p_errno = PENOSPC;
pc_freefile(fd);
fd = (INT)ret_stat;
}
}
}
else /* IO Error */
fd = (INT)ret_stat;
if (fd >= 0) /* No error */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -