| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: vfs_quotactl.c,v 1.25 2012/01/29 07:06:01 dholland Exp $ */ | | 1 | /* $NetBSD: vfs_quotactl.c,v 1.26 2012/01/29 07:06:37 dholland Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1991, 1993, 1994 | | 4 | * Copyright (c) 1991, 1993, 1994 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * (c) UNIX System Laboratories, Inc. | | 6 | * (c) UNIX System Laboratories, Inc. |
7 | * All or some portions of this file are derived from material licensed | | 7 | * All or some portions of this file are derived from material licensed |
8 | * to the University of California by American Telephone and Telegraph | | 8 | * to the University of California by American Telephone and Telegraph |
9 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with | | 9 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with |
10 | * the permission of UNIX System Laboratories, Inc. | | 10 | * the permission of UNIX System Laboratories, Inc. |
11 | * | | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | | 12 | * Redistribution and use in source and binary forms, with or without |
13 | * modification, are permitted provided that the following conditions | | 13 | * modification, are permitted provided that the following conditions |
14 | * are met: | | 14 | * are met: |
| @@ -70,27 +70,27 @@ | | | @@ -70,27 +70,27 @@ |
70 | * | | 70 | * |
71 | * @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95 | | 71 | * @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95 |
72 | * From NetBSD: ufs_quota.c,v 1.70 2011/03/24 17:05:46 bouyer Exp | | 72 | * From NetBSD: ufs_quota.c,v 1.70 2011/03/24 17:05:46 bouyer Exp |
73 | */ | | 73 | */ |
74 | | | 74 | |
75 | /* | | 75 | /* |
76 | * Note that both of the copyrights above are moderately spurious; | | 76 | * Note that both of the copyrights above are moderately spurious; |
77 | * this code should almost certainly have the Copyright 2010 Manuel | | 77 | * this code should almost certainly have the Copyright 2010 Manuel |
78 | * Bouyer notice and license found in e.g. sys/ufs/ufs/quota2_subr.c. | | 78 | * Bouyer notice and license found in e.g. sys/ufs/ufs/quota2_subr.c. |
79 | * However, they're what was on the files this code was sliced out of. | | 79 | * However, they're what was on the files this code was sliced out of. |
80 | */ | | 80 | */ |
81 | | | 81 | |
82 | #include <sys/cdefs.h> | | 82 | #include <sys/cdefs.h> |
83 | __KERNEL_RCSID(0, "$NetBSD: vfs_quotactl.c,v 1.25 2012/01/29 07:06:01 dholland Exp $"); | | 83 | __KERNEL_RCSID(0, "$NetBSD: vfs_quotactl.c,v 1.26 2012/01/29 07:06:37 dholland Exp $"); |
84 | | | 84 | |
85 | #include <sys/malloc.h> /* XXX: temporary */ | | 85 | #include <sys/malloc.h> /* XXX: temporary */ |
86 | #include <sys/mount.h> | | 86 | #include <sys/mount.h> |
87 | #include <sys/quota.h> | | 87 | #include <sys/quota.h> |
88 | #include <sys/quotactl.h> | | 88 | #include <sys/quotactl.h> |
89 | #include <quota/quotaprop.h> | | 89 | #include <quota/quotaprop.h> |
90 | | | 90 | |
91 | static int | | 91 | static int |
92 | vfs_quotactl_getversion(struct mount *mp, | | 92 | vfs_quotactl_getversion(struct mount *mp, |
93 | prop_dictionary_t cmddict, int q2type, | | 93 | prop_dictionary_t cmddict, int q2type, |
94 | prop_array_t datas) | | 94 | prop_array_t datas) |
95 | { | | 95 | { |
96 | prop_array_t replies; | | 96 | prop_array_t replies; |
| @@ -429,101 +429,120 @@ vfs_quotactl_put(struct mount *mp, | | | @@ -429,101 +429,120 @@ vfs_quotactl_put(struct mount *mp, |
429 | if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) { | | 429 | if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) { |
430 | error = ENOMEM; | | 430 | error = ENOMEM; |
431 | } else { | | 431 | } else { |
432 | error = 0; | | 432 | error = 0; |
433 | } | | 433 | } |
434 | return error; | | 434 | return error; |
435 | err: | | 435 | err: |
436 | prop_object_iterator_release(iter); | | 436 | prop_object_iterator_release(iter); |
437 | prop_object_release(replies); | | 437 | prop_object_release(replies); |
438 | return error; | | 438 | return error; |
439 | } | | 439 | } |
440 | | | 440 | |
441 | static prop_dictionary_t | | 441 | static prop_dictionary_t |
442 | vfs_quotactl_getall_makereply(id_t id, int def, | | 442 | vfs_quotactl_getall_makereply(const struct quotakey *key) |
443 | const struct quotaval *blocks, | | 443 | { |
444 | const struct quotaval *files) | | 444 | prop_dictionary_t dict; |
| | | 445 | id_t id; |
| | | 446 | int defaultq; |
| | | 447 | |
| | | 448 | dict = prop_dictionary_create(); |
| | | 449 | if (dict == NULL) |
| | | 450 | return NULL; |
| | | 451 | |
| | | 452 | id = key->qk_id; |
| | | 453 | if (id == QUOTA_DEFAULTID) { |
| | | 454 | id = 0; |
| | | 455 | defaultq = 1; |
| | | 456 | } else { |
| | | 457 | defaultq = 0; |
| | | 458 | } |
| | | 459 | |
| | | 460 | if (defaultq) { |
| | | 461 | if (!prop_dictionary_set_cstring_nocopy(dict, "id", |
| | | 462 | "default")) { |
| | | 463 | goto err; |
| | | 464 | } |
| | | 465 | } else { |
| | | 466 | if (!prop_dictionary_set_uint32(dict, "id", id)) { |
| | | 467 | goto err; |
| | | 468 | } |
| | | 469 | } |
| | | 470 | |
| | | 471 | return dict; |
| | | 472 | |
| | | 473 | err: |
| | | 474 | prop_object_release(dict); |
| | | 475 | return NULL; |
| | | 476 | } |
| | | 477 | |
| | | 478 | static int |
| | | 479 | vfs_quotactl_getall_addreply(prop_dictionary_t thisreply, |
| | | 480 | const struct quotakey *key, const struct quotaval *val) |
445 | { | | 481 | { |
446 | #define INITQVNAMES_ALL { \ | | 482 | #define INITQVNAMES_ALL { \ |
447 | QUOTADICT_LIMIT_HARD, \ | | 483 | QUOTADICT_LIMIT_HARD, \ |
448 | QUOTADICT_LIMIT_SOFT, \ | | 484 | QUOTADICT_LIMIT_SOFT, \ |
449 | QUOTADICT_LIMIT_USAGE, \ | | 485 | QUOTADICT_LIMIT_USAGE, \ |
450 | QUOTADICT_LIMIT_ETIME, \ | | 486 | QUOTADICT_LIMIT_ETIME, \ |
451 | QUOTADICT_LIMIT_GTIME \ | | 487 | QUOTADICT_LIMIT_GTIME \ |
452 | } | | 488 | } |
453 | #define N_QV 5 | | 489 | #define N_QV 5 |
454 | | | 490 | |
455 | const char *val_names[] = INITQVNAMES_ALL; | | 491 | const char *val_names[] = INITQVNAMES_ALL; |
456 | uint64_t vals[N_QV]; | | 492 | uint64_t vals[N_QV]; |
457 | prop_dictionary_t dict1 = prop_dictionary_create(); | | | |
458 | prop_dictionary_t dict2; | | 493 | prop_dictionary_t dict2; |
| | | 494 | const char *objtypename; |
459 | | | 495 | |
460 | if (dict1 == NULL) | | 496 | switch (key->qk_objtype) { |
461 | return NULL; | | 497 | case QUOTA_OBJTYPE_BLOCKS: |
462 | | | 498 | objtypename = QUOTADICT_LTYPE_BLOCK; |
463 | if (def) { | | 499 | break; |
464 | if (!prop_dictionary_set_cstring_nocopy(dict1, "id", | | 500 | case QUOTA_OBJTYPE_FILES: |
465 | "default")) { | | 501 | objtypename = QUOTADICT_LTYPE_FILE; |
466 | goto err; | | 502 | break; |
467 | } | | 503 | default: |
468 | } else { | | 504 | return EINVAL; |
469 | if (!prop_dictionary_set_uint32(dict1, "id", id)) { | | | |
470 | goto err; | | | |
471 | } | | | |
472 | } | | 505 | } |
473 | | | 506 | |
474 | vals[0] = blocks->qv_hardlimit; | | 507 | vals[0] = val->qv_hardlimit; |
475 | vals[1] = blocks->qv_softlimit; | | 508 | vals[1] = val->qv_softlimit; |
476 | vals[2] = blocks->qv_usage; | | 509 | vals[2] = val->qv_usage; |
477 | vals[3] = blocks->qv_expiretime; | | 510 | vals[3] = val->qv_expiretime; |
478 | vals[4] = blocks->qv_grace; | | 511 | vals[4] = val->qv_grace; |
479 | dict2 = limits64toprop(vals, val_names, N_QV); | | | |
480 | if (dict2 == NULL) | | | |
481 | goto err; | | | |
482 | if (!prop_dictionary_set_and_rel(dict1, QUOTADICT_LTYPE_BLOCK, dict2)) | | | |
483 | goto err; | | | |
484 | | | | |
485 | | | | |
486 | vals[0] = files->qv_hardlimit; | | | |
487 | vals[1] = files->qv_softlimit; | | | |
488 | vals[2] = files->qv_usage; | | | |
489 | vals[3] = files->qv_expiretime; | | | |
490 | vals[4] = files->qv_grace; | | | |
491 | dict2 = limits64toprop(vals, val_names, N_QV); | | 512 | dict2 = limits64toprop(vals, val_names, N_QV); |
492 | if (dict2 == NULL) | | 513 | if (dict2 == NULL) |
493 | goto err; | | 514 | return ENOMEM; |
494 | if (!prop_dictionary_set_and_rel(dict1, QUOTADICT_LTYPE_FILE, dict2)) | | | |
495 | goto err; | | | |
496 | | | 515 | |
497 | return dict1; | | 516 | if (!prop_dictionary_set_and_rel(thisreply, objtypename, dict2)) |
| | | 517 | return ENOMEM; |
498 | | | 518 | |
499 | err: | | 519 | return 0; |
500 | prop_object_release(dict1); | | | |
501 | return NULL; | | | |
502 | } | | 520 | } |
503 | | | 521 | |
504 | static int | | 522 | static int |
505 | vfs_quotactl_getall(struct mount *mp, | | 523 | vfs_quotactl_getall(struct mount *mp, |
506 | prop_dictionary_t cmddict, int q2type, | | 524 | prop_dictionary_t cmddict, int q2type, |
507 | prop_array_t datas) | | 525 | prop_array_t datas) |
508 | { | | 526 | { |
509 | struct quotakcursor cursor; | | 527 | struct quotakcursor cursor; |
510 | struct quota_getall_result result; | | 528 | struct quota_getall_result result; |
511 | struct vfs_quotactl_args args; | | 529 | struct vfs_quotactl_args args; |
512 | prop_array_t replies; | | 530 | prop_array_t replies; |
513 | prop_dictionary_t dict; | | 531 | prop_dictionary_t thisreply; |
| | | 532 | struct quotakey *key; |
| | | 533 | struct quotaval *val; |
| | | 534 | id_t lastid; |
514 | unsigned i; | | 535 | unsigned i; |
515 | id_t id; | | | |
516 | int defaultq; | | | |
517 | int error, error2; | | 536 | int error, error2; |
518 | int skip = 0; | | 537 | int skip = 0; |
519 | | | 538 | |
520 | KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY); | | 539 | KASSERT(prop_object_type(cmddict) == PROP_TYPE_DICTIONARY); |
521 | | | 540 | |
522 | args.qc_type = QCT_CURSOROPEN; | | 541 | args.qc_type = QCT_CURSOROPEN; |
523 | args.u.cursoropen.qc_cursor = &cursor; | | 542 | args.u.cursoropen.qc_cursor = &cursor; |
524 | error = VFS_QUOTACTL(mp, QUOTACTL_CURSOROPEN, &args); | | 543 | error = VFS_QUOTACTL(mp, QUOTACTL_CURSOROPEN, &args); |
525 | if (error) { | | 544 | if (error) { |
526 | return error; | | 545 | return error; |
527 | } | | 546 | } |
528 | | | 547 | |
529 | result.qr_keys = NULL; | | 548 | result.qr_keys = NULL; |
| @@ -551,43 +570,54 @@ vfs_quotactl_getall(struct mount *mp, | | | @@ -551,43 +570,54 @@ vfs_quotactl_getall(struct mount *mp, |
551 | goto err; | | 570 | goto err; |
552 | } | | 571 | } |
553 | | | 572 | |
554 | replies = prop_array_create(); | | 573 | replies = prop_array_create(); |
555 | if (replies == NULL) { | | 574 | if (replies == NULL) { |
556 | error = ENOMEM; | | 575 | error = ENOMEM; |
557 | goto err; | | 576 | goto err; |
558 | } | | 577 | } |
559 | | | 578 | |
560 | if (skip) { | | 579 | if (skip) { |
561 | goto skip; | | 580 | goto skip; |
562 | } | | 581 | } |
563 | | | 582 | |
564 | for (i = 0; i < result.qr_num; i += 2) { | | 583 | thisreply = NULL; |
565 | id = result.qr_keys[i].qk_id; | | 584 | lastid = 0; /* value not actually referenced */ |
566 | if (id == QUOTA_DEFAULTID) { | | 585 | for (i = 0; i < result.qr_num; i++) { |
567 | id = 0; | | 586 | key = &result.qr_keys[i]; |
568 | defaultq = 1; | | 587 | val = &result.qr_vals[i]; |
569 | } else { | | 588 | |
570 | defaultq = 0; | | 589 | if (thisreply == NULL || key->qk_id != lastid) { |
571 | } | | 590 | lastid = key->qk_id; |
572 | dict = vfs_quotactl_getall_makereply(id, defaultq, | | 591 | thisreply = vfs_quotactl_getall_makereply(key); |
573 | &result.qr_vals[i], | | 592 | if (thisreply == NULL) { |
574 | &result.qr_vals[i+1]); | | 593 | error = ENOMEM; |
575 | if (dict == NULL) { | | 594 | goto err; |
576 | error = ENOMEM; | | 595 | } |
577 | goto err; | | 596 | /* |
| | | 597 | * Note: while we release our reference to |
| | | 598 | * thisreply here, we can (and do) continue to |
| | | 599 | * use the pointer in the loop because the |
| | | 600 | * copy attached to the replies array is not |
| | | 601 | * going away. |
| | | 602 | */ |
| | | 603 | if (!prop_array_add_and_rel(replies, thisreply)) { |
| | | 604 | error = ENOMEM; |
| | | 605 | goto err; |
| | | 606 | } |
578 | } | | 607 | } |
579 | if (!prop_array_add_and_rel(replies, dict)) { | | 608 | |
580 | error = ENOMEM; | | 609 | error = vfs_quotactl_getall_addreply(thisreply, key, val); |
| | | 610 | if (error) { |
581 | goto err; | | 611 | goto err; |
582 | } | | 612 | } |
583 | } | | 613 | } |
584 | | | 614 | |
585 | skip: | | 615 | skip: |
586 | | | 616 | |
587 | if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) { | | 617 | if (!prop_dictionary_set_and_rel(cmddict, "data", replies)) { |
588 | error = ENOMEM; | | 618 | error = ENOMEM; |
589 | goto err; | | 619 | goto err; |
590 | } | | 620 | } |
591 | | | 621 | |
592 | error = 0; | | 622 | error = 0; |
593 | err: | | 623 | err: |