1/*
2 * Copyright 2016, NICTA
3 *
4 * This software may be distributed and modified according to the terms of
5 * the GNU General Public License version 2. Note that NO WARRANTY is provided.
6 * See "LICENSE_GPLv2.txt" for details.
7 *
8 * @TAG(NICTA_GPL)
9 */
10
11#include <bilbyfs.h>
12
13static u8 inode_mode_to_dent_type(umode_t mode)
14{
15        switch (mode & S_IFMT) {
16        case S_IFREG:  return BILBYFS_ITYPE_REG;
17        case S_IFDIR:  return BILBYFS_ITYPE_DIR;
18        case S_IFLNK:  return BILBYFS_ITYPE_LNK;
19        case S_IFSOCK: return BILBYFS_ITYPE_SOCK;
20        case S_IFIFO:  return BILBYFS_ITYPE_FIFO;
21        case S_IFBLK:  return BILBYFS_ITYPE_BLK;
22        case S_IFCHR:  return BILBYFS_ITYPE_CHR;
23        default: bilbyfs_assert(0);
24        }
25        return 0;
26}
27
28int check_obj_header(void *obj, int max_obj_sz)
29{
30        struct obj_ch *ch = obj;
31        u32 offs;
32        u32 crc;
33
34        if (max_obj_sz < BILBYFS_CH_SZ)
35                return -ENOENT;
36        if (le32_to_cpu(ch->magic) != BILBYFS_OBJ_MAGIC)
37                return -ENOENT;
38        if (le32_to_cpu(ch->len) < BILBYFS_CH_SZ ||
39            le32_to_cpu(ch->len) > max_obj_sz) {
40                bilbyfs_err("Invalid object size (%d vs %d)", le32_to_cpu(ch->len), max_obj_sz);
41                return -EINVAL;
42        }
43        offs = offsetof(struct obj_ch, crc) + sizeof(ch->crc);
44        crc = crc32(BILBYFS_CRC32_INIT, obj + offs, le32_to_cpu(ch->len) - offs);
45        if (crc != le32_to_cpu(ch->crc)) {
46                bilbyfs_err("Invalid CRC32 for object %x != %x, obj->type=%d\n", crc, le32_to_cpu(ch->crc), ch->type);
47                return -EINVAL;
48        }
49        /* FIXME: More sanity checking?? */
50        return 0;
51}
52
53void pack_obj_header(void *obj, u64 sqnum, u8 trans_pos)
54{
55        struct obj_ch *ch = obj;
56        uint32_t crc;
57        int offs;
58
59        bilbyfs_assert(ch->type < BILBYFS_OBJ_TYPES_CNT);
60
61        ch->magic = cpu_to_le32(BILBYFS_OBJ_MAGIC);
62        ch->sqnum = cpu_to_le64(sqnum);
63        ch->trans = trans_pos;
64        zero_obj_ch_unused(ch);
65
66        /* we CRC right after the field crc to the end of the object */
67        offs = offsetof(struct obj_ch, crc) + sizeof(ch->crc);
68        crc = crc32(BILBYFS_CRC32_INIT, obj + offs, le32_to_cpu(ch->len) - offs);
69        ch->crc = cpu_to_le32(crc);
70}
71
72__le32 len_to_le32(int len)
73{
74        bilbyfs_assert(len >= BILBYFS_CH_SZ);
75        return cpu_to_le32(ALIGN(len, BILBYFS_OBJ_PADDING));
76}
77
78void pack_obj_inode(struct obj_inode *ino, struct inode *inode)
79{
80        struct bilbyfs_inode *binode = inode_to_binode(inode);
81
82        ino->ch.type = BILBYFS_INODE_OBJ;
83        ino->ch.len = len_to_le32(BILBYFS_INODE_SZ);
84
85        ino->id = cpu_to_le64(inode_id_init(inode->i_ino));
86        ino->creat_sqnum = cpu_to_le64(binode->creat_sqnum);
87        ino->size  = cpu_to_le64(inode->i_size);
88        ino->atime_sec = cpu_to_le64(inode->i_atime.tv_sec);
89        ino->ctime_sec = cpu_to_le64(inode->i_ctime.tv_sec);
90        ino->mtime_sec = cpu_to_le64(inode->i_mtime.tv_sec);
91        ino->nlink = cpu_to_le32(inode->i_nlink);
92        ino->uid   = cpu_to_le32(i_uid_read(inode));
93        ino->gid   = cpu_to_le32(i_gid_read(inode));
94        ino->mode  = cpu_to_le32(inode->i_mode);
95        ino->flags = cpu_to_le32(binode->flags);
96        zero_obj_inode_unused(ino);
97}
98
99void pack_obj_dentarr(struct obj_dentarr *dentarr, obj_id id,
100                      int nbdentry, int size)
101{
102        dentarr->ch.type = BILBYFS_DENTARR_OBJ;
103        dentarr->ch.len = len_to_le32(size);
104
105        dentarr->id = cpu_to_le64(id);
106        dentarr->nb_dentry = cpu_to_le32(nbdentry);
107        dentarr->size = cpu_to_le32(size);
108        zero_obj_dentarr_unused(dentarr);
109}
110
111void pack_obj_data(struct obj_data *odata, obj_id id, int sz_data,
112                   const void *data)
113{
114        odata->ch.type = BILBYFS_DATA_OBJ;
115        odata->ch.len = len_to_le32(BILBYFS_DATA_SZ + sz_data);
116
117        odata->id = cpu_to_le64(id);
118        odata->size = cpu_to_le32(sz_data);
119        memcpy(odata->data, data, sz_data);
120        zero_obj_data_unused(odata);
121}
122
123void pack_obj_dentry(struct obj_dentry *de, struct inode *inode,
124                     const char *name)
125{
126        de->ino = cpu_to_le32(inode->i_ino);
127        de->type = inode_mode_to_dent_type(inode->i_mode);
128        /* The dentry.nlen field does not include the \0 */
129        de->nlen = cpu_to_le16(strlen(name));
130        strcpy(de->name, name);
131        zero_obj_dentry_unused(de);
132}
133
134void pack_obj_pad(struct obj_ch *pad, int pad_sz)
135{
136        pad->type = BILBYFS_PAD_OBJ;
137        pad->len = len_to_le32(pad_sz);
138
139        memset(pad + 1, BILBYFS_PAD_BYTE, pad_sz - BILBYFS_CH_SZ);
140}
141
142void unpack_obj_inode(struct inode *inode, struct obj_inode *ino)
143{
144        struct bilbyfs_inode *binode = inode_to_binode(inode);
145
146        inode->i_flags |= (S_NOCMTIME | S_NOATIME);
147        set_nlink(inode, le32_to_cpu(ino->nlink));
148        i_uid_write(inode, le32_to_cpu(ino->uid));
149        i_gid_write(inode, le32_to_cpu(ino->gid));
150        inode->i_atime.tv_sec = (int64_t)le64_to_cpu(ino->atime_sec);
151        inode->i_mtime.tv_sec = (int64_t)le64_to_cpu(ino->mtime_sec);
152        inode->i_ctime.tv_sec = (int64_t)le64_to_cpu(ino->ctime_sec);
153        inode->i_mode = le32_to_cpu(ino->mode);
154        inode->i_size = le64_to_cpu(ino->size);
155
156        binode->flags       = le32_to_cpu(ino->flags);
157        binode->creat_sqnum = le64_to_cpu(ino->creat_sqnum);
158}
159
160void pack_obj_super(struct obj_super *super, const struct bilbyfs_super *bsuper)
161{
162        super->ch.type = BILBYFS_SUP_OBJ;
163        super->ch.len = len_to_le32(BILBYFS_SUPER_SZ);
164
165        super->flags = cpu_to_le32(bsuper->flags);
166        super->leb_cnt = cpu_to_le32(bsuper->leb_cnt);
167        super->nb_reserved_del = cpu_to_le32(bsuper->nb_reserved_del);
168        super->nb_reserved_gc = cpu_to_le32(bsuper->nb_reserved_gc);
169        super->leb_size = cpu_to_le32(bsuper->leb_size);
170        super->log_head_leb = cpu_to_le32(bsuper->log_lnum);
171        super->log_head_offs = cpu_to_le32(bsuper->log_offs);
172        super->lowest_sqnum = cpu_to_le64(bsuper->lowest_sqnum);
173        zero_obj_super_unused(super);
174}
175
176void unpack_obj_super(struct bilbyfs_super *bsuper, struct obj_super *super)
177{
178        bsuper->sqnum = le64_to_cpu(super->ch.sqnum);
179        bsuper->flags = le32_to_cpu(super->flags);
180        bsuper->leb_cnt = le32_to_cpu(super->leb_cnt);
181        bsuper->nb_reserved_del = le32_to_cpu(super->nb_reserved_del);
182        bsuper->nb_reserved_gc = le32_to_cpu(super->nb_reserved_gc);
183        bsuper->leb_size = le32_to_cpu(super->leb_size);
184        bsuper->log_lnum = le32_to_cpu(super->log_head_leb);
185        bsuper->log_offs = le32_to_cpu(super->log_head_offs);
186        bsuper->lowest_sqnum = le64_to_cpu(super->lowest_sqnum);
187        bsuper->last_inum = le64_to_cpu(super->last_inum);
188}
189
190void pack_obj_del(void *obj, obj_id id)
191{
192        struct obj_del *del = (struct obj_del *) obj;
193
194        del->ch.type = BILBYFS_DEL_OBJ;
195        del->ch.len = len_to_le32(BILBYFS_DEL_SZ);
196
197        del->id = cpu_to_le64(id);
198
199        zero_obj_del_unused(del);
200}
201
202void pack_obj_sum(struct obj_sum *sum, u32 offs)
203{
204        u32 len = obj_sum_size(sum);
205
206        sum->ch.type = BILBYFS_SUM_OBJ;
207        sum->ch.len = len_to_le32(len);
208        memset((void *)sum + len, BILBYFS_PAD_BYTE, le32_to_cpu(sum->ch.len) - len);
209        *obj_sum_offs(sum) = cpu_to_le32(offs);
210
211        zero_obj_sum_unused(sum);
212}
213