1 /****************************************************************************
2 * drivers/pipes/pipe_common.c
3 *
4 * Copyright (C) 2008-2009, 2011, 2015-2016, 2018 Gregory Nutt. All
5 * rights reserved.
6 * Author: Gregory Nutt <gnutt@nuttx.org>
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * 3. Neither the name NuttX nor the names of its contributors may be
19 * used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
29 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 *
35 ****************************************************************************/
36
37 /****************************************************************************
38 * Included Files
39 ****************************************************************************/
40
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <sys/ioctl.h>
44 #include <stdint.h>
45 #include <stdbool.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <sched.h>
49 #include <semaphore.h>
50 #include <fcntl.h>
51 #include <errno.h>
52 #include <poll.h>
53 #include "linux/wait.h"
54 #include <assert.h>
55
56 #ifdef CONFIG_DEBUG_FEATURES
57 # include <nuttx/arch.h>
58 #endif
59 #include <semaphore.h>
60 #include <fs/driver.h>
61 #include "pipe_common.h"
62 #include "los_printf.h"
63 #include "user_copy.h"
64 #ifdef LOSCFG_KERNEL_PIPE
65
66 /****************************************************************************
67 * Pre-processor Definitions
68 ****************************************************************************/
69
70 /* CONFIG_DEV_PIPEDUMP will dump the contents of each transfer into and out
71 * of the pipe.
72 */
73
74 #ifdef CONFIG_DEV_PIPEDUMP
75 # define pipe_dumpbuffer(m,a,n) lib_dumpbuffer(m,a,n)
76 #else
77 # define pipe_dumpbuffer(m,a,n)
78 #endif
79
80 /****************************************************************************
81 * Private Function Prototypes
82 ****************************************************************************/
83
84 static void pipecommon_semtake(sem_t *sem);
85
86 /****************************************************************************
87 * Private Functions
88 ****************************************************************************/
89
90 /****************************************************************************
91 * Name: pipecommon_semtake
92 ****************************************************************************/
93
pipecommon_semtake(sem_t * sem)94 static void pipecommon_semtake(sem_t *sem)
95 {
96 int ret;
97
98 do
99 {
100 /* Take the semaphore (perhaps waiting) */
101
102 ret = sem_wait(sem);
103
104 }
105 while (ret == -EINTR);
106 }
107
108 /****************************************************************************
109 * Name: pipecommon_pollnotify
110 ****************************************************************************/
111
pipecommon_pollnotify(struct pipe_dev_s * dev,pollevent_t eventset)112 static void pipecommon_pollnotify(struct pipe_dev_s *dev,
113 pollevent_t eventset)
114 {
115 if (eventset & POLLERR)
116 {
117 eventset &= ~(POLLOUT | POLLIN);
118 }
119
120 notify_poll_with_key(&dev->wq, eventset);
121 }
122
123 /****************************************************************************
124 * Public Functions
125 ****************************************************************************/
126
127 /****************************************************************************
128 * Name: pipecommon_allocdev
129 ****************************************************************************/
130
pipecommon_allocdev(size_t bufsize,const char * name)131 struct pipe_dev_s *pipecommon_allocdev(size_t bufsize, const char *name)
132 {
133 struct pipe_dev_s *dev = NULL;
134 int ret;
135
136 if (bufsize > CONFIG_DEV_PIPE_MAXSIZE)
137 {
138 return NULL;
139 }
140
141 /* Allocate a private structure to manage the pipe */
142
143 dev = (struct pipe_dev_s *)malloc(sizeof(struct pipe_dev_s));
144 if (dev)
145 {
146 /* Initialize the private structure */
147
148 (void)memset_s(dev, sizeof(struct pipe_dev_s), 0, sizeof(struct pipe_dev_s));
149 ret = strcpy_s(dev->name, sizeof(dev->name), name);
150 if (ret < 0)
151 {
152 free(dev);
153 return NULL;
154 }
155 sem_init(&dev->d_bfsem, 0, 1);
156 sem_init(&dev->d_rdsem, 0, 0);
157 sem_init(&dev->d_wrsem, 0, 0);
158 LOS_ListInit(&dev->wq.poll_queue);
159 /* The read/write wait semaphores are used for signaling and, hence,
160 * should not have priority inheritance enabled.
161 */
162
163 dev->d_bufsize = bufsize;
164 }
165
166 return dev;
167 }
168
169 /****************************************************************************
170 * Name: pipecommon_freedev
171 ****************************************************************************/
172
pipecommon_freedev(struct pipe_dev_s * dev)173 void pipecommon_freedev(struct pipe_dev_s *dev)
174 {
175 sem_destroy(&dev->d_bfsem);
176 sem_destroy(&dev->d_rdsem);
177 sem_destroy(&dev->d_wrsem);
178 free(dev);
179 }
180
181 /****************************************************************************
182 * Name: pipecommon_open
183 ****************************************************************************/
184
pipecommon_open(struct file * filep)185 int pipecommon_open(struct file *filep)
186 {
187 struct Vnode *vnode = filep->f_vnode;
188 struct pipe_dev_s *dev = (struct pipe_dev_s *)((struct drv_data *)vnode->data)->priv;
189 int sval;
190 int ret;
191
192 if (dev == NULL)
193 {
194 return -EINVAL;
195 }
196
197 /* Make sure that we have exclusive access to the device structure. The
198 * sem_wait() call should fail only if we are awakened by a signal.
199 */
200
201 ret = sem_wait(&dev->d_bfsem);
202 if (ret < 0)
203 {
204 PRINT_ERR("ERROR: sem_wait failed: %d\n", ret);
205 return ret;
206 }
207
208 /* If this the first reference on the device, then allocate the buffer.
209 * In the case of policy 1, the buffer already be present when the pipe
210 * is first opened.
211 */
212
213 if (vnode->useCount == 1 && dev->d_buffer == NULL)
214 {
215 dev->d_buffer = (uint8_t *)malloc(dev->d_bufsize);
216 if (!dev->d_buffer)
217 {
218 (void)sem_post(&dev->d_bfsem);
219 return -ENOMEM;
220 }
221 }
222
223
224 /* If opened for writing, increment the count of writers on the pipe instance */
225
226 if ((filep->f_oflags & O_WRONLY) != 0)
227 {
228 dev->d_nwriters++;
229
230 /* If this this is the first writer, then the read semaphore indicates the
231 * number of readers waiting for the first writer. Wake them all up.
232 */
233
234 if (dev->d_nwriters == 1)
235 {
236 while (sem_getvalue(&dev->d_rdsem, &sval) == 0 && sval == 0)
237 {
238 sem_post(&dev->d_rdsem);
239 }
240 }
241 }
242
243 /* If opened for reading, increment the count of reader on on the pipe instance */
244
245 if ((filep->f_oflags & O_WRONLY) == 0)
246 {
247 dev->d_nreaders++;
248 }
249
250 /* If opened for read-only, then wait for either (1) at least one writer
251 * on the pipe (policy == 0), or (2) until there is buffered data to be
252 * read (policy == 1).
253 */
254
255 (void)sem_post(&dev->d_bfsem);
256
257 if ((filep->f_oflags & O_WRONLY) == 0 && /* Read-only */
258 dev->d_nwriters < 1 && /* No writers on the pipe */
259 dev->d_wrndx == dev->d_rdndx) /* Buffer is empty */
260 {
261 /* NOTE: d_rdsem is normally used when the read logic waits for more
262 * data to be written. But until the first writer has opened the
263 * pipe, the meaning is different: it is used prevent O_RDONLY open
264 * calls from returning until there is at least one writer on the pipe.
265 * This is required both by spec and also because it prevents
266 * subsequent read() calls from returning end-of-file because there is
267 * no writer on the pipe.
268 */
269
270 ret = sem_wait(&dev->d_rdsem);
271 if (ret < 0)
272 {
273 /* The sem_wait() call should fail only if we are awakened by
274 * a signal.
275 */
276
277 PRINT_ERR("ERROR: sem_wait failed: %d\n", ret);
278
279 /* Immediately close the pipe that we just opened */
280
281 (void)pipecommon_close(filep);
282 }
283 }
284 VnodeHold();
285 vnode->useCount++;
286 VnodeDrop();
287 return ret;
288 }
289
290 /****************************************************************************
291 * Name: pipecommon_close
292 ****************************************************************************/
293
pipecommon_close(struct file * filep)294 int pipecommon_close(struct file *filep)
295 {
296 struct Vnode *vnode = filep->f_vnode;
297 struct pipe_dev_s *dev = (struct pipe_dev_s *)((struct drv_data *)vnode->data)->priv;
298 int sval;
299
300 if (dev == NULL || filep->f_vnode->useCount <= 1)
301 {
302 return -EINVAL;
303 }
304
305 /* Make sure that we have exclusive access to the device structure.
306 * NOTE: close() is supposed to return EINTR if interrupted, however
307 * I've never seen anyone check that.
308 */
309
310 pipecommon_semtake(&dev->d_bfsem);
311
312 /* Decrement the number of references on the pipe. Check if there are
313 * still outstanding references to the pipe.
314 */
315
316 /* Check if the decremented vnode reference count would go to zero */
317
318 if (vnode->useCount > 1)
319 {
320 /* More references.. If opened for writing, decrement the count of
321 * writers on the pipe instance.
322 */
323
324 if ((filep->f_oflags & O_WRONLY) != 0)
325 {
326 /* If there are no longer any writers on the pipe, then notify all of the
327 * waiting readers that they must return end-of-file.
328 */
329
330 if (--dev->d_nwriters <= 0)
331 {
332 while (sem_getvalue(&dev->d_rdsem, &sval) == 0 && sval == 0)
333 {
334 sem_post(&dev->d_rdsem);
335 }
336
337 /* Inform poll readers that other end closed. */
338
339 pipecommon_pollnotify(dev, POLLHUP);
340 }
341 }
342
343 /* If opened for reading, decrement the count of readers on the pipe
344 * instance.
345 */
346
347 if ((filep->f_oflags & O_WRONLY) == 0)
348 {
349 if (--dev->d_nreaders <= 0)
350 {
351 if (PIPE_IS_POLICY_0(dev->d_flags))
352 {
353 /* Inform poll writers that other end closed. */
354
355 pipecommon_pollnotify(dev, POLLERR);
356 }
357 }
358 }
359 }
360
361 /* What is the buffer management policy? Do we free the buffer when the
362 * last client closes the pipe policy 0, or when the buffer becomes empty.
363 * In the latter case, the buffer data will remain valid and can be
364 * obtained when the pipe is re-opened.
365 */
366
367 else if (PIPE_IS_POLICY_0(dev->d_flags) || dev->d_wrndx == dev->d_rdndx)
368 {
369 /* Policy 0 or the buffer is empty ... deallocate the buffer now. */
370
371 free(dev->d_buffer);
372 dev->d_buffer = NULL;
373
374 /* And reset all counts and indices */
375
376 dev->d_wrndx = 0;
377 dev->d_rdndx = 0;
378 dev->d_nwriters = 0;
379 dev->d_nreaders = 0;
380 }
381 VnodeHold();
382 vnode->useCount--;
383 VnodeDrop();
384 sem_post(&dev->d_bfsem);
385 return OK;
386 }
387
388 /****************************************************************************
389 * Name: pipecommon_read
390 ****************************************************************************/
391
pipecommon_read(struct file * filep,char * buffer,size_t len)392 ssize_t pipecommon_read(struct file *filep, char *buffer, size_t len)
393 {
394 struct Vnode *vnode = filep->f_vnode;
395 struct pipe_dev_s *dev = (struct pipe_dev_s *)((struct drv_data *)vnode->data)->priv;
396 ssize_t nread;
397 int sval;
398 int ret;
399 volatile int num;
400
401 if (dev == NULL)
402 {
403 return -EINVAL;
404 }
405
406 if (len == 0)
407 {
408 return 0;
409 }
410
411 if (len > MAX_READ_WRITE_LEN)
412 {
413 return -EINVAL;
414 }
415
416 /* Make sure that we have exclusive access to the device structure */
417
418 ret = sem_wait(&dev->d_bfsem);
419 if (ret < 0)
420 {
421 return ret;
422 }
423
424 /* If the pipe is empty, then wait for something to be written to it */
425
426 while (dev->d_wrndx == dev->d_rdndx)
427 {
428 /* If O_NONBLOCK was set, then return EGAIN */
429
430 if (filep->f_oflags & O_NONBLOCK)
431 {
432 sem_post(&dev->d_bfsem);
433 return -EAGAIN;
434 }
435
436 /* If there are no writers on the pipe, then return end of file */
437
438 if (dev->d_nwriters <= 0)
439 {
440 sem_post(&dev->d_bfsem);
441 return 0;
442 }
443
444 /* Otherwise, wait for something to be written to the pipe */
445
446 sem_post(&dev->d_bfsem);
447 ret = sem_wait(&dev->d_rdsem);
448
449 if (ret < 0 || (ret = sem_wait(&dev->d_bfsem)) < 0)
450 {
451 return ret;
452 }
453 }
454
455 /* Then return whatever is available in the pipe (which is at least one byte) */
456
457 nread = 0;
458 for (; ; )
459 {
460 while ((size_t)nread < len && dev->d_wrndx != dev->d_rdndx)
461 {
462 ret = LOS_ArchCopyToUser(buffer, dev->d_buffer + dev->d_rdndx, sizeof(char));
463 if (ret != 0)
464 {
465 sem_post(&dev->d_bfsem);
466 return -EFAULT;
467 }
468 buffer++;
469 if (++dev->d_rdndx >= dev->d_bufsize)
470 {
471 dev->d_rdndx = 0;
472 }
473
474 nread++;
475 }
476
477 /* Is the read complete? */
478 if ((size_t)nread >= len)
479 {
480 break;
481 }
482
483 /* Notify all waiting writers that bytes have been read from the buffer */
484
485 num = 0;
486 while (sem_getvalue(&dev->d_wrsem, &sval) == 0 && sval == 0)
487 {
488 sem_post(&dev->d_wrsem);
489 num++;
490 }
491
492 /* If there are no writers be awakened, then return */
493
494 if (num == 0 || num == 1)
495 {
496 pipecommon_pollnotify(dev, POLLOUT);
497 sem_post(&dev->d_bfsem);
498 return nread;
499 }
500
501 /* If there are no writers on the pipe, then return the number of read bytes */
502
503 if (dev->d_nwriters <= 0)
504 {
505 sem_post(&dev->d_wrsem);
506 pipecommon_pollnotify(dev, POLLOUT);
507 sem_post(&dev->d_bfsem);
508 return nread;
509 }
510
511 /* wait for something to be written to the pipe */
512 pipecommon_pollnotify(dev, POLLOUT);
513
514 while (sem_getvalue(&dev->d_rdsem, &sval) == 0 && sval != 0)
515 {
516 sem_wait(&dev->d_rdsem);
517 }
518
519 sem_post(&dev->d_bfsem);
520
521 ret = sem_wait(&dev->d_rdsem);
522 if (ret < 0)
523 {
524 return ret;
525 }
526
527 ret = sem_wait(&dev->d_bfsem);
528 if (ret < 0)
529 {
530 return ret;
531 }
532 }
533
534 /* Notify all waiting writers that bytes have been removed from the buffer */
535
536 while (sem_getvalue(&dev->d_wrsem, &sval) == 0 && sval == 0)
537 {
538 sem_post(&dev->d_wrsem);
539 }
540
541 /* Notify all poll/select waiters that they can write to the FIFO */
542
543 pipecommon_pollnotify(dev, POLLOUT);
544 sem_post(&dev->d_bfsem);
545 return nread;
546 }
547
548 /****************************************************************************
549 * Name: pipecommon_write
550 ****************************************************************************/
551
pipecommon_write(struct file * filep,const char * buffer,size_t len)552 ssize_t pipecommon_write(struct file *filep, const char *buffer,
553 size_t len)
554 {
555 struct Vnode *vnode = filep->f_vnode;
556 struct pipe_dev_s *dev = (struct pipe_dev_s *)((struct drv_data *)vnode->data)->priv;
557 ssize_t nwritten = 0;
558 ssize_t last;
559 int nxtwrndx;
560 int sval;
561 int ret;
562
563
564 if (dev == NULL)
565 {
566 return -EINVAL;
567 }
568
569 /* Handle zero-length writes */
570
571 if (len == 0)
572 {
573 return 0;
574 }
575
576 if (len > MAX_READ_WRITE_LEN)
577 {
578 return -EINVAL;
579 }
580
581 /* REVISIT: "If all file descriptors referring to the read end of a pipe
582 * have been closed, then a write will cause a SIGPIPE signal to be
583 * generated for the calling process. If the calling process is ignoring
584 * this signal, then write(2) fails with the error EPIPE."
585 */
586
587 if (dev->d_nreaders <= 0)
588 {
589 return -EPIPE;
590 }
591
592 /* At present, this method cannot be called from interrupt handlers. That
593 * is because it calls sem_wait (via pipecommon_semtake below) and
594 * sem_wait cannot be called from interrupt level. This actually
595 * happens fairly commonly IF [a-z]err() is called from interrupt handlers
596 * and stdout is being redirected via a pipe. In that case, the debug
597 * output will try to go out the pipe (interrupt handlers should use the
598 * _err() APIs).
599 *
600 * On the other hand, it would be very valuable to be able to feed the pipe
601 * from an interrupt handler! TODO: Consider disabling interrupts instead
602 * of taking semaphores so that pipes can be written from interrupt handlers
603 */
604
605 /* Make sure that we have exclusive access to the device structure */
606
607 ret = sem_wait(&dev->d_bfsem);
608 if (ret < 0)
609 {
610 return ret;
611 }
612
613 /* Loop until all of the bytes have been written */
614
615 last = 0;
616 for (; ; )
617 {
618 /* Calculate the write index AFTER the next byte is written */
619
620 nxtwrndx = dev->d_wrndx + 1;
621 if (nxtwrndx >= dev->d_bufsize)
622 {
623 nxtwrndx = 0;
624 }
625
626 /* Would the next write overflow the circular buffer? */
627
628 if (nxtwrndx != dev->d_rdndx)
629 {
630 /* No... copy the byte */
631
632
633 ret = LOS_ArchCopyFromUser(dev->d_buffer + dev->d_wrndx, buffer, sizeof(char));
634 if (ret != 0)
635 {
636 sem_post(&dev->d_bfsem);
637 return -EFAULT;
638 }
639 buffer++;
640 dev->d_wrndx = nxtwrndx;
641
642 /* Is the write complete? */
643
644 nwritten++;
645 if ((size_t)nwritten >= len)
646 {
647 /* Yes.. Notify all of the waiting readers that more data is available */
648 while (sem_getvalue(&dev->d_rdsem, &sval) == 0 && sval == 0)
649 {
650 sem_post(&dev->d_rdsem);
651 }
652
653 /* Notify all poll/select waiters that they can read from the FIFO */
654
655 pipecommon_pollnotify(dev, POLLIN);
656
657 /* Return the number of bytes written */
658
659 sem_post(&dev->d_bfsem);
660 return len;
661 }
662 }
663 else
664 {
665 /* There is not enough room for the next byte. Was anything written in this pass? */
666
667 if (last < nwritten)
668 {
669 /* Yes.. Notify all of the waiting readers that more data is available */
670
671 while (sem_getvalue(&dev->d_rdsem, &sval) == 0 && sval == 0)
672 {
673 sem_post(&dev->d_rdsem);
674 }
675
676 /* Notify all poll/select waiters that they can read from the FIFO */
677
678 pipecommon_pollnotify(dev, POLLIN);
679 }
680
681 last = nwritten;
682
683 /* If O_NONBLOCK was set, then return partial bytes written or EGAIN */
684
685 if (filep->f_oflags & O_NONBLOCK)
686 {
687 if (nwritten == 0)
688 {
689 nwritten = -EAGAIN;
690 }
691
692 sem_post(&dev->d_bfsem);
693 return nwritten;
694 }
695
696 /* There is more to be written.. wait for data to be removed from the pipe */
697
698 while (sem_getvalue(&dev->d_wrsem, &sval) == 0 && sval != 0)
699 {
700 pipecommon_semtake(&dev->d_wrsem);
701 }
702 sem_post(&dev->d_bfsem);
703
704 pipecommon_semtake(&dev->d_wrsem);
705 pipecommon_semtake(&dev->d_bfsem);
706 }
707 }
708 }
709
710 /****************************************************************************
711 * Name: pipecommon_poll
712 ****************************************************************************/
713
pipecommon_poll(struct file * filep,poll_table * table)714 int pipecommon_poll(struct file *filep, poll_table *table)
715 {
716 struct Vnode *vnode = filep->f_vnode;
717 struct pipe_dev_s *dev = (struct pipe_dev_s *)((struct drv_data *)vnode->data)->priv;
718 pollevent_t eventset;
719 pipe_ndx_t nbytes;
720 int ret;
721
722 if (dev == NULL || table == NULL)
723 {
724 return -EINVAL;
725 }
726
727 /* Are we setting up the poll? Or tearing it down? */
728
729 pipecommon_semtake(&dev->d_bfsem);
730
731 /* Should immediately notify on any of the requested events?
732 * First, determine how many bytes are in the buffer
733 */
734
735 if (dev->d_wrndx >= dev->d_rdndx)
736 {
737 nbytes = dev->d_wrndx - dev->d_rdndx;
738 }
739 else
740 {
741 nbytes = dev->d_bufsize + dev->d_wrndx - dev->d_rdndx;
742 }
743
744 /* Notify the POLLOUT event if the pipe is not full, but only if
745 * there is readers.
746 */
747
748 eventset = 0;
749 if (((filep->f_oflags & O_WRONLY) != 0) && (nbytes < (dev->d_bufsize - 1)))
750 {
751 eventset |= POLLOUT;
752 }
753
754 /* Notify the POLLIN event if the pipe is not empty */
755
756 if (((filep->f_oflags & O_WRONLY) == 0) && (nbytes > 0))
757 {
758 eventset |= POLLIN;
759 }
760
761 /* Notify the POLLHUP event if the pipe is empty and no writers */
762
763 if (nbytes == 0 && dev->d_nwriters <= 0)
764 {
765 eventset |= POLLHUP;
766 }
767
768 /* Change POLLOUT to POLLERR, if no readers and policy 0. */
769
770 if ((eventset | POLLOUT) &&
771 PIPE_IS_POLICY_0(dev->d_flags) &&
772 dev->d_nreaders <= 0)
773 {
774 eventset |= POLLERR;
775 }
776
777 ret = eventset & table->key;
778 if (ret == 0)
779 {
780 poll_wait(NULL, &dev->wq, table);
781 }
782 sem_post(&dev->d_bfsem);
783
784 return ret;
785 }
786
787 /****************************************************************************
788 * Name: pipecommon_ioctl
789 ****************************************************************************/
790
pipecommon_ioctl(struct file * filep,int cmd,unsigned long arg)791 int pipecommon_ioctl(struct file *filep, int cmd, unsigned long arg)
792 {
793 return -ENOSYS;
794 }
795
796 /****************************************************************************
797 * Name: pipecommon_unlink
798 ****************************************************************************/
799
800 #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
pipecommon_unlink(struct Vnode * vnode)801 int pipecommon_unlink(struct Vnode *vnode)
802 {
803 struct pipe_dev_s *dev = NULL;
804
805 if (vnode == NULL || vnode->data == NULL)
806 {
807 return -EINVAL;
808 }
809
810 dev = ((struct drv_data *)vnode->data)->priv;
811 if (dev == NULL)
812 {
813 return -EINVAL;
814 }
815
816 if (dev->d_buffer)
817 {
818 free(dev->d_buffer);
819 }
820
821 /* And free the device structure. */
822 unregister_driver(dev->name);
823 pipecommon_freedev(dev);
824
825 return OK;
826 }
827 #endif
828
829 #endif /* LOSCFG_KERNEL_PIPE */
830