Changeset 03661d19 in mainline for uspace/lib/fdisk/src/cap.c


Ignore:
Timestamp:
2015-10-29T10:16:08Z (8 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
55f8c6e7
Parents:
9854a8f
Message:

Handle simplified capacity entry.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/fdisk/src/cap.c

    r9854a8f r03661d19  
    7676 * of bytes is not divisible by the number of blocks, it is rounded
    7777 * up to an integer number of blocks.
    78  */
    79 int fdisk_cap_to_blocks(fdisk_cap_t *cap, size_t block_size,
    80     uint64_t *blocks)
     78 *
     79 * A capacity value entails precision, i.e. it corresponds to a range
     80 * of values. @a cvsel selects the value to return. @c fcv_nom gives
     81 * the nominal (middle) value, @c fcv_min gives the minimum value
     82 * and @c fcv_max gives the maximum value.
     83 */
     84int fdisk_cap_to_blocks(fdisk_cap_t *cap, fdisk_cvsel_t cvsel,
     85    size_t block_size, uint64_t *rblocks)
    8186{
    8287        int exp;
    8388        uint64_t bytes;
    8489        uint64_t f;
     90        uint64_t adj;
     91        uint64_t blocks;
     92        uint64_t rem;
    8593        int rc;
    8694
    87         // XXX Check for overflow
     95        printf("fdisk_cap_to_blocks: m=%" PRIu64 ", dp=%d, cunit=%d\n",
     96            cap->m, cap->dp, cap->cunit);
    8897
    8998        exp = cap->cunit * 3 - cap->dp;
     
    93102                        return ERANGE;
    94103                bytes = (cap->m + (f / 2)) / f;
     104                if (bytes * f - (f / 2) != cap->m)
     105                        return ERANGE;
    95106        } else {
    96107                rc = ipow10_u64(exp, &f);
    97108                if (rc != EOK)
    98109                        return ERANGE;
    99                 bytes = cap->m * f;
    100         }
    101 
    102         *blocks = (bytes + block_size - 1) / block_size;
     110
     111                adj = 0;
     112                switch (cvsel) {
     113                case fcv_nom:
     114                        adj = 0;
     115                        break;
     116                case fcv_min:
     117                        adj = -(f / 2);
     118                        break;
     119                case fcv_max:
     120                        adj = f / 2 - 1;
     121                        break;
     122                }
     123
     124                printf("f=%" PRIu64 ", adj=%" PRId64 "\n", f, adj);
     125                bytes = cap->m * f + adj;
     126                printf("bytes=%" PRIu64 "\n", bytes);
     127                if ((bytes - adj) / f != cap->m)
     128                        return ERANGE;
     129        }
     130
     131        rem = bytes % block_size;
     132        if ((bytes + rem) < bytes)
     133                return ERANGE;
     134
     135        blocks = (bytes + rem) / block_size;
     136        printf("blocks=%" PRIu64 "\n", blocks);
     137
     138        *rblocks = blocks;
    103139        return EOK;
    104140}
     
    185221}
    186222
     223static int fdisk_digit_val(char c, int *val)
     224{
     225        switch (c) {
     226        case '0': *val = 0; break;
     227        case '1': *val = 1; break;
     228        case '2': *val = 2; break;
     229        case '3': *val = 3; break;
     230        case '4': *val = 4; break;
     231        case '5': *val = 5; break;
     232        case '6': *val = 6; break;
     233        case '7': *val = 7; break;
     234        case '8': *val = 8; break;
     235        case '9': *val = 9; break;
     236        default:
     237                return EINVAL;
     238        }
     239
     240        return EOK;
     241}
     242
    187243int fdisk_cap_parse(const char *str, fdisk_cap_t *cap)
    188244{
    189         char *eptr;
    190         char *p;
    191         unsigned long val;
     245        const char *eptr;
     246        const char *p;
     247        int d;
     248        int dp;
     249        unsigned long m;
    192250        int i;
    193251
    194         val = strtoul(str, &eptr, 10);
     252        m = 0;
     253
     254        eptr = str;
     255        while (fdisk_digit_val(*eptr, &d) == EOK) {
     256                m = m * 10 + d;
     257                ++eptr;
     258        }
     259
     260        if (*eptr == '.') {
     261                ++eptr;
     262                dp = 0;
     263                while (fdisk_digit_val(*eptr, &d) == EOK) {
     264                        m = m * 10 + d;
     265                        ++dp;
     266                        ++eptr;
     267                }
     268        } else {
     269                m = 0; dp = 0;
     270        }
    195271
    196272        while (*eptr == ' ')
     
    216292        }
    217293
    218         cap->m = val;
    219         cap->dp = 0;
     294        cap->m = m;
     295        cap->dp = dp;
    220296        return EOK;
    221297}
Note: See TracChangeset for help on using the changeset viewer.