commit
9169637084
|
@ -231,12 +231,232 @@ static mode_t fatfs_get_mode(BYTE attribute, mode_t fs_mode)
|
||||||
fs_mode &= ~mask;
|
fs_mode &= ~mask;
|
||||||
if (attribute & AM_DIR) {
|
if (attribute & AM_DIR) {
|
||||||
fs_mode |= S_IFDIR;
|
fs_mode |= S_IFDIR;
|
||||||
|
} else if (attribute & AM_LNK) {
|
||||||
|
fs_mode |= S_IFLNK;
|
||||||
} else {
|
} else {
|
||||||
fs_mode |= S_IFREG;
|
fs_mode |= S_IFREG;
|
||||||
}
|
}
|
||||||
return fs_mode;
|
return fs_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum VnodeType fatfstype_2_vnodetype(BYTE type) {
|
||||||
|
switch (type) {
|
||||||
|
case AM_ARC:
|
||||||
|
return VNODE_TYPE_REG;
|
||||||
|
case AM_DIR:
|
||||||
|
return VNODE_TYPE_DIR;
|
||||||
|
case AM_LNK:
|
||||||
|
return VNODE_TYPE_LNK;
|
||||||
|
default:
|
||||||
|
return VNODE_TYPE_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static FRESULT init_cluster(DIR *dp_new, FATFS *fs, int type, const char *target, DWORD *clust)
|
||||||
|
{
|
||||||
|
FRESULT result;
|
||||||
|
BYTE *dir = NULL;
|
||||||
|
QWORD sect;
|
||||||
|
UINT n;
|
||||||
|
|
||||||
|
/* Allocate a new cluster */
|
||||||
|
*clust = create_chain(&(dp_new->obj), 0);
|
||||||
|
if (*clust == 0) {
|
||||||
|
return FR_NO_SPACE_LEFT;
|
||||||
|
}
|
||||||
|
if (*clust == 1 || *clust == DISK_ERROR) {
|
||||||
|
return FR_DISK_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = sync_window(fs); /* Flush FAT */
|
||||||
|
if (result != FR_OK) {
|
||||||
|
remove_chain(&(dp_new->obj), *clust, 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the new cluster */
|
||||||
|
#ifndef LOSCFG_FS_FAT_VIRTUAL_PARTITION
|
||||||
|
dir = fs->win;
|
||||||
|
#else
|
||||||
|
dir = PARENTFS(fs)->win;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sect = clst2sect(fs, *clust);
|
||||||
|
mem_set(dir, 0, SS(fs));
|
||||||
|
if (type == AM_LNK && target) {
|
||||||
|
/* Write target to symlink */
|
||||||
|
strcpy_s((char *)dir, SS(fs), target);
|
||||||
|
}
|
||||||
|
for (n = fs->csize; n > 0; n--) {
|
||||||
|
#ifndef LOSCFG_FS_FAT_VIRTUAL_PARTITION
|
||||||
|
fs->winsect = sect++;
|
||||||
|
fs->wflag = 1;
|
||||||
|
#else
|
||||||
|
PARENTFS(fs)->winsect = sect++;
|
||||||
|
PARENTFS(fs)->wflag = 1;
|
||||||
|
result = sync_window(fs);
|
||||||
|
if (result != FR_OK) {
|
||||||
|
remove_chain(&(dp_new->obj), *clust, 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (type == AM_LNK) {
|
||||||
|
/* No need to clean the rest sectors of the cluster for symlink */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fatfs_create_obj(struct Vnode *parent, const char *name, int mode, struct Vnode **vpp, BYTE type, const char *target)
|
||||||
|
{
|
||||||
|
struct Vnode *vp = NULL;
|
||||||
|
FATFS *fs = (FATFS *)parent->originMount->data;
|
||||||
|
DIR_FILE *dfp = (DIR_FILE *)parent->data;
|
||||||
|
FILINFO *finfo = &(dfp->fno);
|
||||||
|
DIR_FILE *dfp_new = NULL;
|
||||||
|
FILINFO *finfo_new = NULL;
|
||||||
|
DIR *dp_new = NULL;
|
||||||
|
QWORD time;
|
||||||
|
DWORD hash;
|
||||||
|
DWORD clust = 0;
|
||||||
|
FRESULT result;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((type != AM_ARC) && (type != AM_DIR) && (type != AM_LNK)) {
|
||||||
|
result = FR_INVALID_NAME;
|
||||||
|
goto ERROR_EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
dfp_new = (DIR_FILE *)zalloc(sizeof(DIR_FILE));
|
||||||
|
if (dfp_new == NULL) {
|
||||||
|
result = FR_NOT_ENOUGH_CORE;
|
||||||
|
goto ERROR_EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = lock_fs(fs);
|
||||||
|
if (ret == FALSE) { /* lock failed */
|
||||||
|
result = FR_TIMEOUT;
|
||||||
|
goto ERROR_FREE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (finfo->fattrib & AM_ARC || finfo->fattrib & AM_LNK) {
|
||||||
|
result = FR_NO_DIR;
|
||||||
|
goto ERROR_UNLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
finfo_new = &(dfp_new->fno);
|
||||||
|
LOS_ListInit(&finfo_new->fp_list);
|
||||||
|
dp_new = &(dfp_new->f_dir);
|
||||||
|
dp_new->obj.fs = fs;
|
||||||
|
dp_new->obj.sclust = finfo->sclst;
|
||||||
|
|
||||||
|
DEF_NAMBUF;
|
||||||
|
INIT_NAMBUF(fs);
|
||||||
|
|
||||||
|
result = create_name(dp_new, &name);
|
||||||
|
if (result != FR_OK) {
|
||||||
|
goto ERROR_UNLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = dir_find(dp_new);
|
||||||
|
if (result == FR_OK) {
|
||||||
|
result = FR_EXIST;
|
||||||
|
goto ERROR_UNLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == AM_DIR || type == AM_LNK) {
|
||||||
|
result = init_cluster(dp_new, fs, type, target, &clust);
|
||||||
|
if (result != FR_OK) {
|
||||||
|
goto ERROR_UNLOCK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = dir_register(dp_new);
|
||||||
|
if (result != FR_OK) {
|
||||||
|
goto ERROR_REMOVE_CHAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the directory entry attribute */
|
||||||
|
if (time_status == SYSTEM_TIME_ENABLE) {
|
||||||
|
time = GET_FATTIME();
|
||||||
|
} else {
|
||||||
|
time = 0;
|
||||||
|
}
|
||||||
|
st_dword(dp_new->dir + DIR_CrtTime, time);
|
||||||
|
st_dword(dp_new->dir + DIR_ModTime, time);
|
||||||
|
st_word(dp_new->dir + DIR_LstAccDate, time >> FTIME_DATE_OFFSET);
|
||||||
|
dp_new->dir[DIR_Attr] = type;
|
||||||
|
if (((DWORD)mode & S_IWUSR) == 0) {
|
||||||
|
dp_new->dir[DIR_Attr] |= AM_RDO;
|
||||||
|
}
|
||||||
|
st_clust(fs, dp_new->dir, clust);
|
||||||
|
if (type == AM_ARC) {
|
||||||
|
st_dword(dp_new->dir + DIR_FileSize, 0);
|
||||||
|
} else if (type == AM_LNK) {
|
||||||
|
st_dword(dp_new->dir + DIR_FileSize, strlen(target));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef LOSCFG_FS_FAT_VIRTUAL_PARTITION
|
||||||
|
PARENTFS(fs)->wflag = 1;
|
||||||
|
#else
|
||||||
|
fs->wflag = 1;
|
||||||
|
#endif
|
||||||
|
result = sync_fs(fs);
|
||||||
|
if (result != FR_OK) {
|
||||||
|
goto ERROR_REMOVE_CHAIN;
|
||||||
|
}
|
||||||
|
result = dir_read(dp_new, 0);
|
||||||
|
if (result != FR_OK) {
|
||||||
|
goto ERROR_REMOVE_CHAIN;
|
||||||
|
}
|
||||||
|
dp_new->blk_ofs = dir_ofs(dp_new);
|
||||||
|
get_fileinfo(dp_new, finfo_new);
|
||||||
|
if (type == AM_ARC) {
|
||||||
|
dp_new->obj.objsize = 0;
|
||||||
|
} else if (type == AM_LNK) {
|
||||||
|
dp_new->obj.objsize = strlen(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = VnodeAlloc(&fatfs_vops, &vp);
|
||||||
|
if (ret != 0) {
|
||||||
|
result = FR_NOT_ENOUGH_CORE;
|
||||||
|
goto ERROR_REMOVE_CHAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
vp->parent = parent;
|
||||||
|
vp->fop = &fatfs_fops;
|
||||||
|
vp->data = dfp_new;
|
||||||
|
vp->originMount = parent->originMount;
|
||||||
|
vp->uid = fs->fs_uid;
|
||||||
|
vp->gid = fs->fs_gid;
|
||||||
|
vp->mode = fatfs_get_mode(finfo_new->fattrib, fs->fs_mode);
|
||||||
|
vp->type = fatfstype_2_vnodetype(type);
|
||||||
|
|
||||||
|
hash = fatfs_hash(dp_new->sect, dp_new->dptr, finfo_new->sclst);
|
||||||
|
ret = VfsHashInsert(vp, hash);
|
||||||
|
if (ret != 0) {
|
||||||
|
result = FR_NOT_ENOUGH_CORE;
|
||||||
|
goto ERROR_REMOVE_CHAIN;
|
||||||
|
}
|
||||||
|
*vpp = vp;
|
||||||
|
|
||||||
|
unlock_fs(fs, FR_OK);
|
||||||
|
FREE_NAMBUF();
|
||||||
|
return fatfs_sync(parent->originMount->mountFlags, fs);
|
||||||
|
|
||||||
|
ERROR_REMOVE_CHAIN:
|
||||||
|
remove_chain(&(dp_new->obj), clust, 0);
|
||||||
|
ERROR_UNLOCK:
|
||||||
|
unlock_fs(fs, result);
|
||||||
|
FREE_NAMBUF();
|
||||||
|
ERROR_FREE:
|
||||||
|
free(dfp_new);
|
||||||
|
ERROR_EXIT:
|
||||||
|
return -fatfs_2_vfs(result);
|
||||||
|
}
|
||||||
|
|
||||||
int fatfs_lookup(struct Vnode *parent, const char *path, int len, struct Vnode **vpp)
|
int fatfs_lookup(struct Vnode *parent, const char *path, int len, struct Vnode **vpp)
|
||||||
{
|
{
|
||||||
struct Vnode *vp = NULL;
|
struct Vnode *vp = NULL;
|
||||||
|
@ -336,119 +556,7 @@ ERROR_EXIT:
|
||||||
|
|
||||||
int fatfs_create(struct Vnode *parent, const char *name, int mode, struct Vnode **vpp)
|
int fatfs_create(struct Vnode *parent, const char *name, int mode, struct Vnode **vpp)
|
||||||
{
|
{
|
||||||
struct Vnode *vp = NULL;
|
return fatfs_create_obj(parent, name, mode, vpp, AM_ARC, NULL);
|
||||||
FATFS *fs = (FATFS *)parent->originMount->data;
|
|
||||||
DIR_FILE *dfp;
|
|
||||||
DIR *dp = NULL;
|
|
||||||
FILINFO *finfo = NULL;
|
|
||||||
QWORD time;
|
|
||||||
DWORD hash;
|
|
||||||
FRESULT result;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
dfp = (DIR_FILE *)zalloc(sizeof(DIR_FILE));
|
|
||||||
if (dfp == NULL) {
|
|
||||||
ret = ENOMEM;
|
|
||||||
goto ERROR_EXIT;
|
|
||||||
}
|
|
||||||
ret = lock_fs(fs);
|
|
||||||
if (ret == FALSE) { /* lock failed */
|
|
||||||
ret = EBUSY;
|
|
||||||
goto ERROR_FREE;
|
|
||||||
}
|
|
||||||
|
|
||||||
finfo = &(dfp->fno);
|
|
||||||
LOS_ListInit(&finfo->fp_list);
|
|
||||||
dp = &(dfp->f_dir);
|
|
||||||
dp->obj.fs = fs;
|
|
||||||
dp->obj.sclust = ((DIR_FILE *)(parent->data))->fno.sclst;
|
|
||||||
|
|
||||||
DEF_NAMBUF;
|
|
||||||
INIT_NAMBUF(fs);
|
|
||||||
result = create_name(dp, &name);
|
|
||||||
if (result != FR_OK) {
|
|
||||||
ret = fatfs_2_vfs(result);
|
|
||||||
goto ERROR_UNLOCK;
|
|
||||||
}
|
|
||||||
result = dir_find(dp);
|
|
||||||
if (result == FR_OK) {
|
|
||||||
ret = EEXIST;
|
|
||||||
goto ERROR_UNLOCK;
|
|
||||||
}
|
|
||||||
result = dir_register(dp);
|
|
||||||
if (result != FR_OK) {
|
|
||||||
ret = fatfs_2_vfs(result);
|
|
||||||
goto ERROR_UNLOCK;
|
|
||||||
}
|
|
||||||
/* Set the directory entry attribute */
|
|
||||||
if (time_status == SYSTEM_TIME_ENABLE) {
|
|
||||||
time = GET_FATTIME();
|
|
||||||
} else {
|
|
||||||
time = 0;
|
|
||||||
}
|
|
||||||
st_dword(dp->dir + DIR_CrtTime, time);
|
|
||||||
st_dword(dp->dir + DIR_ModTime, time);
|
|
||||||
st_word(dp->dir + DIR_LstAccDate, time >> FTIME_DATE_OFFSET);
|
|
||||||
dp->dir[DIR_Attr] = AM_ARC;
|
|
||||||
if (((DWORD)mode & S_IWUSR) == 0) {
|
|
||||||
dp->dir[DIR_Attr] |= AM_RDO;
|
|
||||||
}
|
|
||||||
st_clust(fs, dp->dir, 0);
|
|
||||||
st_dword(dp->dir + DIR_FileSize, 0);
|
|
||||||
|
|
||||||
#ifdef LOSCFG_FS_FAT_VIRTUAL_PARTITION
|
|
||||||
PARENTFS(fs)->wflag = 1;
|
|
||||||
#else
|
|
||||||
fs->wflag = 1;
|
|
||||||
#endif
|
|
||||||
result = sync_fs(fs);
|
|
||||||
if (result != FR_OK) {
|
|
||||||
ret = fatfs_2_vfs(result);
|
|
||||||
goto ERROR_UNLOCK;
|
|
||||||
}
|
|
||||||
result = dir_read(dp, 0);
|
|
||||||
if (result != FR_OK) {
|
|
||||||
ret = fatfs_2_vfs(result);
|
|
||||||
goto ERROR_UNLOCK;
|
|
||||||
}
|
|
||||||
dp->blk_ofs = dir_ofs(dp);
|
|
||||||
get_fileinfo(dp, finfo);
|
|
||||||
dp->obj.objsize = 0;
|
|
||||||
|
|
||||||
ret = VnodeAlloc(&fatfs_vops, &vp);
|
|
||||||
if (ret != 0) {
|
|
||||||
ret = ENOMEM;
|
|
||||||
goto ERROR_UNLOCK;
|
|
||||||
}
|
|
||||||
|
|
||||||
vp->parent = parent;
|
|
||||||
vp->fop = &fatfs_fops;
|
|
||||||
vp->data = dfp;
|
|
||||||
vp->originMount = parent->originMount;
|
|
||||||
vp->uid = fs->fs_uid;
|
|
||||||
vp->gid = fs->fs_gid;
|
|
||||||
vp->mode = fatfs_get_mode(finfo->fattrib, fs->fs_mode);
|
|
||||||
vp->type = VNODE_TYPE_REG;
|
|
||||||
|
|
||||||
hash = fatfs_hash(dp->sect, dp->dptr, finfo->sclst);
|
|
||||||
ret = VfsHashInsert(vp, hash);
|
|
||||||
if (ret != 0) {
|
|
||||||
ret = EINVAL;
|
|
||||||
goto ERROR_UNLOCK;
|
|
||||||
}
|
|
||||||
*vpp = vp;
|
|
||||||
|
|
||||||
unlock_fs(fs, result);
|
|
||||||
FREE_NAMBUF();
|
|
||||||
return fatfs_sync(parent->originMount->mountFlags, fs);
|
|
||||||
|
|
||||||
ERROR_UNLOCK:
|
|
||||||
unlock_fs(fs, result);
|
|
||||||
FREE_NAMBUF();
|
|
||||||
ERROR_FREE:
|
|
||||||
free(dfp);
|
|
||||||
ERROR_EXIT:
|
|
||||||
return -ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int fatfs_open(struct file *filep)
|
int fatfs_open(struct file *filep)
|
||||||
|
@ -1690,150 +1798,7 @@ int fatfs_mkfs (struct Vnode *device, int sectors, int option)
|
||||||
|
|
||||||
int fatfs_mkdir(struct Vnode *parent, const char *name, mode_t mode, struct Vnode **vpp)
|
int fatfs_mkdir(struct Vnode *parent, const char *name, mode_t mode, struct Vnode **vpp)
|
||||||
{
|
{
|
||||||
struct Vnode *vp = NULL;
|
return fatfs_create_obj(parent, name, mode, vpp, AM_DIR, NULL);
|
||||||
FATFS *fs = (FATFS *)parent->originMount->data;
|
|
||||||
DIR_FILE *dfp = (DIR_FILE *)parent->data;
|
|
||||||
FILINFO *finfo = &(dfp->fno);
|
|
||||||
DIR_FILE *dfp_new = NULL;
|
|
||||||
QWORD sect;
|
|
||||||
DWORD clust;
|
|
||||||
BYTE *dir = NULL;
|
|
||||||
DWORD hash;
|
|
||||||
FRESULT result = FR_OK;
|
|
||||||
int ret;
|
|
||||||
UINT n;
|
|
||||||
|
|
||||||
ret = lock_fs(fs);
|
|
||||||
if (ret == FALSE) {
|
|
||||||
result = FR_TIMEOUT;
|
|
||||||
goto ERROR_OUT;
|
|
||||||
}
|
|
||||||
if (finfo->fattrib & AM_ARC) {
|
|
||||||
result = FR_NO_DIR;
|
|
||||||
goto ERROR_UNLOCK;
|
|
||||||
}
|
|
||||||
DEF_NAMBUF;
|
|
||||||
INIT_NAMBUF(fs);
|
|
||||||
|
|
||||||
dfp_new = (DIR_FILE *)zalloc(sizeof(DIR_FILE));
|
|
||||||
if (dfp_new == NULL) {
|
|
||||||
result = FR_NOT_ENOUGH_CORE;
|
|
||||||
goto ERROR_UNLOCK;
|
|
||||||
}
|
|
||||||
LOS_ListInit(&(dfp_new->fno.fp_list));
|
|
||||||
dfp_new->f_dir.obj.sclust = finfo->sclst;
|
|
||||||
dfp_new->f_dir.obj.fs = fs;
|
|
||||||
result = create_name(&(dfp_new->f_dir), &name);
|
|
||||||
if (result != FR_OK) {
|
|
||||||
goto ERROR_FREE;
|
|
||||||
}
|
|
||||||
result = dir_find(&(dfp_new->f_dir));
|
|
||||||
if (result == FR_OK) {
|
|
||||||
result = FR_EXIST;
|
|
||||||
goto ERROR_FREE;
|
|
||||||
}
|
|
||||||
/* Allocate new chain for directory */
|
|
||||||
clust = create_chain(&(dfp_new->f_dir.obj), 0);
|
|
||||||
if (clust == 0) {
|
|
||||||
result = FR_NO_SPACE_LEFT;
|
|
||||||
goto ERROR_FREE;
|
|
||||||
}
|
|
||||||
if (clust == 1 || clust == DISK_ERROR) {
|
|
||||||
result = FR_DISK_ERR;
|
|
||||||
goto ERROR_FREE;
|
|
||||||
}
|
|
||||||
result = sync_window(fs); /* Flush FAT */
|
|
||||||
if (result != FR_OK) {
|
|
||||||
goto ERROR_REMOVE_CHAIN;
|
|
||||||
}
|
|
||||||
/* Initialize the new directory */
|
|
||||||
#ifndef LOSCFG_FS_FAT_VIRTUAL_PARTITION
|
|
||||||
dir = fs->win;
|
|
||||||
#else
|
|
||||||
dir = PARENTFS(fs)->win;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
sect = clst2sect(fs, clust);
|
|
||||||
mem_set(dir, 0, SS(fs));
|
|
||||||
for (n = fs->csize; n > 0; n--) { /* Write zero to directory */
|
|
||||||
#ifndef LOSCFG_FS_FAT_VIRTUAL_PARTITION
|
|
||||||
fs->winsect = sect++;
|
|
||||||
fs->wflag = 1;
|
|
||||||
#else
|
|
||||||
PARENTFS(fs)->winsect = sect++;
|
|
||||||
PARENTFS(fs)->wflag = 1;
|
|
||||||
result = sync_window(fs);
|
|
||||||
if (result != FR_OK) break;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result != FR_OK) {
|
|
||||||
goto ERROR_REMOVE_CHAIN;
|
|
||||||
}
|
|
||||||
result = dir_register(&(dfp_new->f_dir));
|
|
||||||
if (result != FR_OK) {
|
|
||||||
goto ERROR_REMOVE_CHAIN;
|
|
||||||
}
|
|
||||||
dir = dfp_new->f_dir.dir;
|
|
||||||
st_dword(dir + DIR_ModTime, 0); /* Set the time */
|
|
||||||
st_clust(fs, dir, clust); /* Set the start cluster */
|
|
||||||
dir[DIR_Attr] = AM_DIR; /* Set the attrib */
|
|
||||||
if ((mode & S_IWUSR) == 0) {
|
|
||||||
dir[DIR_Attr] |= AM_RDO;
|
|
||||||
}
|
|
||||||
#ifndef LOSCFG_FS_FAT_VIRTUAL_PARTITION
|
|
||||||
fs->wflag = 1;
|
|
||||||
#else
|
|
||||||
PARENTFS(fs)->wflag = 1;
|
|
||||||
#endif
|
|
||||||
result = sync_fs(fs);
|
|
||||||
if (result != FR_OK) {
|
|
||||||
goto ERROR_REMOVE_CHAIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the FILINFO struct */
|
|
||||||
result = dir_read(&(dfp_new->f_dir), 0);
|
|
||||||
if (result != FR_OK) {
|
|
||||||
goto ERROR_REMOVE_CHAIN;
|
|
||||||
}
|
|
||||||
dfp_new->f_dir.blk_ofs = dir_ofs(&(dfp_new->f_dir));
|
|
||||||
get_fileinfo(&(dfp_new->f_dir), &(dfp_new->fno));
|
|
||||||
|
|
||||||
ret = VnodeAlloc(&fatfs_vops, &vp);
|
|
||||||
if (ret != 0) {
|
|
||||||
result = FR_NOT_ENOUGH_CORE;
|
|
||||||
goto ERROR_REMOVE_CHAIN;
|
|
||||||
}
|
|
||||||
vp->parent = parent;
|
|
||||||
vp->fop = &fatfs_fops;
|
|
||||||
vp->data = dfp_new;
|
|
||||||
vp->originMount = parent->originMount;
|
|
||||||
vp->uid = fs->fs_uid;
|
|
||||||
vp->gid = fs->fs_gid;
|
|
||||||
vp->mode = fatfs_get_mode(dfp_new->fno.fattrib, fs->fs_mode);
|
|
||||||
vp->type = VNODE_TYPE_DIR;
|
|
||||||
|
|
||||||
hash = fatfs_hash(dfp_new->f_dir.sect, dfp_new->f_dir.dptr, dfp_new->fno.sclst);
|
|
||||||
ret = VfsHashInsert(vp, hash);
|
|
||||||
if (ret != 0) {
|
|
||||||
result = FR_NOT_ENOUGH_CORE;
|
|
||||||
goto ERROR_REMOVE_CHAIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
unlock_fs(fs, FR_OK);
|
|
||||||
FREE_NAMBUF();
|
|
||||||
*vpp = vp;
|
|
||||||
return fatfs_sync(vp->originMount->mountFlags, fs);
|
|
||||||
|
|
||||||
ERROR_REMOVE_CHAIN:
|
|
||||||
remove_chain(&(dfp_new->f_dir.obj), clust, 0);
|
|
||||||
ERROR_FREE:
|
|
||||||
free(dfp_new);
|
|
||||||
ERROR_UNLOCK:
|
|
||||||
unlock_fs(fs, result);
|
|
||||||
FREE_NAMBUF();
|
|
||||||
ERROR_OUT:
|
|
||||||
return -fatfs_2_vfs(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int fatfs_rmdir(struct Vnode *parent, struct Vnode *vp, const char *name)
|
int fatfs_rmdir(struct Vnode *parent, struct Vnode *vp, const char *name)
|
||||||
|
@ -2064,6 +2029,57 @@ ERROR_WITH_DIR:
|
||||||
return -fatfs_2_vfs(result);
|
return -fatfs_2_vfs(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fatfs_symlink(struct Vnode *parentVnode, struct Vnode **newVnode, const char *path, const char *target)
|
||||||
|
{
|
||||||
|
return fatfs_create_obj(parentVnode, path, 0, newVnode, AM_LNK, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t fatfs_readlink(struct Vnode *vnode, char *buffer, size_t bufLen)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
FRESULT res = FR_OK;
|
||||||
|
DWORD clust;
|
||||||
|
QWORD sect;
|
||||||
|
DIR_FILE *dfp = (DIR_FILE *)(vnode->data);
|
||||||
|
DIR *dp = &(dfp->f_dir);
|
||||||
|
FATFS *fs = dp->obj.fs;
|
||||||
|
FILINFO *finfo = &(dfp->fno);
|
||||||
|
size_t targetLen = finfo->fsize;
|
||||||
|
size_t cnt;
|
||||||
|
|
||||||
|
ret = lock_fs(fs);
|
||||||
|
if (ret == FALSE) {
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
clust = finfo->sclst;
|
||||||
|
sect = clst2sect(fs, clust); /* Get current sector */
|
||||||
|
if (sect == 0) {
|
||||||
|
res = FR_DISK_ERR;
|
||||||
|
goto ERROUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (move_window(fs, sect) != FR_OK) {
|
||||||
|
res = FR_DISK_ERR;
|
||||||
|
goto ERROUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
cnt = (bufLen - 1) < targetLen ? (bufLen - 1) : targetLen;
|
||||||
|
ret = LOS_CopyFromKernel(buffer, bufLen, fs->win, cnt);
|
||||||
|
if (ret != EOK) {
|
||||||
|
res = FR_INVALID_PARAMETER;
|
||||||
|
goto ERROUT;
|
||||||
|
}
|
||||||
|
buffer[cnt] = '\0';
|
||||||
|
|
||||||
|
unlock_fs(fs, FR_OK);
|
||||||
|
return cnt;
|
||||||
|
|
||||||
|
ERROUT:
|
||||||
|
unlock_fs(fs, res);
|
||||||
|
return -fatfs_2_vfs(res);
|
||||||
|
}
|
||||||
|
|
||||||
struct VnodeOps fatfs_vops = {
|
struct VnodeOps fatfs_vops = {
|
||||||
/* file ops */
|
/* file ops */
|
||||||
.Getattr = fatfs_stat,
|
.Getattr = fatfs_stat,
|
||||||
|
@ -2083,6 +2099,8 @@ struct VnodeOps fatfs_vops = {
|
||||||
.Mkdir = fatfs_mkdir,
|
.Mkdir = fatfs_mkdir,
|
||||||
.Rmdir = fatfs_rmdir,
|
.Rmdir = fatfs_rmdir,
|
||||||
.Fscheck = fatfs_fscheck,
|
.Fscheck = fatfs_fscheck,
|
||||||
|
.Symlink = fatfs_symlink,
|
||||||
|
.Readlink = fatfs_readlink,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MountOps fatfs_mops = {
|
struct MountOps fatfs_mops = {
|
||||||
|
|
Loading…
Reference in New Issue