summaryrefslogtreecommitdiffstats
path: root/contrib/syslinux-4.02/libfat
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/syslinux-4.02/libfat')
-rw-r--r--contrib/syslinux-4.02/libfat/cache.c65
-rw-r--r--contrib/syslinux-4.02/libfat/fat.h108
-rw-r--r--contrib/syslinux-4.02/libfat/fatchain.c134
-rw-r--r--contrib/syslinux-4.02/libfat/libfat.h85
-rw-r--r--contrib/syslinux-4.02/libfat/libfatint.h55
-rw-r--r--contrib/syslinux-4.02/libfat/open.c117
-rw-r--r--contrib/syslinux-4.02/libfat/searchdir.c64
-rw-r--r--contrib/syslinux-4.02/libfat/ulint.h112
8 files changed, 740 insertions, 0 deletions
diff --git a/contrib/syslinux-4.02/libfat/cache.c b/contrib/syslinux-4.02/libfat/cache.c
new file mode 100644
index 0000000..85b7ead
--- /dev/null
+++ b/contrib/syslinux-4.02/libfat/cache.c
@@ -0,0 +1,65 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * cache.c
+ *
+ * Simple sector cache
+ */
+
+#include <stdlib.h>
+#include "libfatint.h"
+
+void *libfat_get_sector(struct libfat_filesystem *fs, libfat_sector_t n)
+{
+ struct libfat_sector *ls;
+
+ for (ls = fs->sectors; ls; ls = ls->next) {
+ if (ls->n == n)
+ return ls->data; /* Found in cache */
+ }
+
+ /* Not found in cache */
+ ls = malloc(sizeof(struct libfat_sector));
+ if (!ls) {
+ libfat_flush(fs);
+ ls = malloc(sizeof(struct libfat_sector));
+
+ if (!ls)
+ return NULL; /* Can't allocate memory */
+ }
+
+ if (fs->read(fs->readptr, ls->data, LIBFAT_SECTOR_SIZE, n)
+ != LIBFAT_SECTOR_SIZE) {
+ free(ls);
+ return NULL; /* I/O error */
+ }
+
+ ls->n = n;
+ ls->next = fs->sectors;
+ fs->sectors = ls;
+
+ return ls->data;
+}
+
+void libfat_flush(struct libfat_filesystem *fs)
+{
+ struct libfat_sector *ls, *lsnext;
+
+ lsnext = fs->sectors;
+ fs->sectors = NULL;
+
+ for (ls = lsnext; ls; ls = lsnext) {
+ lsnext = ls->next;
+ free(ls);
+ }
+}
diff --git a/contrib/syslinux-4.02/libfat/fat.h b/contrib/syslinux-4.02/libfat/fat.h
new file mode 100644
index 0000000..b4e32f7
--- /dev/null
+++ b/contrib/syslinux-4.02/libfat/fat.h
@@ -0,0 +1,108 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2001-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * fat.h
+ *
+ * Basic data structures for a FAT filesystem
+ */
+
+#ifndef FAT_H
+#define FAT_H
+
+#include "ulint.h"
+
+/* The poor excuse FAT has for a superblock -- in the boot sector */
+struct fat_bootsect {
+ le8_t bsJump[3]; /* Jump to code */
+ char bsOemName[8]; /* Formatting program */
+ le16_t bsBytesPerSec; /* Bytes/sector */
+ le8_t bsSecPerClust; /* Sectors/cluster */
+ le16_t bsResSectors; /* Reserved sectors */
+ le8_t bsFATs; /* Number of FATs */
+ le16_t bsRootDirEnts; /* Number of entries/root directory */
+ le16_t bsSectors; /* Number of sectors [1] */
+ le8_t bsMedia; /* Magic media type byte */
+ le16_t bsFATsecs; /* Sectors/FAT */
+ le16_t bsSecPerTrack; /* Sectors/track */
+ le16_t bsHeads; /* Number of heads */
+ le32_t bsHiddenSecs; /* Number of hidden sectors */
+ le32_t bsHugeSectors; /* Number of sectors [2] */
+ union {
+ /* FAT12/16 */
+ struct {
+ le8_t bsDriveNumber; /* Drive number */
+ le8_t bsReserved1; /* Reserved */
+ le8_t bsBootSignature; /* 0x29 */
+ le32_t bsVolumeID; /* Volume serial number */
+ char bsVolumeLabel[11]; /* Volume name */
+ char bsFileSysType[8]; /* File system type */
+
+ le8_t bsCode[448]; /* Boot sector code */
+ } fat16;
+
+ /* FAT32 */
+ struct {
+ le32_t bpb_fatsz32; /* Sectors/FAT */
+ le16_t bpb_extflags; /* Extended flags */
+ le16_t bpb_fsver; /* Filesystem version */
+ le32_t bpb_rootclus; /* Root directory cluster */
+ le16_t bpb_fsinfo; /* FSINFO sector number */
+ le16_t bpb_bkbootsec; /* Backup boot sector (superblock) */
+ char bpb_reserved[12];
+
+ /* Same shit, different offset! */
+ le8_t bsDriveNumber; /* Drive number */
+ le8_t bsReserved1; /* Reserved */
+ le8_t bsBootSignature; /* 0x29 */
+ le32_t bsVolumeID; /* Volume serial number */
+ char bsVolumeLabel[11]; /* Volume name */
+ char bsFileSysType[8]; /* File system type */
+
+ le8_t bsCode[420]; /* Boot sector code */
+ } fat32;
+ } u;
+
+ le16_t bsSignature; /* 0xAA55 */
+};
+
+#define BS_BOOTSIGNATURE 0x29
+#define BS_SIGNATURE 0xAA55
+
+/* A FAT filesystem directory entry */
+
+struct fat_dirent {
+ le8_t name[11]; /* Mangled filename */
+ le8_t attribute; /* File type/attribute */
+ le8_t caseflags; /* VFAT: case for basis and extension */
+ le8_t ctime_ms; /* ms of creation time */
+ le32_t ctime; /* Creation time */
+ le16_t atime; /* Date portion (high 16 bits) of atime */
+ le16_t clusthi; /* FAT32: high 16 bits of cluster */
+ le32_t mtime; /* Modification time */
+ le16_t clustlo; /* First cluster pointer */
+ le32_t size; /* File size (bytes) */
+};
+
+/* A VFAT filesystem continuation entry */
+struct fat_vfat_slot {
+ le8_t id; /* Sequence number for slot */
+ le16_t name0[5]; /* 5 characters */
+ le8_t attribute; /* Attribute byte */
+ le8_t reserved; /* Reserved, MBZ */
+ le8_t alias_csum; /* Short name checksum */
+ le16_t name5[6]; /* 6 characters */
+ le16_t firstclust; /* MBZ */
+ le16_t name11[2]; /* 2 characters */
+};
+
+#endif /* FAT_H */
diff --git a/contrib/syslinux-4.02/libfat/fatchain.c b/contrib/syslinux-4.02/libfat/fatchain.c
new file mode 100644
index 0000000..9853a72
--- /dev/null
+++ b/contrib/syslinux-4.02/libfat/fatchain.c
@@ -0,0 +1,134 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * fatchain.c
+ *
+ * Follow a FAT chain
+ */
+
+#include "libfatint.h"
+#include "ulint.h"
+
+/*
+ * Convert a cluster number (or 0 for the root directory) to a
+ * sector number. Return -1 on failure.
+ */
+libfat_sector_t libfat_clustertosector(const struct libfat_filesystem *fs,
+ int32_t cluster)
+{
+ if (cluster == 0)
+ cluster = fs->rootcluster;
+
+ if (cluster == 0)
+ return fs->rootdir;
+ else if (cluster < 2 || cluster >= fs->endcluster)
+ return -1;
+ else
+ return fs->data + ((libfat_sector_t) (cluster - 2) << fs->clustshift);
+}
+
+/*
+ * Get the next sector of either the root directory or a FAT chain.
+ * Returns 0 on end of file and -1 on error.
+ */
+
+libfat_sector_t libfat_nextsector(struct libfat_filesystem * fs,
+ libfat_sector_t s)
+{
+ int32_t cluster, nextcluster;
+ uint32_t fatoffset;
+ libfat_sector_t fatsect;
+ uint8_t *fsdata;
+ uint32_t clustmask = fs->clustsize - 1;
+ libfat_sector_t rs;
+
+ if (s < fs->data) {
+ if (s < fs->rootdir)
+ return -1;
+
+ /* Root directory */
+ s++;
+ return (s < fs->data) ? s : 0;
+ }
+
+ rs = s - fs->data;
+
+ if (~rs & clustmask)
+ return s + 1; /* Next sector in cluster */
+
+ cluster = 2 + (rs >> fs->clustshift);
+
+ if (cluster >= fs->endcluster)
+ return -1;
+
+ switch (fs->fat_type) {
+ case FAT12:
+ /* Get first byte */
+ fatoffset = cluster + (cluster >> 1);
+ fatsect = fs->fat + (fatoffset >> LIBFAT_SECTOR_SHIFT);
+ fsdata = libfat_get_sector(fs, fatsect);
+ if (!fsdata)
+ return -1;
+ nextcluster = fsdata[fatoffset & LIBFAT_SECTOR_MASK];
+
+ /* Get second byte */
+ fatoffset++;
+ fatsect = fs->fat + (fatoffset >> LIBFAT_SECTOR_SHIFT);
+ fsdata = libfat_get_sector(fs, fatsect);
+ if (!fsdata)
+ return -1;
+ nextcluster |= fsdata[fatoffset & LIBFAT_SECTOR_MASK] << 8;
+
+ /* Extract the FAT entry */
+ if (cluster & 1)
+ nextcluster >>= 4;
+ else
+ nextcluster &= 0x0FFF;
+
+ if (nextcluster >= 0x0FF8)
+ return 0;
+ break;
+
+ case FAT16:
+ fatoffset = cluster << 1;
+ fatsect = fs->fat + (fatoffset >> LIBFAT_SECTOR_SHIFT);
+ fsdata = libfat_get_sector(fs, fatsect);
+ if (!fsdata)
+ return -1;
+ nextcluster =
+ read16((le16_t *) & fsdata[fatoffset & LIBFAT_SECTOR_MASK]);
+
+ if (nextcluster >= 0x0FFF8)
+ return 0;
+ break;
+
+ case FAT28:
+ fatoffset = cluster << 2;
+ fatsect = fs->fat + (fatoffset >> LIBFAT_SECTOR_SHIFT);
+ fsdata = libfat_get_sector(fs, fatsect);
+ if (!fsdata)
+ return -1;
+ nextcluster =
+ read32((le32_t *) & fsdata[fatoffset & LIBFAT_SECTOR_MASK]);
+ nextcluster &= 0x0FFFFFFF;
+
+ if (nextcluster >= 0x0FFFFFF8)
+ return 0;
+ break;
+
+ default:
+ return -1; /* WTF? */
+ }
+
+ return libfat_clustertosector(fs, nextcluster);
+}
diff --git a/contrib/syslinux-4.02/libfat/libfat.h b/contrib/syslinux-4.02/libfat/libfat.h
new file mode 100644
index 0000000..a0179d7
--- /dev/null
+++ b/contrib/syslinux-4.02/libfat/libfat.h
@@ -0,0 +1,85 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * libfat.h
+ *
+ * Headers for the libfat library
+ */
+
+#ifndef LIBFAT_H
+#define LIBFAT_H
+
+#include <stddef.h>
+#include <inttypes.h>
+
+#define LIBFAT_SECTOR_SHIFT 9
+#define LIBFAT_SECTOR_SIZE 512
+#define LIBFAT_SECTOR_MASK 511
+
+typedef uint64_t libfat_sector_t;
+struct libfat_filesystem;
+
+struct libfat_direntry {
+ libfat_sector_t sector;
+ int offset;
+ unsigned char entry[32];
+};
+
+/*
+ * Open the filesystem. The readfunc is the function to read
+ * sectors, in the format:
+ * int readfunc(intptr_t readptr, void *buf, size_t secsize,
+ * libfat_sector_t secno)
+ *
+ * ... where readptr is a private argument.
+ *
+ * A return value of != secsize is treated as error.
+ */
+struct libfat_filesystem
+ *libfat_open(int (*readfunc) (intptr_t, void *, size_t, libfat_sector_t),
+ intptr_t readptr);
+
+void libfat_close(struct libfat_filesystem *);
+
+/*
+ * Convert a cluster number (or 0 for the root directory) to a
+ * sector number. Return -1 on failure.
+ */
+libfat_sector_t libfat_clustertosector(const struct libfat_filesystem *fs,
+ int32_t cluster);
+
+/*
+ * Get the next sector of either the root directory or a FAT chain.
+ * Returns 0 on end of file and -1 on error.
+ */
+libfat_sector_t libfat_nextsector(struct libfat_filesystem *fs,
+ libfat_sector_t s);
+
+/*
+ * Flush all cached sectors for this filesystem.
+ */
+void libfat_flush(struct libfat_filesystem *fs);
+
+/*
+ * Get a pointer to a specific sector.
+ */
+void *libfat_get_sector(struct libfat_filesystem *fs, libfat_sector_t n);
+
+/*
+ * Search a FAT directory for a particular pre-mangled filename.
+ * Copies the directory entry into direntry and returns 0 if found.
+ */
+int32_t libfat_searchdir(struct libfat_filesystem *fs, int32_t dirclust,
+ const void *name, struct libfat_direntry *direntry);
+
+#endif /* LIBFAT_H */
diff --git a/contrib/syslinux-4.02/libfat/libfatint.h b/contrib/syslinux-4.02/libfat/libfatint.h
new file mode 100644
index 0000000..adfad00
--- /dev/null
+++ b/contrib/syslinux-4.02/libfat/libfatint.h
@@ -0,0 +1,55 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * libfatint.h
+ *
+ * Internals for the libfat filesystem
+ */
+
+#ifndef LIBFATINT_H
+#define LIBFATINT_H
+
+#include "libfat.h"
+#include "fat.h"
+
+struct libfat_sector {
+ libfat_sector_t n; /* Sector number */
+ struct libfat_sector *next; /* Next in list */
+ char data[LIBFAT_SECTOR_SIZE];
+};
+
+enum fat_type {
+ FAT12,
+ FAT16,
+ FAT28
+};
+
+struct libfat_filesystem {
+ int (*read) (intptr_t, void *, size_t, libfat_sector_t);
+ intptr_t readptr;
+
+ enum fat_type fat_type;
+ unsigned int clustsize;
+ int clustshift;
+ int32_t endcluster; /* Highest legal cluster number + 1 */
+ int32_t rootcluster; /* Root directory cluster */
+
+ libfat_sector_t fat; /* Start of FAT */
+ libfat_sector_t rootdir; /* Start of root directory */
+ libfat_sector_t data; /* Start of data area */
+ libfat_sector_t end; /* End of filesystem */
+
+ struct libfat_sector *sectors;
+};
+
+#endif /* LIBFATINT_H */
diff --git a/contrib/syslinux-4.02/libfat/open.c b/contrib/syslinux-4.02/libfat/open.c
new file mode 100644
index 0000000..7281e03
--- /dev/null
+++ b/contrib/syslinux-4.02/libfat/open.c
@@ -0,0 +1,117 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * open.c
+ *
+ * Open a FAT filesystem and compute some initial values; return NULL
+ * on failure.
+ */
+
+#include <stdlib.h>
+#include "libfatint.h"
+#include "ulint.h"
+
+struct libfat_filesystem *
+libfat_open(int (*readfunc) (intptr_t, void *, size_t, libfat_sector_t),
+ intptr_t readptr)
+{
+ struct libfat_filesystem *fs = NULL;
+ struct fat_bootsect *bs;
+ int i;
+ uint32_t sectors, fatsize, minfatsize, rootdirsize;
+ uint32_t nclusters;
+
+ fs = malloc(sizeof(struct libfat_filesystem));
+ if (!fs)
+ goto barf;
+
+ fs->sectors = NULL;
+ fs->read = readfunc;
+ fs->readptr = readptr;
+
+ bs = libfat_get_sector(fs, 0);
+ if (!bs)
+ goto barf;
+
+ if (read16(&bs->bsBytesPerSec) != LIBFAT_SECTOR_SIZE)
+ goto barf;
+
+ for (i = 0; i <= 8; i++) {
+ if ((uint8_t) (1 << i) == read8(&bs->bsSecPerClust))
+ break;
+ }
+ if (i > 8)
+ goto barf;
+ fs->clustsize = 1 << i; /* Treat 0 as 2^8 = 64K */
+ fs->clustshift = i;
+
+ sectors = read16(&bs->bsSectors);
+ if (!sectors)
+ sectors = read32(&bs->bsHugeSectors);
+
+ fs->end = sectors;
+
+ fs->fat = read16(&bs->bsResSectors);
+ fatsize = read16(&bs->bsFATsecs);
+ if (!fatsize)
+ fatsize = read32(&bs->u.fat32.bpb_fatsz32);
+
+ fs->rootdir = fs->fat + fatsize * read8(&bs->bsFATs);
+
+ rootdirsize = ((read16(&bs->bsRootDirEnts) << 5) + LIBFAT_SECTOR_MASK)
+ >> LIBFAT_SECTOR_SHIFT;
+ fs->data = fs->rootdir + rootdirsize;
+
+ /* Sanity checking */
+ if (fs->data >= fs->end)
+ goto barf;
+
+ /* Figure out how many clusters */
+ nclusters = (fs->end - fs->data) >> fs->clustshift;
+ fs->endcluster = nclusters + 2;
+
+ if (nclusters <= 0xff4) {
+ fs->fat_type = FAT12;
+ minfatsize = fs->endcluster + (fs->endcluster >> 1);
+ } else if (nclusters <= 0xfff4) {
+ fs->fat_type = FAT16;
+ minfatsize = fs->endcluster << 1;
+ } else if (nclusters <= 0xffffff4) {
+ fs->fat_type = FAT28;
+ minfatsize = fs->endcluster << 2;
+ } else
+ goto barf; /* Impossibly many clusters */
+
+ minfatsize = (minfatsize + LIBFAT_SECTOR_SIZE - 1) >> LIBFAT_SECTOR_SHIFT;
+
+ if (minfatsize > fatsize)
+ goto barf; /* The FATs don't fit */
+
+ if (fs->fat_type == FAT28)
+ fs->rootcluster = read32(&bs->u.fat32.bpb_rootclus);
+ else
+ fs->rootcluster = 0;
+
+ return fs; /* All good */
+
+barf:
+ if (fs)
+ free(fs);
+ return NULL;
+}
+
+void libfat_close(struct libfat_filesystem *fs)
+{
+ libfat_flush(fs);
+ free(fs);
+}
diff --git a/contrib/syslinux-4.02/libfat/searchdir.c b/contrib/syslinux-4.02/libfat/searchdir.c
new file mode 100644
index 0000000..4964120
--- /dev/null
+++ b/contrib/syslinux-4.02/libfat/searchdir.c
@@ -0,0 +1,64 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * searchdir.c
+ *
+ * Search a FAT directory for a particular pre-mangled filename.
+ * Copies the directory entry into direntry and returns the starting cluster
+ * if found; returns -2 on not found, -1 on error, 0 on empty file.
+ */
+
+#include <string.h>
+#include "libfatint.h"
+
+int32_t libfat_searchdir(struct libfat_filesystem *fs, int32_t dirclust,
+ const void *name, struct libfat_direntry *direntry)
+{
+ struct fat_dirent *dep;
+ int nent;
+ libfat_sector_t s = libfat_clustertosector(fs, dirclust);
+
+ while (1) {
+ if (s == 0)
+ return -2; /* Not found */
+ else if (s == (libfat_sector_t) - 1)
+ return -1; /* Error */
+
+ dep = libfat_get_sector(fs, s);
+ if (!dep)
+ return -1; /* Read error */
+
+ for (nent = 0; nent < LIBFAT_SECTOR_SIZE;
+ nent += sizeof(struct fat_dirent)) {
+ if (!memcmp(dep->name, name, 11)) {
+ if (direntry) {
+ memcpy(direntry->entry, dep, sizeof(*dep));
+ direntry->sector = s;
+ direntry->offset = nent;
+ }
+ if (read32(&dep->size) == 0)
+ return 0; /* An empty file has no clusters */
+ else
+ return read16(&dep->clustlo) +
+ (read16(&dep->clusthi) << 16);
+ }
+
+ if (dep->name[0] == 0)
+ return -2; /* Hit high water mark */
+
+ dep++;
+ }
+
+ s = libfat_nextsector(fs, s);
+ }
+}
diff --git a/contrib/syslinux-4.02/libfat/ulint.h b/contrib/syslinux-4.02/libfat/ulint.h
new file mode 100644
index 0000000..c2fadb7
--- /dev/null
+++ b/contrib/syslinux-4.02/libfat/ulint.h
@@ -0,0 +1,112 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2001-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ * USA; either version 2 of the License, or (at your option) any later
+ * version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * ulint.h
+ *
+ * Basic operations on unaligned, littleendian integers
+ */
+
+#ifndef ULINT_H
+#define ULINT_H
+
+#include <inttypes.h>
+
+/* These are unaligned, littleendian integer types */
+
+typedef uint8_t le8_t; /* 8-bit byte */
+typedef uint8_t le16_t[2]; /* 16-bit word */
+typedef uint8_t le32_t[4]; /* 32-bit dword */
+
+/* Read/write these quantities */
+
+static inline unsigned char read8(le8_t * _p)
+{
+ return *_p;
+}
+
+static inline void write8(le8_t * _p, uint8_t _v)
+{
+ *_p = _v;
+}
+
+#if defined(__i386__) || defined(__x86_64__)
+
+/* Littleendian architectures which support unaligned memory accesses */
+
+static inline unsigned short read16(le16_t * _p)
+{
+ return *((const uint16_t *)_p);
+}
+
+static inline void write16(le16_t * _p, unsigned short _v)
+{
+ *((uint16_t *) _p) = _v;
+}
+
+static inline unsigned int read32(le32_t * _p)
+{
+ return *((const uint32_t *)_p);
+}
+
+static inline void write32(le32_t * _p, uint32_t _v)
+{
+ *((uint32_t *) _p) = _v;
+}
+
+#else
+
+/* Generic, mostly portable versions */
+
+static inline unsigned short read16(le16_t * _pp)
+{
+ uint8_t *_p = *_pp;
+ uint16_t _v;
+
+ _v = _p[0];
+ _v |= _p[1] << 8;
+ return _v;
+}
+
+static inline void write16(le16_t * _pp, uint16_t _v)
+{
+ uint8_t *_p = *_pp;
+
+ _p[0] = _v & 0xFF;
+ _p[1] = (_v >> 8) & 0xFF;
+}
+
+static inline unsigned int read32(le32_t * _pp)
+{
+ uint8_t *_p = *_pp;
+ uint32_t _v;
+
+ _v = _p[0];
+ _v |= _p[1] << 8;
+ _v |= _p[2] << 16;
+ _v |= _p[3] << 24;
+ return _v;
+}
+
+static inline void write32(le32_t * _pp, uint32_t _v)
+{
+ uint8_t *_p = *_pp;
+
+ _p[0] = _v & 0xFF;
+ _p[1] = (_v >> 8) & 0xFF;
+ _p[2] = (_v >> 16) & 0xFF;
+ _p[3] = (_v >> 24) & 0xFF;
+}
+
+#endif
+
+#endif /* ULINT_H */