1*10465441SEvalZero /*
2*10465441SEvalZero * Copyright (c) 2006-2018, RT-Thread Development Team
3*10465441SEvalZero *
4*10465441SEvalZero * SPDX-License-Identifier: Apache-2.0
5*10465441SEvalZero *
6*10465441SEvalZero * Change Logs:
7*10465441SEvalZero * Date Author Notes
8*10465441SEvalZero * 2009-05-27 Yi.qiu The first version
9*10465441SEvalZero * 2018-02-07 Bernard Change the 3rd parameter of open/fcntl/ioctl to '...'
10*10465441SEvalZero */
11*10465441SEvalZero
12*10465441SEvalZero #include <dfs.h>
13*10465441SEvalZero #include <dfs_posix.h>
14*10465441SEvalZero #include "dfs_private.h"
15*10465441SEvalZero
16*10465441SEvalZero /**
17*10465441SEvalZero * @addtogroup FsPosixApi
18*10465441SEvalZero */
19*10465441SEvalZero
20*10465441SEvalZero /*@{*/
21*10465441SEvalZero
22*10465441SEvalZero /**
23*10465441SEvalZero * this function is a POSIX compliant version, which will open a file and
24*10465441SEvalZero * return a file descriptor according specified flags.
25*10465441SEvalZero *
26*10465441SEvalZero * @param file the path name of file.
27*10465441SEvalZero * @param flags the file open flags.
28*10465441SEvalZero *
29*10465441SEvalZero * @return the non-negative integer on successful open, others for failed.
30*10465441SEvalZero */
open(const char * file,int flags,...)31*10465441SEvalZero int open(const char *file, int flags, ...)
32*10465441SEvalZero {
33*10465441SEvalZero int fd, result;
34*10465441SEvalZero struct dfs_fd *d;
35*10465441SEvalZero
36*10465441SEvalZero /* allocate a fd */
37*10465441SEvalZero fd = fd_new();
38*10465441SEvalZero if (fd < 0)
39*10465441SEvalZero {
40*10465441SEvalZero rt_set_errno(-ENOMEM);
41*10465441SEvalZero
42*10465441SEvalZero return -1;
43*10465441SEvalZero }
44*10465441SEvalZero d = fd_get(fd);
45*10465441SEvalZero
46*10465441SEvalZero result = dfs_file_open(d, file, flags);
47*10465441SEvalZero if (result < 0)
48*10465441SEvalZero {
49*10465441SEvalZero /* release the ref-count of fd */
50*10465441SEvalZero fd_put(d);
51*10465441SEvalZero fd_put(d);
52*10465441SEvalZero
53*10465441SEvalZero rt_set_errno(result);
54*10465441SEvalZero
55*10465441SEvalZero return -1;
56*10465441SEvalZero }
57*10465441SEvalZero
58*10465441SEvalZero /* release the ref-count of fd */
59*10465441SEvalZero fd_put(d);
60*10465441SEvalZero
61*10465441SEvalZero return fd;
62*10465441SEvalZero }
63*10465441SEvalZero RTM_EXPORT(open);
64*10465441SEvalZero
65*10465441SEvalZero /**
66*10465441SEvalZero * this function is a POSIX compliant version, which will close the open
67*10465441SEvalZero * file descriptor.
68*10465441SEvalZero *
69*10465441SEvalZero * @param fd the file descriptor.
70*10465441SEvalZero *
71*10465441SEvalZero * @return 0 on successful, -1 on failed.
72*10465441SEvalZero */
close(int fd)73*10465441SEvalZero int close(int fd)
74*10465441SEvalZero {
75*10465441SEvalZero int result;
76*10465441SEvalZero struct dfs_fd *d;
77*10465441SEvalZero
78*10465441SEvalZero d = fd_get(fd);
79*10465441SEvalZero if (d == NULL)
80*10465441SEvalZero {
81*10465441SEvalZero rt_set_errno(-EBADF);
82*10465441SEvalZero
83*10465441SEvalZero return -1;
84*10465441SEvalZero }
85*10465441SEvalZero
86*10465441SEvalZero result = dfs_file_close(d);
87*10465441SEvalZero fd_put(d);
88*10465441SEvalZero
89*10465441SEvalZero if (result < 0)
90*10465441SEvalZero {
91*10465441SEvalZero rt_set_errno(result);
92*10465441SEvalZero
93*10465441SEvalZero return -1;
94*10465441SEvalZero }
95*10465441SEvalZero
96*10465441SEvalZero fd_put(d);
97*10465441SEvalZero
98*10465441SEvalZero return 0;
99*10465441SEvalZero }
100*10465441SEvalZero RTM_EXPORT(close);
101*10465441SEvalZero
102*10465441SEvalZero /**
103*10465441SEvalZero * this function is a POSIX compliant version, which will read specified data
104*10465441SEvalZero * buffer length for an open file descriptor.
105*10465441SEvalZero *
106*10465441SEvalZero * @param fd the file descriptor.
107*10465441SEvalZero * @param buf the buffer to save the read data.
108*10465441SEvalZero * @param len the maximal length of data buffer
109*10465441SEvalZero *
110*10465441SEvalZero * @return the actual read data buffer length. If the returned value is 0, it
111*10465441SEvalZero * may be reach the end of file, please check errno.
112*10465441SEvalZero */
113*10465441SEvalZero #if defined(RT_USING_NEWLIB) && defined(_EXFUN)
114*10465441SEvalZero _READ_WRITE_RETURN_TYPE _EXFUN(read, (int fd, void *buf, size_t len))
115*10465441SEvalZero #else
116*10465441SEvalZero int read(int fd, void *buf, size_t len)
117*10465441SEvalZero #endif
118*10465441SEvalZero {
119*10465441SEvalZero int result;
120*10465441SEvalZero struct dfs_fd *d;
121*10465441SEvalZero
122*10465441SEvalZero /* get the fd */
123*10465441SEvalZero d = fd_get(fd);
124*10465441SEvalZero if (d == NULL)
125*10465441SEvalZero {
126*10465441SEvalZero rt_set_errno(-EBADF);
127*10465441SEvalZero
128*10465441SEvalZero return -1;
129*10465441SEvalZero }
130*10465441SEvalZero
131*10465441SEvalZero result = dfs_file_read(d, buf, len);
132*10465441SEvalZero if (result < 0)
133*10465441SEvalZero {
134*10465441SEvalZero fd_put(d);
135*10465441SEvalZero rt_set_errno(result);
136*10465441SEvalZero
137*10465441SEvalZero return -1;
138*10465441SEvalZero }
139*10465441SEvalZero
140*10465441SEvalZero /* release the ref-count of fd */
141*10465441SEvalZero fd_put(d);
142*10465441SEvalZero
143*10465441SEvalZero return result;
144*10465441SEvalZero }
145*10465441SEvalZero RTM_EXPORT(read);
146*10465441SEvalZero
147*10465441SEvalZero /**
148*10465441SEvalZero * this function is a POSIX compliant version, which will write specified data
149*10465441SEvalZero * buffer length for an open file descriptor.
150*10465441SEvalZero *
151*10465441SEvalZero * @param fd the file descriptor
152*10465441SEvalZero * @param buf the data buffer to be written.
153*10465441SEvalZero * @param len the data buffer length.
154*10465441SEvalZero *
155*10465441SEvalZero * @return the actual written data buffer length.
156*10465441SEvalZero */
157*10465441SEvalZero #if defined(RT_USING_NEWLIB) && defined(_EXFUN)
158*10465441SEvalZero _READ_WRITE_RETURN_TYPE _EXFUN(write, (int fd, const void *buf, size_t len))
159*10465441SEvalZero #else
160*10465441SEvalZero int write(int fd, const void *buf, size_t len)
161*10465441SEvalZero #endif
162*10465441SEvalZero {
163*10465441SEvalZero int result;
164*10465441SEvalZero struct dfs_fd *d;
165*10465441SEvalZero
166*10465441SEvalZero /* get the fd */
167*10465441SEvalZero d = fd_get(fd);
168*10465441SEvalZero if (d == NULL)
169*10465441SEvalZero {
170*10465441SEvalZero rt_set_errno(-EBADF);
171*10465441SEvalZero
172*10465441SEvalZero return -1;
173*10465441SEvalZero }
174*10465441SEvalZero
175*10465441SEvalZero result = dfs_file_write(d, buf, len);
176*10465441SEvalZero if (result < 0)
177*10465441SEvalZero {
178*10465441SEvalZero fd_put(d);
179*10465441SEvalZero rt_set_errno(result);
180*10465441SEvalZero
181*10465441SEvalZero return -1;
182*10465441SEvalZero }
183*10465441SEvalZero
184*10465441SEvalZero /* release the ref-count of fd */
185*10465441SEvalZero fd_put(d);
186*10465441SEvalZero
187*10465441SEvalZero return result;
188*10465441SEvalZero }
189*10465441SEvalZero RTM_EXPORT(write);
190*10465441SEvalZero
191*10465441SEvalZero /**
192*10465441SEvalZero * this function is a POSIX compliant version, which will seek the offset for
193*10465441SEvalZero * an open file descriptor.
194*10465441SEvalZero *
195*10465441SEvalZero * @param fd the file descriptor.
196*10465441SEvalZero * @param offset the offset to be seeked.
197*10465441SEvalZero * @param whence the directory of seek.
198*10465441SEvalZero *
199*10465441SEvalZero * @return the current read/write position in the file, or -1 on failed.
200*10465441SEvalZero */
lseek(int fd,off_t offset,int whence)201*10465441SEvalZero off_t lseek(int fd, off_t offset, int whence)
202*10465441SEvalZero {
203*10465441SEvalZero int result;
204*10465441SEvalZero struct dfs_fd *d;
205*10465441SEvalZero
206*10465441SEvalZero d = fd_get(fd);
207*10465441SEvalZero if (d == NULL)
208*10465441SEvalZero {
209*10465441SEvalZero rt_set_errno(-EBADF);
210*10465441SEvalZero
211*10465441SEvalZero return -1;
212*10465441SEvalZero }
213*10465441SEvalZero
214*10465441SEvalZero switch (whence)
215*10465441SEvalZero {
216*10465441SEvalZero case SEEK_SET:
217*10465441SEvalZero break;
218*10465441SEvalZero
219*10465441SEvalZero case SEEK_CUR:
220*10465441SEvalZero offset += d->pos;
221*10465441SEvalZero break;
222*10465441SEvalZero
223*10465441SEvalZero case SEEK_END:
224*10465441SEvalZero offset += d->size;
225*10465441SEvalZero break;
226*10465441SEvalZero
227*10465441SEvalZero default:
228*10465441SEvalZero fd_put(d);
229*10465441SEvalZero rt_set_errno(-EINVAL);
230*10465441SEvalZero
231*10465441SEvalZero return -1;
232*10465441SEvalZero }
233*10465441SEvalZero
234*10465441SEvalZero if (offset < 0)
235*10465441SEvalZero {
236*10465441SEvalZero fd_put(d);
237*10465441SEvalZero rt_set_errno(-EINVAL);
238*10465441SEvalZero
239*10465441SEvalZero return -1;
240*10465441SEvalZero }
241*10465441SEvalZero result = dfs_file_lseek(d, offset);
242*10465441SEvalZero if (result < 0)
243*10465441SEvalZero {
244*10465441SEvalZero fd_put(d);
245*10465441SEvalZero rt_set_errno(result);
246*10465441SEvalZero
247*10465441SEvalZero return -1;
248*10465441SEvalZero }
249*10465441SEvalZero
250*10465441SEvalZero /* release the ref-count of fd */
251*10465441SEvalZero fd_put(d);
252*10465441SEvalZero
253*10465441SEvalZero return offset;
254*10465441SEvalZero }
255*10465441SEvalZero RTM_EXPORT(lseek);
256*10465441SEvalZero
257*10465441SEvalZero /**
258*10465441SEvalZero * this function is a POSIX compliant version, which will rename old file name
259*10465441SEvalZero * to new file name.
260*10465441SEvalZero *
261*10465441SEvalZero * @param old the old file name.
262*10465441SEvalZero * @param new the new file name.
263*10465441SEvalZero *
264*10465441SEvalZero * @return 0 on successful, -1 on failed.
265*10465441SEvalZero *
266*10465441SEvalZero * note: the old and new file name must be belong to a same file system.
267*10465441SEvalZero */
rename(const char * old,const char * new)268*10465441SEvalZero int rename(const char *old, const char *new)
269*10465441SEvalZero {
270*10465441SEvalZero int result;
271*10465441SEvalZero
272*10465441SEvalZero result = dfs_file_rename(old, new);
273*10465441SEvalZero if (result < 0)
274*10465441SEvalZero {
275*10465441SEvalZero rt_set_errno(result);
276*10465441SEvalZero
277*10465441SEvalZero return -1;
278*10465441SEvalZero }
279*10465441SEvalZero
280*10465441SEvalZero return 0;
281*10465441SEvalZero }
282*10465441SEvalZero RTM_EXPORT(rename);
283*10465441SEvalZero
284*10465441SEvalZero /**
285*10465441SEvalZero * this function is a POSIX compliant version, which will unlink (remove) a
286*10465441SEvalZero * specified path file from file system.
287*10465441SEvalZero *
288*10465441SEvalZero * @param pathname the specified path name to be unlinked.
289*10465441SEvalZero *
290*10465441SEvalZero * @return 0 on successful, -1 on failed.
291*10465441SEvalZero */
unlink(const char * pathname)292*10465441SEvalZero int unlink(const char *pathname)
293*10465441SEvalZero {
294*10465441SEvalZero int result;
295*10465441SEvalZero
296*10465441SEvalZero result = dfs_file_unlink(pathname);
297*10465441SEvalZero if (result < 0)
298*10465441SEvalZero {
299*10465441SEvalZero rt_set_errno(result);
300*10465441SEvalZero
301*10465441SEvalZero return -1;
302*10465441SEvalZero }
303*10465441SEvalZero
304*10465441SEvalZero return 0;
305*10465441SEvalZero }
306*10465441SEvalZero RTM_EXPORT(unlink);
307*10465441SEvalZero
308*10465441SEvalZero #ifndef _WIN32 /* we can not implement these functions */
309*10465441SEvalZero /**
310*10465441SEvalZero * this function is a POSIX compliant version, which will get file information.
311*10465441SEvalZero *
312*10465441SEvalZero * @param file the file name
313*10465441SEvalZero * @param buf the data buffer to save stat description.
314*10465441SEvalZero *
315*10465441SEvalZero * @return 0 on successful, -1 on failed.
316*10465441SEvalZero */
stat(const char * file,struct stat * buf)317*10465441SEvalZero int stat(const char *file, struct stat *buf)
318*10465441SEvalZero {
319*10465441SEvalZero int result;
320*10465441SEvalZero
321*10465441SEvalZero result = dfs_file_stat(file, buf);
322*10465441SEvalZero if (result < 0)
323*10465441SEvalZero {
324*10465441SEvalZero rt_set_errno(result);
325*10465441SEvalZero
326*10465441SEvalZero return -1;
327*10465441SEvalZero }
328*10465441SEvalZero
329*10465441SEvalZero return result;
330*10465441SEvalZero }
331*10465441SEvalZero RTM_EXPORT(stat);
332*10465441SEvalZero
333*10465441SEvalZero /**
334*10465441SEvalZero * this function is a POSIX compliant version, which will get file status.
335*10465441SEvalZero *
336*10465441SEvalZero * @param fildes the file description
337*10465441SEvalZero * @param buf the data buffer to save stat description.
338*10465441SEvalZero *
339*10465441SEvalZero * @return 0 on successful, -1 on failed.
340*10465441SEvalZero */
fstat(int fildes,struct stat * buf)341*10465441SEvalZero int fstat(int fildes, struct stat *buf)
342*10465441SEvalZero {
343*10465441SEvalZero struct dfs_fd *d;
344*10465441SEvalZero
345*10465441SEvalZero /* get the fd */
346*10465441SEvalZero d = fd_get(fildes);
347*10465441SEvalZero if (d == NULL)
348*10465441SEvalZero {
349*10465441SEvalZero rt_set_errno(-EBADF);
350*10465441SEvalZero
351*10465441SEvalZero return -1;
352*10465441SEvalZero }
353*10465441SEvalZero
354*10465441SEvalZero /* it's the root directory */
355*10465441SEvalZero buf->st_dev = 0;
356*10465441SEvalZero
357*10465441SEvalZero buf->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH |
358*10465441SEvalZero S_IWUSR | S_IWGRP | S_IWOTH;
359*10465441SEvalZero if (d->type == FT_DIRECTORY)
360*10465441SEvalZero {
361*10465441SEvalZero buf->st_mode &= ~S_IFREG;
362*10465441SEvalZero buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
363*10465441SEvalZero }
364*10465441SEvalZero
365*10465441SEvalZero buf->st_size = d->size;
366*10465441SEvalZero buf->st_mtime = 0;
367*10465441SEvalZero
368*10465441SEvalZero fd_put(d);
369*10465441SEvalZero
370*10465441SEvalZero return RT_EOK;
371*10465441SEvalZero }
372*10465441SEvalZero RTM_EXPORT(fstat);
373*10465441SEvalZero #endif
374*10465441SEvalZero
375*10465441SEvalZero /**
376*10465441SEvalZero * this function is a POSIX compliant version, which shall request that all data
377*10465441SEvalZero * for the open file descriptor named by fildes is to be transferred to the storage
378*10465441SEvalZero * device associated with the file described by fildes.
379*10465441SEvalZero *
380*10465441SEvalZero * @param fildes the file description
381*10465441SEvalZero *
382*10465441SEvalZero * @return 0 on successful completion. Otherwise, -1 shall be returned and errno
383*10465441SEvalZero * set to indicate the error.
384*10465441SEvalZero */
fsync(int fildes)385*10465441SEvalZero int fsync(int fildes)
386*10465441SEvalZero {
387*10465441SEvalZero int ret;
388*10465441SEvalZero struct dfs_fd *d;
389*10465441SEvalZero
390*10465441SEvalZero /* get the fd */
391*10465441SEvalZero d = fd_get(fildes);
392*10465441SEvalZero if (d == NULL)
393*10465441SEvalZero {
394*10465441SEvalZero rt_set_errno(-EBADF);
395*10465441SEvalZero return -1;
396*10465441SEvalZero }
397*10465441SEvalZero
398*10465441SEvalZero ret = dfs_file_flush(d);
399*10465441SEvalZero
400*10465441SEvalZero fd_put(d);
401*10465441SEvalZero return ret;
402*10465441SEvalZero }
403*10465441SEvalZero RTM_EXPORT(fsync);
404*10465441SEvalZero
405*10465441SEvalZero /**
406*10465441SEvalZero * this function is a POSIX compliant version, which shall perform a variety of
407*10465441SEvalZero * control functions on devices.
408*10465441SEvalZero *
409*10465441SEvalZero * @param fildes the file description
410*10465441SEvalZero * @param cmd the specified command
411*10465441SEvalZero * @param data represents the additional information that is needed by this
412*10465441SEvalZero * specific device to perform the requested function.
413*10465441SEvalZero *
414*10465441SEvalZero * @return 0 on successful completion. Otherwise, -1 shall be returned and errno
415*10465441SEvalZero * set to indicate the error.
416*10465441SEvalZero */
fcntl(int fildes,int cmd,...)417*10465441SEvalZero int fcntl(int fildes, int cmd, ...)
418*10465441SEvalZero {
419*10465441SEvalZero int ret = -1;
420*10465441SEvalZero struct dfs_fd *d;
421*10465441SEvalZero
422*10465441SEvalZero /* get the fd */
423*10465441SEvalZero d = fd_get(fildes);
424*10465441SEvalZero if (d)
425*10465441SEvalZero {
426*10465441SEvalZero void* arg;
427*10465441SEvalZero va_list ap;
428*10465441SEvalZero
429*10465441SEvalZero va_start(ap, cmd);
430*10465441SEvalZero arg = va_arg(ap, void*);
431*10465441SEvalZero va_end(ap);
432*10465441SEvalZero
433*10465441SEvalZero ret = dfs_file_ioctl(d, cmd, arg);
434*10465441SEvalZero fd_put(d);
435*10465441SEvalZero }
436*10465441SEvalZero else ret = -EBADF;
437*10465441SEvalZero
438*10465441SEvalZero if (ret < 0)
439*10465441SEvalZero {
440*10465441SEvalZero rt_set_errno(ret);
441*10465441SEvalZero ret = -1;
442*10465441SEvalZero }
443*10465441SEvalZero
444*10465441SEvalZero return ret;
445*10465441SEvalZero }
446*10465441SEvalZero RTM_EXPORT(fcntl);
447*10465441SEvalZero
448*10465441SEvalZero /**
449*10465441SEvalZero * this function is a POSIX compliant version, which shall perform a variety of
450*10465441SEvalZero * control functions on devices.
451*10465441SEvalZero *
452*10465441SEvalZero * @param fildes the file description
453*10465441SEvalZero * @param cmd the specified command
454*10465441SEvalZero * @param data represents the additional information that is needed by this
455*10465441SEvalZero * specific device to perform the requested function.
456*10465441SEvalZero *
457*10465441SEvalZero * @return 0 on successful completion. Otherwise, -1 shall be returned and errno
458*10465441SEvalZero * set to indicate the error.
459*10465441SEvalZero */
ioctl(int fildes,int cmd,...)460*10465441SEvalZero int ioctl(int fildes, int cmd, ...)
461*10465441SEvalZero {
462*10465441SEvalZero void* arg;
463*10465441SEvalZero va_list ap;
464*10465441SEvalZero
465*10465441SEvalZero va_start(ap, cmd);
466*10465441SEvalZero arg = va_arg(ap, void*);
467*10465441SEvalZero va_end(ap);
468*10465441SEvalZero
469*10465441SEvalZero /* we use fcntl for this API. */
470*10465441SEvalZero return fcntl(fildes, cmd, arg);
471*10465441SEvalZero }
472*10465441SEvalZero RTM_EXPORT(ioctl);
473*10465441SEvalZero
474*10465441SEvalZero /**
475*10465441SEvalZero * this function is a POSIX compliant version, which will return the
476*10465441SEvalZero * information about a mounted file system.
477*10465441SEvalZero *
478*10465441SEvalZero * @param path the path which mounted file system.
479*10465441SEvalZero * @param buf the buffer to save the returned information.
480*10465441SEvalZero *
481*10465441SEvalZero * @return 0 on successful, others on failed.
482*10465441SEvalZero */
statfs(const char * path,struct statfs * buf)483*10465441SEvalZero int statfs(const char *path, struct statfs *buf)
484*10465441SEvalZero {
485*10465441SEvalZero int result;
486*10465441SEvalZero
487*10465441SEvalZero result = dfs_statfs(path, buf);
488*10465441SEvalZero if (result < 0)
489*10465441SEvalZero {
490*10465441SEvalZero rt_set_errno(result);
491*10465441SEvalZero
492*10465441SEvalZero return -1;
493*10465441SEvalZero }
494*10465441SEvalZero
495*10465441SEvalZero return result;
496*10465441SEvalZero }
497*10465441SEvalZero RTM_EXPORT(statfs);
498*10465441SEvalZero
499*10465441SEvalZero /**
500*10465441SEvalZero * this function is a POSIX compliant version, which will make a directory
501*10465441SEvalZero *
502*10465441SEvalZero * @param path the directory path to be made.
503*10465441SEvalZero * @param mode
504*10465441SEvalZero *
505*10465441SEvalZero * @return 0 on successful, others on failed.
506*10465441SEvalZero */
mkdir(const char * path,mode_t mode)507*10465441SEvalZero int mkdir(const char *path, mode_t mode)
508*10465441SEvalZero {
509*10465441SEvalZero int fd;
510*10465441SEvalZero struct dfs_fd *d;
511*10465441SEvalZero int result;
512*10465441SEvalZero
513*10465441SEvalZero fd = fd_new();
514*10465441SEvalZero if (fd == -1)
515*10465441SEvalZero {
516*10465441SEvalZero rt_set_errno(-ENOMEM);
517*10465441SEvalZero
518*10465441SEvalZero return -1;
519*10465441SEvalZero }
520*10465441SEvalZero
521*10465441SEvalZero d = fd_get(fd);
522*10465441SEvalZero
523*10465441SEvalZero result = dfs_file_open(d, path, O_DIRECTORY | O_CREAT);
524*10465441SEvalZero
525*10465441SEvalZero if (result < 0)
526*10465441SEvalZero {
527*10465441SEvalZero fd_put(d);
528*10465441SEvalZero fd_put(d);
529*10465441SEvalZero rt_set_errno(result);
530*10465441SEvalZero
531*10465441SEvalZero return -1;
532*10465441SEvalZero }
533*10465441SEvalZero
534*10465441SEvalZero dfs_file_close(d);
535*10465441SEvalZero fd_put(d);
536*10465441SEvalZero fd_put(d);
537*10465441SEvalZero
538*10465441SEvalZero return 0;
539*10465441SEvalZero }
540*10465441SEvalZero RTM_EXPORT(mkdir);
541*10465441SEvalZero
542*10465441SEvalZero #ifdef RT_USING_FINSH
543*10465441SEvalZero #include <finsh.h>
544*10465441SEvalZero FINSH_FUNCTION_EXPORT(mkdir, create a directory);
545*10465441SEvalZero #endif
546*10465441SEvalZero
547*10465441SEvalZero /**
548*10465441SEvalZero * this function is a POSIX compliant version, which will remove a directory.
549*10465441SEvalZero *
550*10465441SEvalZero * @param pathname the path name to be removed.
551*10465441SEvalZero *
552*10465441SEvalZero * @return 0 on successful, others on failed.
553*10465441SEvalZero */
rmdir(const char * pathname)554*10465441SEvalZero int rmdir(const char *pathname)
555*10465441SEvalZero {
556*10465441SEvalZero int result;
557*10465441SEvalZero
558*10465441SEvalZero result = dfs_file_unlink(pathname);
559*10465441SEvalZero if (result < 0)
560*10465441SEvalZero {
561*10465441SEvalZero rt_set_errno(result);
562*10465441SEvalZero
563*10465441SEvalZero return -1;
564*10465441SEvalZero }
565*10465441SEvalZero
566*10465441SEvalZero return 0;
567*10465441SEvalZero }
568*10465441SEvalZero RTM_EXPORT(rmdir);
569*10465441SEvalZero
570*10465441SEvalZero /**
571*10465441SEvalZero * this function is a POSIX compliant version, which will open a directory.
572*10465441SEvalZero *
573*10465441SEvalZero * @param name the path name to be open.
574*10465441SEvalZero *
575*10465441SEvalZero * @return the DIR pointer of directory, NULL on open directory failed.
576*10465441SEvalZero */
opendir(const char * name)577*10465441SEvalZero DIR *opendir(const char *name)
578*10465441SEvalZero {
579*10465441SEvalZero struct dfs_fd *d;
580*10465441SEvalZero int fd, result;
581*10465441SEvalZero DIR *t;
582*10465441SEvalZero
583*10465441SEvalZero t = NULL;
584*10465441SEvalZero
585*10465441SEvalZero /* allocate a fd */
586*10465441SEvalZero fd = fd_new();
587*10465441SEvalZero if (fd == -1)
588*10465441SEvalZero {
589*10465441SEvalZero rt_set_errno(-ENOMEM);
590*10465441SEvalZero
591*10465441SEvalZero return NULL;
592*10465441SEvalZero }
593*10465441SEvalZero d = fd_get(fd);
594*10465441SEvalZero
595*10465441SEvalZero result = dfs_file_open(d, name, O_RDONLY | O_DIRECTORY);
596*10465441SEvalZero if (result >= 0)
597*10465441SEvalZero {
598*10465441SEvalZero /* open successfully */
599*10465441SEvalZero t = (DIR *) rt_malloc(sizeof(DIR));
600*10465441SEvalZero if (t == NULL)
601*10465441SEvalZero {
602*10465441SEvalZero dfs_file_close(d);
603*10465441SEvalZero fd_put(d);
604*10465441SEvalZero }
605*10465441SEvalZero else
606*10465441SEvalZero {
607*10465441SEvalZero memset(t, 0, sizeof(DIR));
608*10465441SEvalZero
609*10465441SEvalZero t->fd = fd;
610*10465441SEvalZero }
611*10465441SEvalZero fd_put(d);
612*10465441SEvalZero
613*10465441SEvalZero return t;
614*10465441SEvalZero }
615*10465441SEvalZero
616*10465441SEvalZero /* open failed */
617*10465441SEvalZero fd_put(d);
618*10465441SEvalZero fd_put(d);
619*10465441SEvalZero rt_set_errno(result);
620*10465441SEvalZero
621*10465441SEvalZero return NULL;
622*10465441SEvalZero }
623*10465441SEvalZero RTM_EXPORT(opendir);
624*10465441SEvalZero
625*10465441SEvalZero /**
626*10465441SEvalZero * this function is a POSIX compliant version, which will return a pointer
627*10465441SEvalZero * to a dirent structure representing the next directory entry in the
628*10465441SEvalZero * directory stream.
629*10465441SEvalZero *
630*10465441SEvalZero * @param d the directory stream pointer.
631*10465441SEvalZero *
632*10465441SEvalZero * @return the next directory entry, NULL on the end of directory or failed.
633*10465441SEvalZero */
readdir(DIR * d)634*10465441SEvalZero struct dirent *readdir(DIR *d)
635*10465441SEvalZero {
636*10465441SEvalZero int result;
637*10465441SEvalZero struct dfs_fd *fd;
638*10465441SEvalZero
639*10465441SEvalZero fd = fd_get(d->fd);
640*10465441SEvalZero if (fd == NULL)
641*10465441SEvalZero {
642*10465441SEvalZero rt_set_errno(-EBADF);
643*10465441SEvalZero return NULL;
644*10465441SEvalZero }
645*10465441SEvalZero
646*10465441SEvalZero if (d->num)
647*10465441SEvalZero {
648*10465441SEvalZero struct dirent* dirent_ptr;
649*10465441SEvalZero dirent_ptr = (struct dirent*)&d->buf[d->cur];
650*10465441SEvalZero d->cur += dirent_ptr->d_reclen;
651*10465441SEvalZero }
652*10465441SEvalZero
653*10465441SEvalZero if (!d->num || d->cur >= d->num)
654*10465441SEvalZero {
655*10465441SEvalZero /* get a new entry */
656*10465441SEvalZero result = dfs_file_getdents(fd,
657*10465441SEvalZero (struct dirent*)d->buf,
658*10465441SEvalZero sizeof(d->buf) - 1);
659*10465441SEvalZero if (result <= 0)
660*10465441SEvalZero {
661*10465441SEvalZero fd_put(fd);
662*10465441SEvalZero rt_set_errno(result);
663*10465441SEvalZero
664*10465441SEvalZero return NULL;
665*10465441SEvalZero }
666*10465441SEvalZero
667*10465441SEvalZero d->num = result;
668*10465441SEvalZero d->cur = 0; /* current entry index */
669*10465441SEvalZero }
670*10465441SEvalZero
671*10465441SEvalZero fd_put(fd);
672*10465441SEvalZero
673*10465441SEvalZero return (struct dirent *)(d->buf+d->cur);
674*10465441SEvalZero }
675*10465441SEvalZero RTM_EXPORT(readdir);
676*10465441SEvalZero
677*10465441SEvalZero /**
678*10465441SEvalZero * this function is a POSIX compliant version, which will return current
679*10465441SEvalZero * location in directory stream.
680*10465441SEvalZero *
681*10465441SEvalZero * @param d the directory stream pointer.
682*10465441SEvalZero *
683*10465441SEvalZero * @return the current location in directory stream.
684*10465441SEvalZero */
telldir(DIR * d)685*10465441SEvalZero long telldir(DIR *d)
686*10465441SEvalZero {
687*10465441SEvalZero struct dfs_fd *fd;
688*10465441SEvalZero long result;
689*10465441SEvalZero
690*10465441SEvalZero fd = fd_get(d->fd);
691*10465441SEvalZero if (fd == NULL)
692*10465441SEvalZero {
693*10465441SEvalZero rt_set_errno(-EBADF);
694*10465441SEvalZero
695*10465441SEvalZero return 0;
696*10465441SEvalZero }
697*10465441SEvalZero
698*10465441SEvalZero result = fd->pos - d->num + d->cur;
699*10465441SEvalZero fd_put(fd);
700*10465441SEvalZero
701*10465441SEvalZero return result;
702*10465441SEvalZero }
703*10465441SEvalZero RTM_EXPORT(telldir);
704*10465441SEvalZero
705*10465441SEvalZero /**
706*10465441SEvalZero * this function is a POSIX compliant version, which will set position of
707*10465441SEvalZero * next directory structure in the directory stream.
708*10465441SEvalZero *
709*10465441SEvalZero * @param d the directory stream.
710*10465441SEvalZero * @param offset the offset in directory stream.
711*10465441SEvalZero */
seekdir(DIR * d,off_t offset)712*10465441SEvalZero void seekdir(DIR *d, off_t offset)
713*10465441SEvalZero {
714*10465441SEvalZero struct dfs_fd *fd;
715*10465441SEvalZero
716*10465441SEvalZero fd = fd_get(d->fd);
717*10465441SEvalZero if (fd == NULL)
718*10465441SEvalZero {
719*10465441SEvalZero rt_set_errno(-EBADF);
720*10465441SEvalZero
721*10465441SEvalZero return ;
722*10465441SEvalZero }
723*10465441SEvalZero
724*10465441SEvalZero /* seek to the offset position of directory */
725*10465441SEvalZero if (dfs_file_lseek(fd, offset) >= 0)
726*10465441SEvalZero d->num = d->cur = 0;
727*10465441SEvalZero fd_put(fd);
728*10465441SEvalZero }
729*10465441SEvalZero RTM_EXPORT(seekdir);
730*10465441SEvalZero
731*10465441SEvalZero /**
732*10465441SEvalZero * this function is a POSIX compliant version, which will reset directory
733*10465441SEvalZero * stream.
734*10465441SEvalZero *
735*10465441SEvalZero * @param d the directory stream.
736*10465441SEvalZero */
rewinddir(DIR * d)737*10465441SEvalZero void rewinddir(DIR *d)
738*10465441SEvalZero {
739*10465441SEvalZero struct dfs_fd *fd;
740*10465441SEvalZero
741*10465441SEvalZero fd = fd_get(d->fd);
742*10465441SEvalZero if (fd == NULL)
743*10465441SEvalZero {
744*10465441SEvalZero rt_set_errno(-EBADF);
745*10465441SEvalZero
746*10465441SEvalZero return ;
747*10465441SEvalZero }
748*10465441SEvalZero
749*10465441SEvalZero /* seek to the beginning of directory */
750*10465441SEvalZero if (dfs_file_lseek(fd, 0) >= 0)
751*10465441SEvalZero d->num = d->cur = 0;
752*10465441SEvalZero fd_put(fd);
753*10465441SEvalZero }
754*10465441SEvalZero RTM_EXPORT(rewinddir);
755*10465441SEvalZero
756*10465441SEvalZero /**
757*10465441SEvalZero * this function is a POSIX compliant version, which will close a directory
758*10465441SEvalZero * stream.
759*10465441SEvalZero *
760*10465441SEvalZero * @param d the directory stream.
761*10465441SEvalZero *
762*10465441SEvalZero * @return 0 on successful, -1 on failed.
763*10465441SEvalZero */
closedir(DIR * d)764*10465441SEvalZero int closedir(DIR *d)
765*10465441SEvalZero {
766*10465441SEvalZero int result;
767*10465441SEvalZero struct dfs_fd *fd;
768*10465441SEvalZero
769*10465441SEvalZero fd = fd_get(d->fd);
770*10465441SEvalZero if (fd == NULL)
771*10465441SEvalZero {
772*10465441SEvalZero rt_set_errno(-EBADF);
773*10465441SEvalZero
774*10465441SEvalZero return -1;
775*10465441SEvalZero }
776*10465441SEvalZero
777*10465441SEvalZero result = dfs_file_close(fd);
778*10465441SEvalZero fd_put(fd);
779*10465441SEvalZero
780*10465441SEvalZero fd_put(fd);
781*10465441SEvalZero rt_free(d);
782*10465441SEvalZero
783*10465441SEvalZero if (result < 0)
784*10465441SEvalZero {
785*10465441SEvalZero rt_set_errno(result);
786*10465441SEvalZero
787*10465441SEvalZero return -1;
788*10465441SEvalZero }
789*10465441SEvalZero else
790*10465441SEvalZero return 0;
791*10465441SEvalZero }
792*10465441SEvalZero RTM_EXPORT(closedir);
793*10465441SEvalZero
794*10465441SEvalZero #ifdef DFS_USING_WORKDIR
795*10465441SEvalZero /**
796*10465441SEvalZero * this function is a POSIX compliant version, which will change working
797*10465441SEvalZero * directory.
798*10465441SEvalZero *
799*10465441SEvalZero * @param path the path name to be changed to.
800*10465441SEvalZero *
801*10465441SEvalZero * @return 0 on successful, -1 on failed.
802*10465441SEvalZero */
chdir(const char * path)803*10465441SEvalZero int chdir(const char *path)
804*10465441SEvalZero {
805*10465441SEvalZero char *fullpath;
806*10465441SEvalZero DIR *d;
807*10465441SEvalZero
808*10465441SEvalZero if (path == NULL)
809*10465441SEvalZero {
810*10465441SEvalZero dfs_lock();
811*10465441SEvalZero rt_kprintf("%s\n", working_directory);
812*10465441SEvalZero dfs_unlock();
813*10465441SEvalZero
814*10465441SEvalZero return 0;
815*10465441SEvalZero }
816*10465441SEvalZero
817*10465441SEvalZero if (strlen(path) > DFS_PATH_MAX)
818*10465441SEvalZero {
819*10465441SEvalZero rt_set_errno(-ENOTDIR);
820*10465441SEvalZero
821*10465441SEvalZero return -1;
822*10465441SEvalZero }
823*10465441SEvalZero
824*10465441SEvalZero fullpath = dfs_normalize_path(NULL, path);
825*10465441SEvalZero if (fullpath == NULL)
826*10465441SEvalZero {
827*10465441SEvalZero rt_set_errno(-ENOTDIR);
828*10465441SEvalZero
829*10465441SEvalZero return -1; /* build path failed */
830*10465441SEvalZero }
831*10465441SEvalZero
832*10465441SEvalZero dfs_lock();
833*10465441SEvalZero d = opendir(fullpath);
834*10465441SEvalZero if (d == NULL)
835*10465441SEvalZero {
836*10465441SEvalZero rt_free(fullpath);
837*10465441SEvalZero /* this is a not exist directory */
838*10465441SEvalZero dfs_unlock();
839*10465441SEvalZero
840*10465441SEvalZero return -1;
841*10465441SEvalZero }
842*10465441SEvalZero
843*10465441SEvalZero /* close directory stream */
844*10465441SEvalZero closedir(d);
845*10465441SEvalZero
846*10465441SEvalZero /* copy full path to working directory */
847*10465441SEvalZero strncpy(working_directory, fullpath, DFS_PATH_MAX);
848*10465441SEvalZero /* release normalize directory path name */
849*10465441SEvalZero rt_free(fullpath);
850*10465441SEvalZero
851*10465441SEvalZero dfs_unlock();
852*10465441SEvalZero
853*10465441SEvalZero return 0;
854*10465441SEvalZero }
855*10465441SEvalZero RTM_EXPORT(chdir);
856*10465441SEvalZero
857*10465441SEvalZero #ifdef RT_USING_FINSH
858*10465441SEvalZero FINSH_FUNCTION_EXPORT_ALIAS(chdir, cd, change current working directory);
859*10465441SEvalZero #endif
860*10465441SEvalZero #endif
861*10465441SEvalZero
862*10465441SEvalZero /**
863*10465441SEvalZero * this function is a POSIX compliant version, which shall check the file named
864*10465441SEvalZero * by the pathname pointed to by the path argument for accessibility according
865*10465441SEvalZero * to the bit pattern contained in amode.
866*10465441SEvalZero *
867*10465441SEvalZero * @param path the specified file/dir path.
868*10465441SEvalZero * @param amode the value is either the bitwise-inclusive OR of the access
869*10465441SEvalZero * permissions to be checked (R_OK, W_OK, X_OK) or the existence test (F_OK).
870*10465441SEvalZero */
access(const char * path,int amode)871*10465441SEvalZero int access(const char *path, int amode)
872*10465441SEvalZero {
873*10465441SEvalZero struct stat sb;
874*10465441SEvalZero if (stat(path, &sb) < 0)
875*10465441SEvalZero return -1; /* already sets errno */
876*10465441SEvalZero
877*10465441SEvalZero /* ignore R_OK,W_OK,X_OK condition */
878*10465441SEvalZero return 0;
879*10465441SEvalZero }
880*10465441SEvalZero
881*10465441SEvalZero /**
882*10465441SEvalZero * this function is a POSIX compliant version, which will return current
883*10465441SEvalZero * working directory.
884*10465441SEvalZero *
885*10465441SEvalZero * @param buf the returned current directory.
886*10465441SEvalZero * @param size the buffer size.
887*10465441SEvalZero *
888*10465441SEvalZero * @return the returned current directory.
889*10465441SEvalZero */
getcwd(char * buf,size_t size)890*10465441SEvalZero char *getcwd(char *buf, size_t size)
891*10465441SEvalZero {
892*10465441SEvalZero #ifdef DFS_USING_WORKDIR
893*10465441SEvalZero dfs_lock();
894*10465441SEvalZero strncpy(buf, working_directory, size);
895*10465441SEvalZero dfs_unlock();
896*10465441SEvalZero #else
897*10465441SEvalZero rt_kprintf(NO_WORKING_DIR);
898*10465441SEvalZero #endif
899*10465441SEvalZero
900*10465441SEvalZero return buf;
901*10465441SEvalZero }
902*10465441SEvalZero RTM_EXPORT(getcwd);
903*10465441SEvalZero
904*10465441SEvalZero /* @} */
905