4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "%Z%%M% %I% %E% SMI"
27
28 #include <sys/types.h>
29 #include <sys/param.h>
30 #include <sys/sysmacros.h>
31 #include <sys/systm.h>
32 #include <sys/time.h>
33 #include <sys/vfs.h>
34 #include <sys/vnode.h>
35 #include <sys/errno.h>
36 #include <sys/cmn_err.h>
37 #include <sys/cred.h>
38 #include <sys/stat.h>
39 #include <sys/debug.h>
40 #include <sys/policy.h>
41 #include <sys/fs/tmpnode.h>
42 #include <sys/fs/tmp.h>
43 #include <sys/vtrace.h>
44
45 static int tdircheckpath(struct tmpnode *, struct tmpnode *, struct cred *);
46 static int tdirrename(struct tmpnode *, struct tmpnode *, struct tmpnode *,
47 char *, struct tmpnode *, struct tdirent *, struct cred *);
470 if (dir->tn_dir == NULL)
471 return (ENOENT);
472
473 tpdp = tmpfs_hash_lookup(nm, dir, 0, &tnp);
474 if (tpdp == NULL) {
475 /*
476 * If it is gone, some other thread got here first!
477 * Return error ENOENT.
478 */
479 return (ENOENT);
480 }
481
482 /*
483 * If the tmpnode in the tdirent changed, we were probably
484 * the victim of a concurrent rename operation. The original
485 * is gone, so return that status (same as UFS).
486 */
487 if (tp != tnp)
488 return (ENOENT);
489
490 tmpfs_hash_out(tpdp);
491
492 /*
493 * Take tpdp out of the directory list.
494 */
495 ASSERT(tpdp->td_next != tpdp);
496 ASSERT(tpdp->td_prev != tpdp);
497 if (tpdp->td_prev) {
498 tpdp->td_prev->td_next = tpdp->td_next;
499 }
500 if (tpdp->td_next) {
501 tpdp->td_next->td_prev = tpdp->td_prev;
502 }
503
504 /*
505 * If the roving slot pointer happens to match tpdp,
506 * point it at the previous dirent.
507 */
508 if (dir->tn_dir->td_prev == tpdp) {
509 dir->tn_dir->td_prev = tpdp->td_prev;
510 }
511 ASSERT(tpdp->td_next != tpdp);
512 ASSERT(tpdp->td_prev != tpdp);
513
514 /*
515 * tpdp points to the correct directory entry
516 */
517 namelen = strlen(tpdp->td_name) + 1;
518
519 tmp_memfree(tpdp, sizeof (struct tdirent) + namelen);
520 dir->tn_size -= (sizeof (struct tdirent) + namelen);
521 dir->tn_dirents--;
522
523 gethrestime(&now);
524 dir->tn_mtime = now;
525 dir->tn_ctime = now;
526 tp->tn_ctime = now;
527
528 ASSERT(tp->tn_nlink > 0);
529 DECR_COUNT(&tp->tn_nlink, &tp->tn_tlock);
530 if (op == DR_RMDIR && tp->tn_type == VDIR) {
531 tdirtrunc(tp);
532 ASSERT(tp->tn_nlink == 0);
533 }
534 return (0);
535 }
536
537 /*
538 * tdirinit is used internally to initialize a directory (dir)
539 * with '.' and '..' entries without checking permissions and locking
540 */
541 void
542 tdirinit(
543 struct tmpnode *parent, /* parent of directory to initialize */
544 struct tmpnode *dir) /* the new directory */
545 {
546 struct tdirent *dot, *dotdot;
547 timestruc_t now;
548
549 ASSERT(RW_WRITE_HELD(&parent->tn_rwlock));
550 ASSERT(dir->tn_type == VDIR);
|
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 *
25 * Copyright 2016 RackTop Systems.
26 */
27
28 #include <sys/types.h>
29 #include <sys/param.h>
30 #include <sys/sysmacros.h>
31 #include <sys/systm.h>
32 #include <sys/time.h>
33 #include <sys/vfs.h>
34 #include <sys/vnode.h>
35 #include <sys/errno.h>
36 #include <sys/cmn_err.h>
37 #include <sys/cred.h>
38 #include <sys/stat.h>
39 #include <sys/debug.h>
40 #include <sys/policy.h>
41 #include <sys/fs/tmpnode.h>
42 #include <sys/fs/tmp.h>
43 #include <sys/vtrace.h>
44
45 static int tdircheckpath(struct tmpnode *, struct tmpnode *, struct cred *);
46 static int tdirrename(struct tmpnode *, struct tmpnode *, struct tmpnode *,
47 char *, struct tmpnode *, struct tdirent *, struct cred *);
470 if (dir->tn_dir == NULL)
471 return (ENOENT);
472
473 tpdp = tmpfs_hash_lookup(nm, dir, 0, &tnp);
474 if (tpdp == NULL) {
475 /*
476 * If it is gone, some other thread got here first!
477 * Return error ENOENT.
478 */
479 return (ENOENT);
480 }
481
482 /*
483 * If the tmpnode in the tdirent changed, we were probably
484 * the victim of a concurrent rename operation. The original
485 * is gone, so return that status (same as UFS).
486 */
487 if (tp != tnp)
488 return (ENOENT);
489
490 /*
491 * If we are unlinking a directory which isn't empty (it has
492 * more than the minumum '.' and '..' entries) return EEXIST.
493 */
494 if (tp->tn_type == VDIR && tp->tn_dirents > 2)
495 return (EEXIST);
496
497 tmpfs_hash_out(tpdp);
498
499 /*
500 * Take tpdp out of the directory list.
501 */
502 ASSERT(tpdp->td_next != tpdp);
503 ASSERT(tpdp->td_prev != tpdp);
504 if (tpdp->td_prev) {
505 tpdp->td_prev->td_next = tpdp->td_next;
506 }
507 if (tpdp->td_next) {
508 tpdp->td_next->td_prev = tpdp->td_prev;
509 }
510
511 /*
512 * If the roving slot pointer happens to match tpdp,
513 * point it at the previous dirent.
514 */
515 if (dir->tn_dir->td_prev == tpdp) {
516 dir->tn_dir->td_prev = tpdp->td_prev;
517 }
518 ASSERT(tpdp->td_next != tpdp);
519 ASSERT(tpdp->td_prev != tpdp);
520
521 /*
522 * tpdp points to the correct directory entry
523 */
524 namelen = strlen(tpdp->td_name) + 1;
525
526 tmp_memfree(tpdp, sizeof (struct tdirent) + namelen);
527 dir->tn_size -= (sizeof (struct tdirent) + namelen);
528 dir->tn_dirents--;
529
530 gethrestime(&now);
531 dir->tn_mtime = now;
532 dir->tn_ctime = now;
533 tp->tn_ctime = now;
534
535 ASSERT(tp->tn_nlink > 0);
536 DECR_COUNT(&tp->tn_nlink, &tp->tn_tlock);
537 if (tp->tn_type == VDIR) {
538 tdirtrunc(tp);
539 ASSERT(tp->tn_nlink == 0);
540 }
541 return (0);
542 }
543
544 /*
545 * tdirinit is used internally to initialize a directory (dir)
546 * with '.' and '..' entries without checking permissions and locking
547 */
548 void
549 tdirinit(
550 struct tmpnode *parent, /* parent of directory to initialize */
551 struct tmpnode *dir) /* the new directory */
552 {
553 struct tdirent *dot, *dotdot;
554 timestruc_t now;
555
556 ASSERT(RW_WRITE_HELD(&parent->tn_rwlock));
557 ASSERT(dir->tn_type == VDIR);
|