123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989 |
- /*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2023-05-05 Bernard Implement file APIs in dfs v2.0
- */
- #include "errno.h"
- #include "fcntl.h"
- #include <dfs.h>
- #include "dfs_file.h"
- #include "dfs_dentry.h"
- #include "dfs_fs.h"
- #include "dfs_mnt.h"
- #include "dfs_private.h"
- #define DBG_TAG "DFS.file"
- #define DBG_LVL DBG_WARNING
- #include <rtdbg.h>
- #define MAX_RW_COUNT 0xfffc0000
- /*
- * rw_verify_area doesn't like huge counts. We limit
- * them to something that fits in "int" so that others
- * won't have to do range checks all the time.
- */
- ssize_t rw_verify_area(struct dfs_file *file, off_t *ppos, size_t count)
- {
- off_t pos;
- ssize_t retval = -EINVAL;
- if ((size_t)count < 0)
- return retval;
- pos = *ppos;
- if (pos < 0)
- {
- if (count >= -pos) /* both values are in 0..LLONG_MAX */
- return -EOVERFLOW;
- }
- return count > MAX_RW_COUNT ? MAX_RW_COUNT : count;
- }
- void dfs_file_set_fpos(struct dfs_file *file, off_t fpos)
- {
- if (file)
- {
- rt_mutex_take(&file->pos_lock, RT_WAITING_FOREVER);
- file->fpos = fpos;
- rt_mutex_release(&file->pos_lock);
- }
- }
- void dfs_file_init(struct dfs_file *file)
- {
- if (file)
- {
- rt_memset(file, 0x00, sizeof(struct dfs_file));
- file->magic = DFS_FD_MAGIC;
- rt_mutex_init(&file->pos_lock, "fpos", RT_IPC_FLAG_PRIO);
- rt_atomic_store(&(file->ref_count), 1);
- }
- }
- void dfs_file_deinit(struct dfs_file *file)
- {
- if (file)
- {
- rt_mutex_detach(&file->pos_lock);
- }
- }
- static void dfs_file_unref(struct dfs_file *file)
- {
- rt_err_t ret = RT_EOK;
- ret = dfs_file_lock();
- if (ret == RT_EOK)
- {
- if (rt_atomic_load(&(file->ref_count)) == 1)
- {
- /* should release this file */
- if (file->dentry)
- {
- DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_unref(dentry(%s))", file->dentry->pathname);
- dfs_dentry_unref(file->dentry);
- file->dentry = RT_NULL;
- }
- else if (file->vnode)
- {
- if (file->vnode->ref_count > 1)
- {
- file->vnode->ref_count--;
- }
- else if (file->vnode->ref_count == 1)
- {
- rt_free(file->vnode);
- file->vnode = RT_NULL;
- }
- }
- LOG_I("release a file: %p", file);
- }
- dfs_file_unlock();
- }
- }
- struct dfs_dentry* dfs_file_follow_link(struct dfs_dentry *dentry)
- {
- int ret = 0;
- if (dentry && dentry->vnode && dentry->vnode->type == FT_SYMLINK)
- {
- char *buf = NULL;
- buf = (char *) rt_malloc (DFS_PATH_MAX);
- if (buf)
- {
- do
- {
- ret = dentry->mnt->fs_ops->readlink(dentry, buf, DFS_PATH_MAX);
- if (ret > 0)
- {
- struct dfs_mnt *mnt = NULL;
- if (buf[0] != '/')
- {
- char *dir = dfs_dentry_pathname(dentry);
- /* is the relative directory */
- if (dir)
- {
- char *fullpath = dfs_normalize_path(dir, buf);
- if (fullpath)
- {
- strncpy(buf, fullpath, DFS_PATH_MAX);
- rt_free(fullpath);
- }
- rt_free(dir);
- }
- }
- mnt = dfs_mnt_lookup(buf);
- if (mnt)
- {
- struct dfs_dentry *de = dfs_dentry_lookup(mnt, buf, 0);
- /* release the old dentry */
- dfs_dentry_unref(dentry);
- dentry = de;
- }
- }
- else
- {
- break;
- }
- } while (dentry && dentry->vnode->type == FT_SYMLINK);
- }
- rt_free(buf);
- }
- return dentry;
- }
- /*
- * this function is creat a nolink path.
- *
- * @param mnt
- * @param fullpath
- * @param mode 0 middle path nolink; 1 all path nolink.
- *
- * @return new path.
- */
- static char *dfs_nolink_path(struct dfs_mnt **mnt, char *fullpath, int mode)
- {
- int index = 0;
- char *path = RT_NULL;
- char link_fn[DFS_PATH_MAX] = {0};
- struct dfs_dentry *dentry = RT_NULL;
- path = (char *)rt_malloc(DFS_PATH_MAX);
- if (!path)
- {
- return path;
- }
- if (*mnt && fullpath)
- {
- int i = 0;
- char *fp = fullpath;
- while (*fp != '\0')
- {
- fp++;
- i++;
- if (*fp == '/')
- {
- rt_memcpy(path + index, fp - i, i);
- path[index + i] = '\0';
- dentry = dfs_dentry_lookup(*mnt, path, 0);
- if (dentry && dentry->vnode->type == FT_SYMLINK)
- {
- int ret = -1;
- if ((*mnt)->fs_ops->readlink)
- {
- ret = (*mnt)->fs_ops->readlink(dentry, link_fn, DFS_PATH_MAX);
- }
- if (ret > 0)
- {
- int len = rt_strlen(link_fn);
- if (link_fn[0] == '/')
- {
- rt_memcpy(path, link_fn, len);
- index = len;
- }
- else
- {
- path[index] = '/';
- index++;
- rt_memcpy(path + index, link_fn, len);
- index += len;
- }
- path[index] = '\0';
- *mnt = dfs_mnt_lookup(path);
- }
- else
- {
- rt_kprintf("link error: %s\n", path);
- }
- }
- else
- {
- index += i;
- }
- dfs_dentry_unref(dentry);
- i = 0;
- }
- }
- if (i)
- {
- rt_memcpy(path + index, fp - i, i);
- path[index + i] = '\0';
- if (mode)
- {
- dentry = dfs_dentry_lookup(*mnt, path, 0);
- if (dentry && dentry->vnode->type == FT_SYMLINK)
- {
- int ret = -1;
- if ((*mnt)->fs_ops->readlink)
- {
- ret = (*mnt)->fs_ops->readlink(dentry, link_fn, DFS_PATH_MAX);
- }
- if (ret > 0)
- {
- int len = rt_strlen(link_fn);
- if (link_fn[0] == '/')
- {
- rt_memcpy(path, link_fn, len);
- index = len;
- }
- else
- {
- path[index] = '/';
- index++;
- rt_memcpy(path + index, link_fn, len);
- index += len;
- }
- path[index] = '\0';
- *mnt = dfs_mnt_lookup(path);
- }
- else
- {
- rt_kprintf("link error: %s\n", path);
- }
- }
- dfs_dentry_unref(dentry);
- }
- }
- }
- else
- {
- rt_free(path);
- path = RT_NULL;
- }
- //rt_kprintf("%s: %s => %s\n", __FUNCTION__, fullpath, path);
- return path;
- }
- /**
- * this function will open a file which specified by path with specified oflags.
- *
- * @param fd the file descriptor pointer to return the corresponding result.
- * @param path the specified file path.
- * @param oflags the oflags for open operator.
- *
- * @return 0 on successful, -1 on failed.
- */
- int dfs_file_open(struct dfs_file *file, const char *path, int oflags, mode_t mode)
- {
- int ret = -RT_ERROR;;
- char *fullpath = RT_NULL;
- struct dfs_dentry *dentry = RT_NULL;
- int fflags = dfs_fflags(oflags);
- if (mode == 0)
- {
- mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); /* 0666 */
- }
- if (file && path)
- {
- fullpath = dfs_normalize_path(NULL, path);
- if (fullpath)
- {
- struct dfs_mnt *mnt = RT_NULL;
- DLOG(msg, "dfs_file", "mnt", DLOG_MSG, "dfs_mnt_lookup(%s)", fullpath);
- mnt = dfs_mnt_lookup(fullpath);
- if (mnt)
- {
- char *tmp = dfs_nolink_path(&mnt, fullpath, 0);
- if (tmp)
- {
- rt_free(fullpath);
- fullpath = tmp;
- }
- DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_lookup(mnt, %s)", fullpath);
- dentry = dfs_dentry_lookup(mnt, fullpath, oflags);
- if (dentry && dentry->vnode->type == FT_SYMLINK)
- {
- /* it's a symbol link but not follow */
- if (oflags & O_NOFOLLOW)
- {
- /* no follow symbol link */
- dfs_dentry_unref(dentry);
- dentry = RT_NULL;
- }
- else
- {
- struct dfs_dentry *target_dentry = RT_NULL;
- /* follow symbol link */
- target_dentry = dfs_file_follow_link(dentry);
- if (target_dentry)
- {
- dentry = target_dentry;
- }
- }
- }
- if (dentry)
- {
- if (oflags & O_DIRECTORY)
- {
- if (dentry->vnode->type != FT_DIRECTORY)
- {
- dfs_dentry_unref(dentry);
- dentry = RT_NULL;
- }
- }
- else if (dentry->vnode->type == FT_DIRECTORY)
- {
- if (fflags & (DFS_F_FWRITE))
- {
- dfs_dentry_unref(dentry);
- dentry = RT_NULL;
- }
- else
- {
- oflags |= O_DIRECTORY;
- }
- }
- }
- if (oflags & O_CREAT)
- {
- if (dentry)
- {
- oflags &= ~O_CREAT;
- if (oflags & O_EXCL)
- {
- oflags &= ~O_EXCL;
- /* the dentry already exists */
- dfs_dentry_unref(dentry);
- dentry = RT_NULL;
- }
- }
- else
- {
- /* create file/directory */
- if (mnt->fs_ops->create_vnode)
- {
- struct dfs_vnode *vnode = RT_NULL;
- DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_create(%s)", fullpath);
- dentry = dfs_dentry_create(mnt, fullpath);
- if (dentry)
- {
- mode &= ~S_IFMT;
- DLOG(msg, "dfs_file", mnt->fs_ops->name, DLOG_MSG, "fs_ops->create_vnode");
- vnode = mnt->fs_ops->create_vnode(dentry, oflags & O_DIRECTORY ? FT_DIRECTORY:FT_REGULAR, mode);
- if (vnode)
- {
- /* set vnode */
- dentry->vnode = vnode; /* the refcount of created vnode is 1. no need to reference */
- dfs_dentry_insert(dentry);
- }
- else
- {
- DLOG(msg, mnt->fs_ops->name, "dfs_file", DLOG_MSG_RET, "create failed.");
- dfs_dentry_unref(dentry);
- dentry = RT_NULL;
- }
- }
- }
- }
- }
- if (dentry)
- {
- rt_bool_t permission = RT_TRUE;
- file->dentry = dentry;
- file->vnode = dentry->vnode;
- file->fops = dentry->mnt->fs_ops->default_fops;
- file->flags = oflags;
- /* check permission */
- if (!(oflags & O_CREAT))
- {
- if (fflags & DFS_F_FWRITE)
- {
- if (!(file->vnode->mode & S_IWUSR))
- {
- permission = RT_FALSE;
- }
- }
- if (fflags & DFS_F_FREAD)
- {
- if (!(file->vnode->mode & S_IRUSR))
- {
- permission = RT_FALSE;
- }
- }
- if (oflags & O_EXEC)
- {
- if (!(file->vnode->mode & S_IXUSR))
- {
- permission = RT_FALSE;
- }
- }
- }
- if (permission && file->fops->open)
- {
- DLOG(msg, "dfs_file", mnt->fs_ops->name, DLOG_MSG, "fops->open(file)");
- ret = file->fops->open(file);
- if (ret < 0)
- {
- LOG_E("open %s failed in file system: %s", path, dentry->mnt->fs_ops->name);
- DLOG(msg, mnt->fs_ops->name, "dfs_file", DLOG_MSG_RET, "open failed.");
- dfs_file_unref(file);
- }
- else
- {
- /* for char/block device */
- if ((S_ISCHR(file->vnode->mode)) || (S_ISBLK(file->vnode->mode)))
- {
- file->fops = file->vnode->fops;
- }
- }
- }
- else
- {
- DLOG(msg, "dfs_file", mnt->fs_ops->name, DLOG_MSG, "no permission or fops->open");
- dfs_file_unref(file);
- }
- }
- else
- {
- LOG_I("lookup file:%s failed in file system", path);
- }
- }
- rt_free(fullpath);
- }
- if (ret >= 0 && (oflags & O_TRUNC))
- {
- /* trunc file */
- if (!(fflags & DFS_F_FWRITE) || file->vnode->type == FT_DIRECTORY)
- {
- /* truncate on read a only file or a directory */
- DLOG(msg, "dfs_file", "dfs_file", DLOG_MSG, "dfs_file_unref(file), trunc on RDOnly or directory");
- ret = -RT_ERROR;
- }
- else
- {
- if (file->fops->truncate)
- {
- DLOG(msg, "dfs_file", dentry->mnt->fs_ops->name, DLOG_MSG, "fops->truncate(file, 0)");
- ret = file->fops->truncate(file, 0);
- }
- }
- if (ret < 0)
- {
- dfs_file_unref(file);
- }
- file->flags &= ~O_TRUNC;
- }
- }
- return ret;
- }
- int dfs_file_close(struct dfs_file *file)
- {
- int ret = -RT_ERROR;
- if (file)
- {
- if (dfs_file_lock() == RT_EOK)
- {
- rt_atomic_t ref_count = rt_atomic_load(&(file->ref_count));
- if (ref_count == 1 && file->fops && file->fops->close)
- {
- DLOG(msg, "dfs_file", file->dentry->mnt->fs_ops->name, DLOG_MSG, "fops->close(file)");
- ret = file->fops->close(file);
- if (ret == 0) /* close file sucessfully */
- {
- DLOG(msg, "dfs_file", "dfs_file", DLOG_MSG, "dfs_file_unref(file)");
- dfs_file_unref(file);
- }
- else
- {
- LOG_W("close file:%s failed on low level file system", file->dentry->pathname);
- }
- }
- else
- {
- DLOG(msg, "dfs_file", "dfs_file", DLOG_MSG, "dfs_file_unref(file)");
- dfs_file_unref(file);
- ret = 0;
- }
- dfs_file_unlock();
- }
- }
- return ret;
- }
- ssize_t dfs_file_read(struct dfs_file *file, void *buf, size_t len)
- {
- ssize_t ret = -EBADF;
- if (file)
- {
- /* check whether read */
- if (!(dfs_fflags(file->flags) & DFS_F_FREAD))
- {
- ret = -EPERM;
- }
- else if (!file->fops || !file->fops->read)
- {
- ret = -ENOSYS;
- }
- else if (file->vnode && file->vnode->type != FT_DIRECTORY)
- {
- off_t pos;
- pos = file->fpos;
- ret = rw_verify_area(file, &pos, len);
- if (ret > 0)
- {
- len = ret;
- ret = file->fops->read(file, buf, len, &pos);
- if (ret > 0)
- {
- dfs_file_set_fpos(file, pos);
- }
- }
- }
- }
- return ret;
- }
- ssize_t dfs_file_write(struct dfs_file *file, const void *buf, size_t len)
- {
- size_t ret = -EBADF;
- if (file)
- {
- if (!(dfs_fflags(file->flags) & DFS_F_FWRITE))
- {
- LOG_W("bad write flags.");
- ret = -EBADF;
- }
- else if (!file->fops || !file->fops->write)
- {
- LOG_W("no fops write.");
- ret = -ENOSYS;
- }
- else if (file->vnode && file->vnode->type != FT_DIRECTORY)
- {
- off_t pos;
- pos = file->fpos;
- ret = rw_verify_area(file, &pos, len);
- if (ret > 0)
- {
- len = ret;
- DLOG(msg, "dfs_file", file->dentry->mnt->fs_ops->name, DLOG_MSG,
- "dfs_file_write(fd, buf, %d)", len);
- ret = file->fops->write(file, buf, len, &pos);
- if (ret > 0)
- {
- dfs_file_set_fpos(file, pos);
- }
- }
- }
- }
- return ret;
- }
- int generic_dfs_lseek(struct dfs_file *file, off_t offset, int whence)
- {
- off_t foffset;
- if (whence == SEEK_SET)
- foffset = offset;
- else if (whence == SEEK_CUR)
- foffset = file->fpos + offset;
- else if (whence == SEEK_END)
- foffset = file->vnode->size + offset;
- else
- return -EINVAL;
- dfs_file_set_fpos(file, foffset);
- return foffset;
- }
- off_t dfs_file_lseek(struct dfs_file *file, off_t offset, int wherece)
- {
- off_t retval;
- if (!file)
- return -EBADF;
- retval = -EINVAL;
- if (file->fops->lseek)
- {
- retval = file->fops->lseek(file, offset, wherece);
- if (retval >= 0)
- {
- dfs_file_set_fpos(file, retval);
- }
- }
- return retval;
- }
- int dfs_file_stat(const char *path, struct stat *buf)
- {
- int ret = -ENOENT;
- char *fullpath = RT_NULL;
- struct dfs_mnt *mnt = RT_NULL;
- struct dfs_dentry *dentry = RT_NULL;
- fullpath = dfs_normalize_path(NULL, path);
- if (fullpath)
- {
- DLOG(msg, "dfs_file", "mnt", DLOG_MSG, "dfs_mnt_lookup(%s)", fullpath);
- mnt = dfs_mnt_lookup(fullpath);
- if (mnt)
- {
- char *tmp = dfs_nolink_path(&mnt, fullpath, 1);
- if (tmp)
- {
- rt_free(fullpath);
- fullpath = tmp;
- }
- DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dentry = dfs_dentry_lookup(mnt, %s)", fullpath);
- dentry = dfs_dentry_lookup(mnt, fullpath, 0);
- if (dentry)
- {
- DLOG(msg, "dentry", "dfs_file", DLOG_MSG_RET, "return dentry");
- if (mnt->fs_ops->stat)
- {
- DLOG(msg, "dfs_file", mnt->fs_ops->name, DLOG_MSG, "fs_ops->stat(dentry, buf)");
- ret = mnt->fs_ops->stat(dentry, buf);
- }
- /* unref dentry */
- DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_unref(dentry)");
- dfs_dentry_unref(dentry);
- dentry = RT_NULL;
- }
- }
- rt_free(fullpath);
- fullpath = RT_NULL;
- }
- else
- {
- ret = -ENOMEM;
- }
- return ret;
- }
- int dfs_file_lstat(const char *path, struct stat *buf)
- {
- int ret = -ENOENT;
- char *fullpath = RT_NULL;
- struct dfs_mnt *mnt = RT_NULL;
- struct dfs_dentry *dentry = RT_NULL;
- fullpath = dfs_normalize_path(NULL, path);
- if (fullpath)
- {
- DLOG(msg, "dfs_file", "mnt", DLOG_MSG, "dfs_mnt_lookup(%s)", fullpath);
- mnt = dfs_mnt_lookup(fullpath);
- if (mnt)
- {
- char *tmp = dfs_nolink_path(&mnt, fullpath, 0);
- if (tmp)
- {
- rt_free(fullpath);
- fullpath = tmp;
- }
- DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dentry = dfs_dentry_lookup(mnt, %s)", fullpath);
- dentry = dfs_dentry_lookup(mnt, fullpath, 0);
- if (dentry)
- {
- DLOG(msg, "dentry", "dfs_file", DLOG_MSG_RET, "return dentry");
- if (mnt->fs_ops->stat)
- {
- DLOG(msg, "dfs_file", mnt->fs_ops->name, DLOG_MSG, "fs_ops->stat(dentry, buf)");
- ret = mnt->fs_ops->stat(dentry, buf);
- }
- /* unref dentry */
- DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_unref(dentry)");
- dfs_dentry_unref(dentry);
- dentry = RT_NULL;
- }
- }
- rt_free(fullpath);
- fullpath = RT_NULL;
- }
- else
- {
- ret = -ENOMEM;
- }
- rt_set_errno(-ret);
- return ret;
- }
- int dfs_file_fstat(struct dfs_file *file, struct stat *buf)
- {
- size_t ret = -EBADF;
- if (file)
- {
- if (file->fops && file->fops->ioctl)
- {
- // ret = file->fops->fstat(file, buf);
- }
- else
- {
- ret = -ENOSYS;
- }
- }
- else
- {
- ret = -EBADF;
- }
- return ret;
- }
- int dfs_file_setattr(const char *path, struct dfs_attr *attr)
- {
- int ret = -RT_ERROR;
- char *fullpath = RT_NULL;
- struct dfs_mnt *mnt = RT_NULL;
- struct dfs_dentry *dentry = RT_NULL;
- fullpath = dfs_normalize_path(NULL, path);
- if (fullpath)
- {
- DLOG(msg, "dfs_file", "mnt", DLOG_MSG, "dfs_mnt_lookup(%s)", fullpath);
- mnt = dfs_mnt_lookup(fullpath);
- if (mnt)
- {
- char *tmp = dfs_nolink_path(&mnt, fullpath, 0);
- if (tmp)
- {
- rt_free(fullpath);
- fullpath = tmp;
- }
- DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dentry = dfs_dentry_lookup(mnt, %s)", fullpath);
- dentry = dfs_dentry_lookup(mnt, fullpath, 0);
- if (dentry)
- {
- DLOG(msg, "dentry", "dfs_file", DLOG_MSG_RET, "return dentry");
- if (mnt->fs_ops->setattr)
- {
- DLOG(msg, "dfs_file", mnt->fs_ops->name, DLOG_MSG, "fs_ops->setattr(dentry, attr)");
- ret = mnt->fs_ops->setattr(dentry, attr);
- }
- /* unref dentry */
- DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_unref(dentry)");
- dfs_dentry_unref(dentry);
- dentry = RT_NULL;
- }
- }
- rt_free(fullpath);
- fullpath = RT_NULL;
- }
- return ret;
- }
- int dfs_file_ioctl(struct dfs_file *file, int cmd, void *args)
- {
- size_t ret = 0;
- if (file)
- {
- if (file->fops && file->fops->ioctl)
- {
- ret = file->fops->ioctl(file, cmd, args);
- }
- else
- {
- ret = -ENOSYS;
- }
- }
- else
- {
- ret = -EBADF;
- }
- return ret;
- }
- int dfs_file_fcntl(int fd, int cmd, unsigned long arg)
- {
- int ret = 0;
- struct dfs_file *file;
- file = fd_get(fd);
- if (file)
- {
- switch (cmd)
- {
- case F_DUPFD:
- ret = dfs_dup(fd, arg);
- break;
- case F_GETFD:
- ret = file->mode;
- break;
- case F_SETFD:
- file->mode = arg;
- break;
- case F_GETFL:
- ret = file->flags;
- break;
- case F_SETFL:
- file->flags = arg;
- break;
- case F_GETLK:
- break;
- case F_SETLK:
- case F_SETLKW:
- break;
- default:
- ret = -EPERM;
- break;
- }
- }
- else
- {
- ret = -EBADF;
- }
- return ret;
- }
- int dfs_file_fsync(struct dfs_file *file)
- {
- int ret = -EBADF;
- if (file)
- {
- if (file->fops->flush)
- {
- ret = file->fops->flush(file);
- }
- }
- return ret;
- }
- int dfs_file_unlink(const char *path)
- {
- int ret = -RT_ERROR;
- char *fullpath = RT_NULL;
- struct dfs_mnt *mnt = RT_NULL;
- struct dfs_dentry *dentry = RT_NULL;
- fullpath = dfs_normalize_path(NULL, path);
- if (fullpath)
- {
- DLOG(msg, "dfs_file", "mnt", DLOG_MSG, "dfs_mnt_lookup(%s)", fullpath);
- mnt = dfs_mnt_lookup(fullpath);
- if (mnt)
- {
- char *tmp = dfs_nolink_path(&mnt, fullpath, 0);
- if (tmp)
- {
- rt_free(fullpath);
- fullpath = tmp;
- }
- if (strcmp(mnt->fullpath, fullpath) != 0)
- {
- DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_lookup(mnt, %s)", fullpath);
- dentry = dfs_dentry_lookup(mnt, fullpath, 0);
- if (dentry)
- {
- rt_bool_t has_child = RT_FALSE;
- has_child = dfs_mnt_has_child_mnt(mnt, fullpath);
- if (has_child == RT_FALSE && rt_atomic_load(&(dentry->ref_count)) == 1)
- {
- /* no child mnt point, unlink it */
- ret = -RT_ERROR;
- if (mnt->fs_ops->unlink)
- {
- ret = mnt->fs_ops->unlink(dentry);
- }
- }
- else
- {
- ret = -EBUSY;
- }
- /* release this dentry */
- dfs_dentry_unref(dentry);
- }
- else
- {
- /* no this entry */
- ret = -ENOENT;
- }
- }
- else
- {
- /* it's a mount point, failed for busy */
- ret = -EBUSY;
- }
- }
- else
- {
- ret = -ENOENT;
- }
- /* release fullpath */
- rt_free(fullpath);
- }
- else
- {
- ret = -ENOMEM;
- }
- return ret;
- }
- int dfs_file_link(const char *oldname, const char *newname)
- {
- int ret = -1;
- struct stat stat;
- struct dfs_mnt *mnt = RT_NULL;
- char *old_fullpath, *new_fullpath;
- if (dfs_file_isdir(oldname) == 0)
- {
- return ret;
- }
- if (dfs_file_lstat(newname, &stat) >= 0)
- {
- return ret;
- }
- old_fullpath = dfs_normalize_path(NULL, oldname);
- if (old_fullpath)
- {
- DLOG(msg, "dfs_file", "mnt", DLOG_MSG, "dfs_mnt_lookup(%s)", old_fullpath);
- mnt = dfs_mnt_lookup(old_fullpath);
- if (mnt == RT_NULL)
- {
- rt_free(old_fullpath);
- return -1;
- }
- char *tmp = dfs_nolink_path(&mnt, old_fullpath, 0);
- if (tmp)
- {
- rt_free(old_fullpath);
- old_fullpath = tmp;
- }
- }
- new_fullpath = dfs_normalize_path(NULL, newname);
- if (new_fullpath)
- {
- char *tmp = dfs_nolink_path(&mnt, new_fullpath, 0);
- if (tmp)
- {
- rt_free(new_fullpath);
- new_fullpath = tmp;
- }
- }
- if (old_fullpath && new_fullpath)
- {
- struct dfs_dentry *old_dentry, *new_dentry;
- DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_lookup(mnt, %s)", old_fullpath);
- old_dentry = dfs_dentry_lookup(mnt, old_fullpath, 0);
- DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_create(%s)", new_fullpath);
- new_dentry = dfs_dentry_create(mnt, new_fullpath);
- if (old_dentry && new_dentry)
- {
- if (mnt->fs_ops->link)
- {
- ret = mnt->fs_ops->link(old_dentry, new_dentry);
- }
- }
- dfs_dentry_unref(old_dentry);
- dfs_dentry_unref(new_dentry);
- }
- if (old_fullpath)
- {
- rt_free(old_fullpath);
- }
- if (new_fullpath)
- {
- rt_free(new_fullpath);
- }
- return ret;
- }
- /* symlink creates a symbolic link named `linkpath` which contains the string `target`. */
- int dfs_file_symlink(const char *target, const char *linkpath)
- {
- int ret = -RT_ERROR;
- char *fullpath = RT_NULL, *parent = RT_NULL;
- struct dfs_mnt *mnt = RT_NULL;
- struct dfs_dentry *dentry = RT_NULL;
- if (target && linkpath)
- {
- if (linkpath[0] != '/')
- {
- fullpath = dfs_normalize_path(NULL, linkpath);
- }
- else
- {
- fullpath = (char*)linkpath;
- }
- /* linkpath should be not exist */
- if (dfs_file_access(fullpath, O_RDONLY) != 0)
- {
- char *index;
- /* get parent path */
- index = strrchr(fullpath, '/');
- if (index)
- {
- int length = index - fullpath;
- if (length > 0)
- {
- parent = (char*) rt_malloc (length + 1);
- if (parent)
- {
- memcpy(parent, fullpath, length);
- parent[length] = '\0';
- }
- }
- else
- {
- parent = (char*) rt_malloc (1 + 1);
- if (parent)
- {
- parent[0] = '/';
- parent[1] = '\0';
- }
- }
- }
- if (parent)
- {
- DLOG(msg, "dfs_file", "mnt", DLOG_MSG, "dfs_mnt_lookup(%s)", fullpath);
- mnt = dfs_mnt_lookup(parent);
- if (mnt)
- {
- char *tmp = dfs_nolink_path(&mnt, parent, 0);
- if (tmp)
- {
- rt_free(parent);
- parent = tmp;
- }
- DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_lookup(mnt, %s)", fullpath);
- dentry = dfs_dentry_lookup(mnt, parent, 0);
- if (dentry)
- {
- if (dentry->mnt->fs_ops->symlink)
- {
- char *path = dfs_normalize_path(NULL, target);
- if (path)
- {
- char *tmp = dfs_nolink_path(&mnt, path, 0);
- if (tmp)
- {
- rt_free(path);
- path = tmp;
- }
- else
- {
- tmp = path;
- }
- if (dfs_file_access(path, O_RDONLY) == 0)
- {
- ret = rt_strncmp(parent, path, strlen(parent));
- if (ret == 0)
- {
- tmp = path + strlen(parent);
- if (*tmp == '/')
- {
- tmp ++;
- }
- }
- ret = mnt->fs_ops->symlink(dentry, tmp, index + 1);
- }
- else
- {
- ret = -ENOENT;
- }
- rt_free(path);
- }
- }
- else
- {
- ret = -ENOSYS;
- }
- dfs_dentry_unref(dentry);
- }
- else
- {
- ret = -ENOENT;
- }
- }
- else
- {
- ret = -ENOENT;
- }
- rt_free(parent);
- }
- }
- if (fullpath != linkpath)
- rt_free(fullpath);
- }
- else
- {
- ret = -EINVAL;
- }
- return ret;
- }
- int dfs_file_readlink(const char *path, char *buf, int bufsize)
- {
- int ret = -RT_ERROR;
- char *fullpath = RT_NULL;
- struct dfs_mnt *mnt = RT_NULL;
- struct dfs_dentry *dentry = RT_NULL;
- fullpath = dfs_normalize_path(NULL, path);
- if (fullpath)
- {
- DLOG(msg, "dfs_file", "mnt", DLOG_MSG, "dfs_mnt_lookup(%s)", fullpath);
- mnt = dfs_mnt_lookup(fullpath);
- if (mnt)
- {
- char *tmp = dfs_nolink_path(&mnt, fullpath, 0);
- if (tmp)
- {
- rt_free(fullpath);
- fullpath = tmp;
- }
- DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_lookup(mnt, %s)", fullpath);
- dentry = dfs_dentry_lookup(mnt, fullpath, 0);
- if (dentry)
- {
- if (mnt->fs_ops->readlink)
- {
- ret = mnt->fs_ops->readlink(dentry, buf, bufsize);
- }
- else
- {
- ret = -ENOSYS;
- }
- /* release this dentry */
- dfs_dentry_unref(dentry);
- }
- else
- {
- /* no this entry */
- ret = -ENOENT;
- }
- }
- else
- {
- ret = -ENOENT;
- }
- /* release fullpath */
- rt_free(fullpath);
- }
- else
- {
- ret = -ENOMEM;
- }
- return ret;
- }
- int dfs_file_rename(const char *old_file, const char *new_file)
- {
- int ret = -1;
- struct dfs_mnt *mnt = RT_NULL;
- char *old_fullpath, *new_fullpath;
- old_fullpath = dfs_normalize_path(NULL, old_file);
- if (old_fullpath)
- {
- DLOG(msg, "dfs_file", "mnt", DLOG_MSG, "dfs_mnt_lookup(%s)", old_fullpath);
- mnt = dfs_mnt_lookup(old_fullpath);
- if (mnt == RT_NULL)
- {
- rt_free(old_fullpath);
- return -1;
- }
- char *tmp = dfs_nolink_path(&mnt, old_fullpath, 0);
- if (tmp)
- {
- rt_free(old_fullpath);
- old_fullpath = tmp;
- }
- }
- new_fullpath = dfs_normalize_path(NULL, new_file);
- if (new_fullpath)
- {
- char *tmp = dfs_nolink_path(&mnt, new_fullpath, 0);
- if (tmp)
- {
- rt_free(new_fullpath);
- new_fullpath = tmp;
- }
- }
- if (old_fullpath && new_fullpath)
- {
- struct dfs_dentry *old_dentry, *new_dentry;
- DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_lookup(mnt, %s)", old_fullpath);
- old_dentry = dfs_dentry_lookup(mnt, old_fullpath, 0);
- DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_create(%s)", new_fullpath);
- new_dentry = dfs_dentry_create(mnt, new_fullpath);
- if (old_dentry && new_dentry)
- {
- if (mnt->fs_ops->rename)
- {
- ret = mnt->fs_ops->rename(old_dentry, new_dentry);
- }
- }
- dfs_dentry_unref(old_dentry);
- dfs_dentry_unref(new_dentry);
- }
- if (old_fullpath)
- {
- rt_free(old_fullpath);
- }
- if (new_fullpath)
- {
- rt_free(new_fullpath);
- }
- return ret;
- }
- int dfs_file_ftruncate(struct dfs_file *file, off_t length)
- {
- int ret = 0;
- if (file)
- {
- if (file->fops->truncate)
- {
- ret = file->fops->truncate(file, length);
- }
- else
- {
- ret = -ENOSYS;
- }
- }
- else
- {
- ret = -EBADF;
- }
- return ret;
- }
- int dfs_file_flush(struct dfs_file *file)
- {
- int ret = 0;
- if (file)
- {
- if (file->fops->flush)
- {
- ret = file->fops->flush(file);
- }
- else
- {
- ret = -ENOSYS;
- }
- }
- else
- {
- ret = -EBADF;
- }
- return ret;
- }
- int dfs_file_getdents(struct dfs_file *file, struct dirent *dirp, size_t nbytes)
- {
- int ret = -RT_ERROR;
- if (file)
- {
- if (file->vnode && S_ISDIR(file->vnode->mode))
- {
- if (file->fops && file->fops->getdents)
- {
- DLOG(msg, "dfs_file", file->dentry->mnt->fs_ops->name, DLOG_MSG, "fops->getdents()");
- ret = file->fops->getdents(file, dirp, nbytes);
- }
- }
- }
- else
- {
- ret = -EBADF;
- }
- return ret;
- }
- /**
- * this function will check the path is it a directory.
- *
- * @param path the file path.
- *
- * @return 0 on is dir, -1 on not dir.
- */
- int dfs_file_isdir(const char *path)
- {
- int ret = -RT_ERROR;
- char *fullpath = RT_NULL;
- struct dfs_mnt *mnt = RT_NULL;
- struct dfs_dentry *dentry = RT_NULL;
- fullpath = dfs_normalize_path(NULL, path);
- if (fullpath)
- {
- DLOG(msg, "dfs_file", "mnt", DLOG_MSG, "dfs_mnt_lookup(%s)", fullpath);
- mnt = dfs_mnt_lookup(fullpath);
- if (mnt)
- {
- char *tmp = dfs_nolink_path(&mnt, fullpath, 1);
- if (tmp)
- {
- rt_free(fullpath);
- fullpath = tmp;
- }
- DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dentry = dfs_dentry_lookup(mnt, %s)", fullpath);
- dentry = dfs_dentry_lookup(mnt, fullpath, 0);
- if (dentry)
- {
- DLOG(msg, "dentry", "dfs_file", DLOG_MSG_RET, "return dentry");
- if (mnt->fs_ops->stat)
- {
- struct stat stat = {0};
- DLOG(msg, "dfs_file", mnt->fs_ops->name, DLOG_MSG, "fs_ops->stat(dentry, buf)");
- ret = mnt->fs_ops->stat(dentry, &stat);
- if (ret == RT_EOK && S_ISDIR(stat.st_mode))
- {
- ret = RT_EOK;
- }
- else
- {
- ret = -RT_ERROR;
- }
- }
- /* unref dentry */
- DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_unref(dentry)");
- dfs_dentry_unref(dentry);
- dentry = RT_NULL;
- }
- }
- rt_free(fullpath);
- fullpath = RT_NULL;
- }
- return ret;
- }
- int dfs_file_access(const char *path, mode_t mode)
- {
- int ret;
- struct dfs_file file;
- dfs_file_init(&file);
- if (dfs_file_open(&file, path, O_RDONLY, mode) >= 0)
- {
- ret = 0;
- dfs_file_close(&file);
- }
- else
- {
- ret = -1;
- }
- dfs_file_deinit(&file);
- return ret;
- }
- int dfs_file_mmap2(struct dfs_file *file, struct dfs_mmap2_args *mmap2)
- {
- int ret = 0;
- if (file && mmap2)
- {
- if (file->vnode->type != FT_DEVICE || !file->vnode->fops->ioctl)
- {
- rt_set_errno(EINVAL);
- }
- else if (file->vnode->type == FT_DEVICE && file->vnode->fops->ioctl)
- {
- ret = file->vnode->fops->ioctl(file, RT_FIOMMAP2, mmap2);
- if (ret != 0)
- {
- ret = ret > 0 ? ret : -ret;
- rt_set_errno(ret);
- }
- }
- }
- return ret;
- }
- #ifdef RT_USING_FINSH
- #define _COLOR_RED "\033[31m"
- #define _COLOR_GREEN "\033[32m"
- #define _COLOR_BLUE "\033[34m"
- #define _COLOR_CYAN "\033[36m"
- #define _COLOR_WHITE "\033[37m"
- #define _COLOR_NORMAL "\033[0m"
- void ls(const char *pathname)
- {
- struct dirent dirent;
- struct stat stat;
- int length;
- char *fullpath, *path;
- struct dfs_file file;
- if (pathname == NULL)
- {
- #ifdef DFS_USING_WORKDIR
- /* open current working directory */
- path = rt_strdup(working_directory);
- #else
- path = rt_strdup("/");
- #endif
- if (path == NULL)
- {
- return; /* out of memory */
- }
- }
- else
- {
- path = dfs_normalize_path(NULL, (char *)pathname);
- if (path == NULL)
- {
- return; /* out of memory */
- }
- }
- dfs_file_init(&file);
- /* list directory */
- DLOG(msg, "dfs", "dfs_file", DLOG_MSG, "dfs_file_open(%s, O_DIRECTORY, 0)", path);
- if (dfs_file_open(&file, path, O_DIRECTORY, 0) >= 0)
- {
- char *link_fn = (char *) rt_malloc (DFS_PATH_MAX);
- if (link_fn)
- {
- rt_kprintf("Directory %s:\n", path);
- do
- {
- memset(&dirent, 0, sizeof(struct dirent));
- DLOG(group, "foreach_item");
- DLOG(msg, "dfs", "dfs_file", DLOG_MSG, "dfs_file_getdents(&dirent)");
- length = dfs_file_getdents(&file, &dirent, sizeof(struct dirent));
- if (length > 0)
- {
- DLOG(msg, "dfs_file", "dfs", DLOG_MSG_RET, "dirent.d_name=%s", dirent.d_name);
- memset(&stat, 0, sizeof(struct stat));
- /* build full path for each file */
- fullpath = dfs_normalize_path(path, dirent.d_name);
- if (fullpath == NULL)
- break;
- DLOG(msg, "dfs", "dfs_file", DLOG_MSG, "dfs_file_lstat(%s, &stat)", fullpath);
- if (dfs_file_lstat(fullpath, &stat) == 0)
- {
- if (S_ISDIR(stat.st_mode))
- {
- rt_kprintf(_COLOR_BLUE "%-20s" _COLOR_NORMAL, dirent.d_name);
- rt_kprintf("%-25s\n", "<DIR>");
- }
- else if (S_ISLNK(stat.st_mode))
- {
- int ret = 0;
- rt_kprintf(_COLOR_CYAN "%-20s" _COLOR_NORMAL, dirent.d_name);
- ret = dfs_file_readlink(fullpath, link_fn, DFS_PATH_MAX);
- if (ret > 0)
- {
- char *link_path = link_fn;
- struct dfs_mnt *mnt = RT_NULL;
- mnt = dfs_mnt_lookup(fullpath);
- if (mnt)
- {
- char *tmp = dfs_nolink_path(&mnt, fullpath, 0);
- if (tmp)
- {
- char *index;
- index = strrchr(fullpath, '/');
- if (index)
- {
- int length = index - fullpath;
- char *parent = (char*) rt_malloc (length + 1);
- if (parent)
- {
- rt_memcpy(parent, fullpath, length);
- parent[length] = '\0';
- ret = rt_strncmp(parent, link_fn, length);
- if (ret == 0)
- {
- link_path = link_fn + length;
- if (*link_path == '/')
- {
- link_path ++;
- }
- }
- rt_free(parent);
- }
- }
- rt_free(tmp);
- }
- }
- rt_kprintf("-> %s\n", link_path);
- }
- else
- {
- rt_kprintf(_COLOR_RED "-> link_error\n" _COLOR_NORMAL);
- }
- }
- else if (stat.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))
- {
- rt_kprintf(_COLOR_GREEN "%-20s" _COLOR_NORMAL, dirent.d_name);
- rt_kprintf("%-25lu\n", (unsigned long)stat.st_size);
- }
- else
- {
- rt_kprintf("%-20s", dirent.d_name);
- rt_kprintf("%-25lu\n", (unsigned long)stat.st_size);
- }
- }
- else
- {
- rt_kprintf(_COLOR_RED "%-20s" _COLOR_NORMAL, dirent.d_name);
- }
- rt_free(fullpath);
- }
- else
- {
- DLOG(msg, "dfs_file", "dfs", DLOG_MSG_RET, "return NULL");
- }
- DLOG(group_end);
- } while (length > 0);
- rt_free(link_fn);
- }
- DLOG(msg, "dfs", "dfs_file", DLOG_MSG, "dfs_file_close()");
- dfs_file_close(&file);
- }
- else
- {
- rt_kprintf("No such directory\n");
- }
- dfs_file_deinit(&file);
- DLOG(msg, "dfs_file", "dfs", DLOG_MSG_RET, "return");
- rt_free(path);
- }
- void cat(const char *filename)
- {
- int length = 0;
- char buffer[81];
- struct dfs_file file;
- if (filename && dfs_file_isdir(filename) == 0)
- {
- rt_kprintf("cat: %s Is a directory\n", filename);
- return;
- }
- dfs_file_init(&file);
- DLOG(msg, "dfs", "dfs_file", DLOG_MSG, "dfs_file_open(%s, O_RDONLY, 0)", filename);
- if (dfs_file_open(&file, filename, O_RDONLY, 0) < 0)
- {
- rt_kprintf("Open %s failed\n", filename);
- dfs_file_deinit(&file);
- return;
- }
- do
- {
- rt_memset(buffer, 0x0, sizeof(buffer));
- DLOG(msg, "dfs", "dfs_file", DLOG_MSG, "dfs_file_read(fd, buffer, %d)", sizeof(buffer) - 1);
- length = dfs_file_read(&file, (void *)buffer, sizeof(buffer) - 1);
- if (length > 0)
- {
- buffer[length] = '\0';
- rt_kprintf("%s", buffer);
- }
- } while (length > 0);
- rt_kprintf("\n");
- DLOG(msg, "dfs", "dfs_file", DLOG_MSG, "dfs_file_close()");
- dfs_file_close(&file);
- dfs_file_deinit(&file);
- }
- #define BUF_SZ 4096
- static void copyfile(const char *src, const char *dst)
- {
- int ret;
- struct dfs_file src_file, dst_file;
- rt_uint8_t *block_ptr;
- rt_int32_t read_bytes;
- block_ptr = (rt_uint8_t *)rt_malloc(BUF_SZ);
- if (block_ptr == NULL)
- {
- rt_kprintf("out of memory\n");
- return;
- }
- dfs_file_init(&src_file);
- ret = dfs_file_open(&src_file, src, O_RDONLY, 0);
- if (ret < 0)
- {
- dfs_file_deinit(&src_file);
- rt_free(block_ptr);
- rt_kprintf("Read %s failed\n", src);
- return;
- }
- dfs_file_init(&dst_file);
- ret = dfs_file_open(&dst_file, dst, O_WRONLY | O_CREAT, 0);
- if (ret < 0)
- {
- dfs_file_deinit(&dst_file);
- dfs_file_close(&src_file);
- dfs_file_deinit(&src_file);
- rt_free(block_ptr);
- rt_kprintf("Write %s failed\n", dst);
- return;
- }
- do
- {
- read_bytes = dfs_file_read(&src_file, block_ptr, BUF_SZ);
- if (read_bytes > 0)
- {
- int length;
- length = dfs_file_write(&dst_file, block_ptr, read_bytes);
- if (length != read_bytes)
- {
- /* write failed. */
- rt_kprintf("Write file data failed, errno=%d\n", length);
- break;
- }
- }
- } while (read_bytes > 0);
- dfs_file_close(&dst_file);
- dfs_file_deinit(&dst_file);
- dfs_file_close(&src_file);
- dfs_file_deinit(&src_file);
- rt_free(block_ptr);
- }
- extern int mkdir(const char *path, mode_t mode);
- static void copydir(const char *src, const char *dst)
- {
- struct dirent dirent;
- struct stat stat;
- int length;
- struct dfs_file file;
- dfs_file_init(&file);
- if (dfs_file_open(&file, src, O_DIRECTORY, 0) < 0)
- {
- rt_kprintf("open %s failed\n", src);
- dfs_file_deinit(&file);
- return ;
- }
- do
- {
- rt_memset(&dirent, 0, sizeof(struct dirent));
- length = dfs_file_getdents(&file, &dirent, sizeof(struct dirent));
- if (length > 0)
- {
- char *src_entry_full = NULL;
- char *dst_entry_full = NULL;
- if (strcmp(dirent.d_name, "..") == 0 || strcmp(dirent.d_name, ".") == 0)
- continue;
- /* build full path for each file */
- if ((src_entry_full = dfs_normalize_path(src, dirent.d_name)) == NULL)
- {
- rt_kprintf("out of memory!\n");
- break;
- }
- if ((dst_entry_full = dfs_normalize_path(dst, dirent.d_name)) == NULL)
- {
- rt_kprintf("out of memory!\n");
- rt_free(src_entry_full);
- break;
- }
- rt_memset(&stat, 0, sizeof(struct stat));
- if (dfs_file_lstat(src_entry_full, &stat) != 0)
- {
- rt_kprintf("open file: %s failed\n", dirent.d_name);
- continue;
- }
- if (S_ISDIR(stat.st_mode))
- {
- mkdir(dst_entry_full, 0);
- copydir(src_entry_full, dst_entry_full);
- }
- else
- {
- copyfile(src_entry_full, dst_entry_full);
- }
- rt_free(src_entry_full);
- rt_free(dst_entry_full);
- }
- }
- while (length > 0);
- dfs_file_close(&file);
- dfs_file_deinit(&file);
- }
- static const char *_get_path_lastname(const char *path)
- {
- char *ptr;
- if ((ptr = (char *)strrchr(path, '/')) == NULL)
- return path;
- /* skip the '/' then return */
- return ++ptr;
- }
- void copy(const char *src, const char *dst)
- {
- #define FLAG_SRC_TYPE 0x03
- #define FLAG_SRC_IS_DIR 0x01
- #define FLAG_SRC_IS_FILE 0x02
- #define FLAG_SRC_NON_EXSIT 0x00
- #define FLAG_DST_TYPE 0x0C
- #define FLAG_DST_IS_DIR 0x04
- #define FLAG_DST_IS_FILE 0x08
- #define FLAG_DST_NON_EXSIT 0x00
- struct stat stat;
- uint32_t flag = 0;
- /* check the staus of src and dst */
- if (dfs_file_lstat(src, &stat) < 0)
- {
- rt_kprintf("copy failed, bad %s\n", src);
- return;
- }
- if (S_ISDIR(stat.st_mode))
- flag |= FLAG_SRC_IS_DIR;
- else
- flag |= FLAG_SRC_IS_FILE;
- if (dfs_file_stat(dst, &stat) < 0)
- {
- flag |= FLAG_DST_NON_EXSIT;
- }
- else
- {
- if (S_ISDIR(stat.st_mode))
- flag |= FLAG_DST_IS_DIR;
- else
- flag |= FLAG_DST_IS_FILE;
- }
- //2. check status
- if ((flag & FLAG_SRC_IS_DIR) && (flag & FLAG_DST_IS_FILE))
- {
- rt_kprintf("cp faild, cp dir to file is not permitted!\n");
- return ;
- }
- //3. do copy
- if (flag & FLAG_SRC_IS_FILE)
- {
- if (flag & FLAG_DST_IS_DIR)
- {
- char *fdst;
- fdst = dfs_normalize_path(dst, _get_path_lastname(src));
- if (fdst == NULL)
- {
- rt_kprintf("out of memory\n");
- return;
- }
- copyfile(src, fdst);
- rt_free(fdst);
- }
- else
- {
- copyfile(src, dst);
- }
- }
- else //flag & FLAG_SRC_IS_DIR
- {
- if (flag & FLAG_DST_IS_DIR)
- {
- char *fdst;
- fdst = dfs_normalize_path(dst, _get_path_lastname(src));
- if (fdst == NULL)
- {
- rt_kprintf("out of memory\n");
- return;
- }
- mkdir(fdst, 0);
- copydir(src, fdst);
- rt_free(fdst);
- }
- else if ((flag & FLAG_DST_TYPE) == FLAG_DST_NON_EXSIT)
- {
- mkdir(dst, 0);
- copydir(src, dst);
- }
- else
- {
- copydir(src, dst);
- }
- }
- }
- FINSH_FUNCTION_EXPORT(copy, copy file or dir)
- #endif
|