/*
 * wnix, a Unix-like operating system for WebAssembly applications.
 * Copyright (C) 2025  Xavier Del Campo Romero
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

#ifndef ISO9660_TYPES_H
#define ISO9660_TYPES_H

#include <fs/fs.h>
#include <fs/inode.h>
#include <stdint.h>

#define ISO9660_LE ((const union {int a; char c;}){.a = 1}.c)

struct fs_mp_prv
{
    int dummy;
};

enum
{
    ISO9660_TYPE_BOOT_RECORD,
    ISO9660_TYPE_PRIMARY_VD,
    ISO9660_TYPE_SUPPLEMENTARY_VD,
    ISO9660_TYPE_VOLUME_PARTITION,
    ISO9660_TYPE_TERMINATOR = 0xff,
};

struct inode_prv
{
    long offset;
};

struct iso9660_magic
{
    uint8_t id[sizeof "CD001" - 1];
};

struct iso9660_header
{
    uint8_t type;
    struct iso9660_magic magic;
    uint8_t version;
};

struct iso9660_lmsb16
{
    uint8_t le[sizeof (uint16_t)], be[sizeof (uint16_t)];
};

struct iso9660_lmsb32
{
    uint8_t le[sizeof (uint32_t)], be[sizeof (uint32_t)];
};

struct iso9660_dt
{
    char year[sizeof "9999" - 1],
        month[sizeof "12" - 1],
        day[sizeof "31" - 1],
        hour[sizeof "23" - 1],
        min[sizeof "59" - 1],
        sec[sizeof "59" - 1],
        hsec[sizeof "99" - 1];
    int8_t zone;
};

struct iso9660_lsb32
{
    uint8_t data[sizeof (uint32_t)];
};

struct iso9660_msb32
{
    uint8_t data[sizeof (uint32_t)];
};

struct iso9660_entry_dt
{
    uint8_t year, month, day, hour, min, sec, offset;
};

enum
{
    ISO9660_FLAGS_HIDDEN = 1,
    ISO9660_FLAGS_DIR = 1 << 1,
    ISO9660_FLAGS_ASSOC = 1 << 2,
    ISO9660_FLAGS_HAS_FORMAT = 1 << 3,
    ISO9660_FLAGS_HAS_UID_GID = 1 << 4,
    ISO9660_FLAGS_NOT_FINAL = 1 << 7
};

struct iso9660_entry
{
    uint8_t len, attr;
    struct iso9660_lmsb32 extent_loc, data_len;
    struct iso9660_entry_dt dt;
    uint8_t flags;
    uint8_t funit_sz, interleave_sz;
    struct iso9660_lmsb16 seq_num;
    uint8_t id_len;
};

struct iso9660_pvd
{
    uint8_t :8, sysid[32], vid[32], unused[8];
    struct iso9660_lmsb32 space_size;
    uint8_t unused_2[32];
    struct iso9660_lmsb16 set_size, seq_num, block_size;
    struct iso9660_lmsb32 pathtable_size;
    struct iso9660_lsb32 lpath_loc, optlpath_loc;
    struct iso9660_msb32 mpath_loc, optmpath_loc;
    struct iso9660_entry root_dir;
    uint8_t padding, set_id[128], pub_id[128], dprep_id[128], app_id[128],
        copyright_id[37], abstract_id[37], bibl_id[37];
    struct iso9660_dt creat, mod, exp, eff;
    uint8_t fs_version, :8, reserved[512 + 653];
};


struct iso9660_vd
{
    struct iso9660_header header;

    union
    {
        struct iso9660_pvd pvd;
    } u;
};

enum {ISO9660_SECTOR_SZ = 2048};

extern const struct fs iso9660;

#endif
