1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2012-09-30 Bernard first version.
9 * 2017-11-08 JasonJiaJie fix memory leak issue when close a pipe.
10 * 2023-06-28 shell return POLLHUP when writer closed its channel on poll()
11 * fix flag test on pipe_fops_open()
12 * 2023-12-02 shell Make read pipe operation interruptable.
13 */
14 #include <rthw.h>
15 #include <rtdevice.h>
16 #include <stdint.h>
17 #include <sys/errno.h>
18 #include <ipc/condvar.h>
19
20 #if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE)
21 #include <unistd.h>
22 #include <fcntl.h>
23 #include <poll.h>
24 #include <sys/ioctl.h>
25 #include <dfs_file.h>
26 #include <resource_id.h>
27
28 /* check RT_UNAMED_PIPE_NUMBER */
29
30 #ifndef RT_UNAMED_PIPE_NUMBER
31 #define RT_UNAMED_PIPE_NUMBER 64
32 #endif
33
34 #define BITS(x) _BITS(x)
35 #define _BITS(x) (sizeof(#x) - 1)
36
37 struct check_rt_unamed_pipe_number
38 {
39 /* -4 for "pipe" prefix */
40 /* -1 for '\0' postfix */
41 char _check[RT_NAME_MAX - 4 - 1 - BITS(RT_UNAMED_PIPE_NUMBER)];
42 };
43
44 /* check end */
45
46 static void *resoure_id[RT_UNAMED_PIPE_NUMBER];
47 static resource_id_t id_mgr = RESOURCE_ID_INIT(RT_UNAMED_PIPE_NUMBER, resoure_id);
48
49 /**
50 * @brief This function will open a pipe.
51 *
52 * @param fd is the file descriptor.
53 *
54 * @return Return the operation status.
55 * When the return value is 0, it means the operation is successful.
56 * When the return value is -1, it means the file descriptor is invalid.
57 * When the return value is -RT_ENOMEM, it means insufficient memory allocation failed.
58 */
pipe_fops_open(struct dfs_file * fd)59 static int pipe_fops_open(struct dfs_file *fd)
60 {
61 int rc = 0;
62 rt_pipe_t *pipe;
63
64 pipe = (rt_pipe_t *)fd->vnode->data;
65 if (!pipe)
66 {
67 return -1;
68 }
69
70 rt_mutex_take(&pipe->lock, RT_WAITING_FOREVER);
71
72 if ((fd->flags & O_ACCMODE) == O_RDONLY)
73 {
74 pipe->reader += 1;
75 }
76
77 if ((fd->flags & O_ACCMODE) == O_WRONLY)
78 {
79 pipe->writer += 1;
80 }
81 if (fd->vnode->ref_count == 1)
82 {
83 pipe->fifo = rt_ringbuffer_create(pipe->bufsz);
84 if (pipe->fifo == RT_NULL)
85 {
86 rc = -RT_ENOMEM;
87 goto __exit;
88 }
89 }
90
91 if ((fd->flags & O_ACCMODE) == O_RDONLY && !pipe->writer)
92 {
93 /* wait for partner */
94 rc = rt_condvar_timedwait(&pipe->waitfor_parter, &pipe->lock,
95 RT_INTERRUPTIBLE, RT_WAITING_FOREVER);
96 if (rc != 0)
97 {
98 pipe->reader--;
99 }
100 }
101 else if ((fd->flags & O_ACCMODE) == O_WRONLY)
102 {
103 rt_condvar_broadcast(&pipe->waitfor_parter);
104 }
105
106 __exit:
107 rt_mutex_release(&pipe->lock);
108
109 return rc;
110 }
111
112 /**
113 * @brief This function will close a pipe.
114 *
115 * @param fd is the file descriptor.
116 *
117 * @return Return the operation status.
118 * When the return value is 0, it means the operation is successful.
119 * When the return value is -1, it means the file descriptor is invalid.
120 */
pipe_fops_close(struct dfs_file * fd)121 static int pipe_fops_close(struct dfs_file *fd)
122 {
123 rt_device_t device;
124 rt_pipe_t *pipe;
125
126 pipe = (rt_pipe_t *)fd->vnode->data;
127 if (!pipe)
128 {
129 return -1;
130 }
131
132 device = &pipe->parent;
133 rt_mutex_take(&pipe->lock, RT_WAITING_FOREVER);
134
135 if ((fd->flags & O_RDONLY) == O_RDONLY)
136 {
137 pipe->reader -= 1;
138 }
139
140 if ((fd->flags & O_WRONLY) == O_WRONLY)
141 {
142 pipe->writer -= 1;
143 while (!rt_list_isempty(&pipe->reader_queue.waiting_list))
144 {
145 rt_wqueue_wakeup(&pipe->reader_queue, (void*)POLLIN);
146 }
147 }
148
149 if (fd->vnode->ref_count == 1)
150 {
151 if (pipe->fifo != RT_NULL)
152 {
153 rt_ringbuffer_destroy(pipe->fifo);
154 }
155 pipe->fifo = RT_NULL;
156 }
157
158 rt_mutex_release(&pipe->lock);
159
160 if (fd->vnode->ref_count == 1 && pipe->is_named == RT_FALSE)
161 {
162 /* delete the unamed pipe */
163 rt_pipe_delete(device->parent.name);
164 }
165
166 return 0;
167 }
168
169 /**
170 * @brief This function will get the pipe space size depends on the command.
171 *
172 * @param fd is the file descriptor.
173 *
174 * @param cmd is the command. It determines what data will get.
175 *
176 * FIONREAD The command to get the number of bytes in the pipe.
177 *
178 * FIONWRITE The command to get the number of bytes can be written to the pipe.
179 *
180 * @param args is the pointer to the data to store the read data.
181 *
182 * @return Return the operation status.
183 * When the return value is 0, it means the operation is successful.
184 * When the return value is -EINVAL, it means the command is invalid.
185 */
pipe_fops_ioctl(struct dfs_file * fd,int cmd,void * args)186 static int pipe_fops_ioctl(struct dfs_file *fd, int cmd, void *args)
187 {
188 rt_pipe_t *pipe;
189 int ret = 0;
190
191 pipe = (rt_pipe_t *)fd->vnode->data;
192
193 switch (cmd)
194 {
195 case FIONREAD:
196 *((int*)args) = rt_ringbuffer_data_len(pipe->fifo);
197 break;
198 case FIONWRITE:
199 *((int*)args) = rt_ringbuffer_space_len(pipe->fifo);
200 break;
201 default:
202 ret = -EINVAL;
203 break;
204 }
205
206 return ret;
207 }
208
209 /**
210 * @brief This function will read data from pipe.
211 *
212 * @param fd is the file descriptor.
213 *
214 * @param buf is the buffer to store the read data.
215 *
216 * @param count is the length of data to be read.
217 *
218 * @return Return the length of data read.
219 * When the return value is 0, it means O_NONBLOCK is enabled and there is no thread that has the pipe open for writing.
220 * When the return value is -EAGAIN, it means there are no data to be read.
221 */
222 #ifdef RT_USING_DFS_V2
pipe_fops_read(struct dfs_file * fd,void * buf,size_t count,off_t * pos)223 static ssize_t pipe_fops_read(struct dfs_file *fd, void *buf, size_t count, off_t *pos)
224 #else
225 static ssize_t pipe_fops_read(struct dfs_file *fd, void *buf, size_t count)
226 #endif
227 {
228 int len = 0;
229 rt_pipe_t *pipe;
230
231 pipe = (rt_pipe_t *)fd->vnode->data;
232
233 /* no process has the pipe open for writing, return end-of-file */
234 rt_mutex_take(&pipe->lock, RT_WAITING_FOREVER);
235
236 while (1)
237 {
238 len = rt_ringbuffer_get(pipe->fifo, buf, count);
239
240 if (len > 0 || pipe->writer == 0)
241 {
242 break;
243 }
244 else
245 {
246 if (fd->flags & O_NONBLOCK)
247 {
248 len = -EAGAIN;
249 goto out;
250 }
251
252 rt_mutex_release(&pipe->lock);
253 rt_wqueue_wakeup(&pipe->writer_queue, (void*)POLLOUT);
254 if (rt_wqueue_wait_interruptible(&pipe->reader_queue, 0, -1) == -RT_EINTR)
255 return -EINTR;
256 rt_mutex_take(&pipe->lock, RT_WAITING_FOREVER);
257 }
258 }
259
260 /* wakeup writer */
261 rt_wqueue_wakeup(&pipe->writer_queue, (void*)POLLOUT);
262
263 out:
264 rt_mutex_release(&pipe->lock);
265 return len;
266 }
267
268 /**
269 * @brief This function will write data to pipe.
270 *
271 * @param fd is the file descriptor.
272 *
273 * @param buf is a pointer to the data buffer to be written.
274 *
275 * @param count is the length of data to be write.
276 *
277 * @return Return the length of data written.
278 * When the return value is -EAGAIN, it means O_NONBLOCK is enabled and there are no space to be written.
279 * When the return value is -EPIPE, it means there is no thread that has the pipe open for reading.
280 */
281 #ifdef RT_USING_DFS_V2
pipe_fops_write(struct dfs_file * fd,const void * buf,size_t count,off_t * pos)282 static ssize_t pipe_fops_write(struct dfs_file *fd, const void *buf, size_t count, off_t *pos)
283 #else
284 static ssize_t pipe_fops_write(struct dfs_file *fd, const void *buf, size_t count)
285 #endif
286 {
287 int len;
288 rt_pipe_t *pipe;
289 int wakeup = 0;
290 int ret = 0;
291 uint8_t *pbuf;
292
293 pipe = (rt_pipe_t *)fd->vnode->data;
294
295 if (count == 0)
296 {
297 return 0;
298 }
299
300 pbuf = (uint8_t*)buf;
301 rt_mutex_take(&pipe->lock, -1);
302
303 while (1)
304 {
305 len = rt_ringbuffer_put(pipe->fifo, pbuf, count - ret);
306 ret += len;
307 pbuf += len;
308 wakeup = 1;
309
310 if (ret == count)
311 {
312 break;
313 }
314 else
315 {
316 if (fd->flags & O_NONBLOCK)
317 {
318 if (ret == 0)
319 {
320 ret = -EAGAIN;
321 }
322
323 break;
324 }
325 }
326
327 rt_mutex_release(&pipe->lock);
328 rt_wqueue_wakeup(&pipe->reader_queue, (void*)POLLIN);
329 /* pipe full, waiting on suspended write list */
330 if (rt_wqueue_wait_interruptible(&pipe->writer_queue, 0, -1) == -RT_EINTR)
331 return -EINTR;
332 rt_mutex_take(&pipe->lock, -1);
333 }
334 rt_mutex_release(&pipe->lock);
335
336 if (wakeup)
337 {
338 rt_wqueue_wakeup(&pipe->reader_queue, (void*)POLLIN);
339 }
340
341 return ret;
342 }
343
344 /**
345 * @brief This function will get the pipe status.
346 *
347 * @param fd is the file descriptor.
348 *
349 * @param req is the request type.
350 *
351 * @return mask of the pipe status.
352 * POLLIN means there is data to be read.
353 * POLLHUP means there is no thread that occupied the pipe to open for writing.
354 * POLLOUT means there is space to be written.
355 * POLLERR means there is no thread that occupied the pipe to open for reading.
356 */
pipe_fops_poll(struct dfs_file * fd,rt_pollreq_t * req)357 static int pipe_fops_poll(struct dfs_file *fd, rt_pollreq_t *req)
358 {
359 int mask = 0;
360 rt_pipe_t *pipe;
361 int mode = 0;
362 pipe = (rt_pipe_t *)fd->vnode->data;
363
364 rt_poll_add(&pipe->reader_queue, req);
365 rt_poll_add(&pipe->writer_queue, req);
366
367 switch (fd->flags & O_ACCMODE)
368 {
369 case O_RDONLY:
370 mode = 1;
371 break;
372 case O_WRONLY:
373 mode = 2;
374 break;
375 case O_RDWR:
376 mode = 3;
377 break;
378 }
379
380 if (mode & 1)
381 {
382 if (rt_ringbuffer_data_len(pipe->fifo) != 0)
383 {
384 mask |= POLLIN;
385 }
386 else if (pipe->writer == 0)
387 {
388 mask = POLLHUP;
389 }
390 }
391
392 if (mode & 2)
393 {
394 if (rt_ringbuffer_space_len(pipe->fifo) != 0)
395 {
396 mask |= POLLOUT;
397 }
398 }
399
400 return mask;
401 }
402
403 static const struct dfs_file_ops pipe_fops =
404 {
405 .open = pipe_fops_open,
406 .close = pipe_fops_close,
407 .ioctl = pipe_fops_ioctl,
408 .read = pipe_fops_read,
409 .write = pipe_fops_write,
410 .poll = pipe_fops_poll,
411 };
412 #endif /* defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE) */
413
414 /**
415 * @brief This function will open the pipe and actually creates the pipe buffer.
416 *
417 * @param device is a pointer to the pipe device descriptor.
418 *
419 * @param oflag is the open method, but it is not used yet.
420 *
421 * @return Return the operation status.
422 * When the return value is RT_EOK, the operation is successful.
423 * When the return value is -RT_EINVAL, it means the device handle is empty.
424 * When the return value is -RT_ENOMEM, it means insufficient memory allocation failed.
425 */
rt_pipe_open(rt_device_t device,rt_uint16_t oflag)426 rt_err_t rt_pipe_open(rt_device_t device, rt_uint16_t oflag)
427 {
428 rt_pipe_t *pipe = (rt_pipe_t *)device;
429 rt_err_t ret = RT_EOK;
430
431 if (device == RT_NULL)
432 {
433 ret = -RT_EINVAL;
434 goto __exit;
435 }
436
437 rt_mutex_take(&pipe->lock, RT_WAITING_FOREVER);
438
439 if (pipe->fifo == RT_NULL)
440 {
441 pipe->fifo = rt_ringbuffer_create(pipe->bufsz);
442 if (pipe->fifo == RT_NULL)
443 {
444 ret = -RT_ENOMEM;
445 }
446 }
447
448 rt_mutex_release(&pipe->lock);
449
450 __exit:
451 return ret;
452 }
453
454 /**
455 * @brief This function will close the pipe and release the pipe buffer.
456 *
457 * @param device is a pointer to the pipe device descriptor.
458 *
459 * @return Return the operation status.
460 * When the return value is RT_EOK, the operation is successful.
461 * When the return value is -RT_EINVAL, it means the device handle is empty.
462 */
rt_pipe_close(rt_device_t device)463 rt_err_t rt_pipe_close(rt_device_t device)
464 {
465 rt_pipe_t *pipe = (rt_pipe_t *)device;
466
467 if (device == RT_NULL)
468 {
469 return -RT_EINVAL;
470 }
471 rt_mutex_take(&pipe->lock, RT_WAITING_FOREVER);
472
473 rt_ringbuffer_destroy(pipe->fifo);
474 pipe->fifo = RT_NULL;
475
476 rt_mutex_release(&pipe->lock);
477
478 return RT_EOK;
479 }
480
481 /**
482 * @brief This function will read the specified length of data from the pipe.
483 *
484 * @param device is a pointer to the pipe device descriptor.
485 *
486 * @param pos is a parameter compatible with POSIX standard interface (currently meaningless, just pass in 0).
487 *
488 * @param buffer is a pointer to the buffer to store the read data.
489 *
490 * @param count is the length of data to be read.
491 *
492 * @return Return the length of data read.
493 * When the return value is 0, it means the pipe device handle is empty or the count is 0.
494 */
rt_pipe_read(rt_device_t device,rt_off_t pos,void * buffer,rt_size_t count)495 rt_ssize_t rt_pipe_read(rt_device_t device, rt_off_t pos, void *buffer, rt_size_t count)
496 {
497 uint8_t *pbuf;
498 rt_size_t read_bytes = 0;
499 rt_pipe_t *pipe = (rt_pipe_t *)device;
500
501 if (device == RT_NULL)
502 {
503 rt_set_errno(-EINVAL);
504 return 0;
505 }
506 if (count == 0)
507 {
508 return 0;
509 }
510
511 pbuf = (uint8_t*)buffer;
512 rt_mutex_take(&pipe->lock, RT_WAITING_FOREVER);
513
514 while (read_bytes < count)
515 {
516 int len = rt_ringbuffer_get(pipe->fifo, &pbuf[read_bytes], count - read_bytes);
517 if (len <= 0)
518 {
519 break;
520 }
521
522 read_bytes += len;
523 }
524 rt_mutex_release(&pipe->lock);
525
526 return read_bytes;
527 }
528
529 /**
530 * @brief This function will write the specified length of data to the pipe.
531 *
532 * @param device is a pointer to the pipe device descriptor.
533 *
534 * @param pos is a parameter compatible with POSIX standard interface (currently meaningless, just pass in 0).
535 *
536 * @param buffer is a pointer to the data buffer to be written.
537 *
538 * @param count is the length of data to be written.
539 *
540 * @return Return the length of data written.
541 * When the return value is 0, it means the pipe device handle is empty or the count is 0.
542 */
rt_pipe_write(rt_device_t device,rt_off_t pos,const void * buffer,rt_size_t count)543 rt_ssize_t rt_pipe_write(rt_device_t device, rt_off_t pos, const void *buffer, rt_size_t count)
544 {
545 uint8_t *pbuf;
546 rt_size_t write_bytes = 0;
547 rt_pipe_t *pipe = (rt_pipe_t *)device;
548
549 if (device == RT_NULL)
550 {
551 rt_set_errno(-EINVAL);
552 return 0;
553 }
554 if (count == 0)
555 {
556 return 0;
557 }
558
559 pbuf = (uint8_t*)buffer;
560 rt_mutex_take(&pipe->lock, RT_WAITING_FOREVER);
561
562 while (write_bytes < count)
563 {
564 int len = rt_ringbuffer_put(pipe->fifo, &pbuf[write_bytes], count - write_bytes);
565 if (len <= 0)
566 {
567 break;
568 }
569
570 write_bytes += len;
571 }
572 rt_mutex_release(&pipe->lock);
573
574 return write_bytes;
575 }
576
577 /**
578 * @brief This function is not used yet.
579 *
580 * @param dev is not used yet.
581 *
582 * @param cmd is not used yet.
583 *
584 * @param args is not used yet.
585 *
586 * @return Always return RT_EOK.
587 */
rt_pipe_control(rt_device_t dev,int cmd,void * args)588 rt_err_t rt_pipe_control(rt_device_t dev, int cmd, void *args)
589 {
590 return RT_EOK;
591 }
592
593 #ifdef RT_USING_DEVICE_OPS
594 const static struct rt_device_ops pipe_ops =
595 {
596 RT_NULL,
597 rt_pipe_open,
598 rt_pipe_close,
599 rt_pipe_read,
600 rt_pipe_write,
601 rt_pipe_control,
602 };
603 #endif /* RT_USING_DEVICE_OPS */
604
605 /**
606 * @brief This function will initialize a pipe device.
607 * The system allocates a pipe handle from dynamic heap memory, initializes the pipe handle
608 * with the specified value, and registers the pipe device with the system.
609 *
610 * @param name is the name of pipe device.
611 *
612 * @param bufsz is the size of pipe buffer.
613 *
614 * @return Return the pointer to the pipe device.
615 * When the return value is RT_NULL, it means the initialization failed.
616 */
rt_pipe_create(const char * name,int bufsz)617 rt_pipe_t *rt_pipe_create(const char *name, int bufsz)
618 {
619 rt_pipe_t *pipe;
620 rt_device_t dev;
621
622 RT_ASSERT(name != RT_NULL);
623 RT_ASSERT(bufsz < 0xFFFF);
624
625 if (rt_device_find(name) != RT_NULL)
626 {
627 /* pipe device has been created */
628 return RT_NULL;
629 }
630 pipe = (rt_pipe_t *)rt_malloc(sizeof(rt_pipe_t));
631 if (pipe == RT_NULL) return RT_NULL;
632
633 rt_memset(pipe, 0, sizeof(rt_pipe_t));
634 pipe->is_named = RT_TRUE; /* initialize as a named pipe */
635 #if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE)
636 pipe->pipeno = -1;
637 #endif
638 rt_mutex_init(&pipe->lock, name, RT_IPC_FLAG_FIFO);
639 rt_wqueue_init(&pipe->reader_queue);
640 rt_wqueue_init(&pipe->writer_queue);
641 rt_condvar_init(&pipe->waitfor_parter, "piwfp");
642
643 pipe->writer = 0;
644 pipe->reader = 0;
645
646 pipe->bufsz = bufsz;
647
648 dev = &pipe->parent;
649 dev->type = RT_Device_Class_Pipe;
650 #ifdef RT_USING_DEVICE_OPS
651 dev->ops = &pipe_ops;
652 #else
653 dev->init = RT_NULL;
654 dev->open = rt_pipe_open;
655 dev->read = rt_pipe_read;
656 dev->write = rt_pipe_write;
657 dev->close = rt_pipe_close;
658 dev->control = rt_pipe_control;
659 #endif
660
661 dev->rx_indicate = RT_NULL;
662 dev->tx_complete = RT_NULL;
663
664 rt_device_register(&pipe->parent, name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE);
665
666 #if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE)
667 dev->fops = (void *)&pipe_fops;
668 #endif
669
670 return pipe;
671 }
672
673 /**
674 * @brief This function will delete a pipe device.
675 * The system will release the pipe handle and unregister the pipe device from the system.
676 *
677 * @param pipe is the pointer to the pipe device.
678 *
679 * @return Return the operation status.
680 * When the return value is 0, it means the operation is successful.
681 * When the return value is -RT_EINVAL, it means the pipe device is not found or the device isn't a pipe.
682 * When the return value is -RT_EBUSY, it means the pipe device is busy.
683 */
rt_pipe_delete(const char * name)684 int rt_pipe_delete(const char *name)
685 {
686 int result = 0;
687 rt_device_t device;
688
689 device = rt_device_find(name);
690 if (device)
691 {
692 if (device->type == RT_Device_Class_Pipe)
693 {
694 rt_pipe_t *pipe;
695
696 pipe = (rt_pipe_t *)device;
697
698 rt_condvar_detach(&pipe->waitfor_parter);
699 rt_mutex_detach(&pipe->lock);
700 #if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE)
701 resource_id_put(&id_mgr, pipe->pipeno);
702 #endif
703 rt_device_unregister(device);
704
705 /* close fifo ringbuffer */
706 if (pipe->fifo)
707 {
708 rt_ringbuffer_destroy(pipe->fifo);
709 pipe->fifo = RT_NULL;
710 }
711 rt_free(pipe);
712 }
713 else
714 {
715 result = -ENODEV;
716 }
717 }
718 else
719 {
720 result = -ENODEV;
721 }
722
723 return result;
724 }
725
726 #if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE)
727 /**
728 * @brief This function will creat a anonymous pipe.
729 *
730 * @param fildes[0] is the read handle.
731 * fildes[1] is the write handle.
732 *
733 * @return Return the operation status.
734 * When the return value is 0, it means the operation is successful.
735 * When the return value is -1, it means the operation is failed.
736 */
pipe(int fildes[2])737 int pipe(int fildes[2])
738 {
739 rt_pipe_t *pipe;
740 char dname[8];
741 char dev_name[32];
742 int pipeno = 0;
743
744 pipeno = resource_id_get(&id_mgr);
745 if (pipeno == -1)
746 {
747 return -1;
748 }
749 rt_snprintf(dname, sizeof(dname), "pipe%d", pipeno);
750
751 pipe = rt_pipe_create(dname, RT_USING_POSIX_PIPE_SIZE);
752 if (pipe == RT_NULL)
753 {
754 resource_id_put(&id_mgr, pipeno);
755 return -1;
756 }
757
758 pipe->is_named = RT_FALSE; /* unamed pipe */
759 pipe->pipeno = pipeno;
760 rt_snprintf(dev_name, sizeof(dev_name), "/dev/%s", dname);
761
762 fildes[1] = open(dev_name, O_WRONLY, 0);
763 if (fildes[1] < 0)
764 {
765 rt_pipe_delete(dname);
766 return -1;
767 }
768
769 fildes[0] = open(dev_name, O_RDONLY, 0);
770 if (fildes[0] < 0)
771 {
772 close(fildes[1]);
773 rt_pipe_delete(dname);
774 return -1;
775 }
776
777 return 0;
778 }
779
780 /**
781 * @brief This function will create a named pipe.
782 *
783 * @param path is the name of pipe device.
784 *
785 * @param mode is not used yet.
786 *
787 * @return Return the operation status.
788 * When the return value is 0, it means the operation is successful.
789 * When the return value is -1, it means the operation is failed.
790 */
mkfifo(const char * path,mode_t mode)791 int mkfifo(const char *path, mode_t mode)
792 {
793 rt_pipe_t *pipe;
794
795 pipe = rt_pipe_create(path, RT_USING_POSIX_PIPE_SIZE);
796 if (pipe == RT_NULL)
797 {
798 return -1;
799 }
800
801 return 0;
802 }
803 #endif /* defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE) */
804