pmt: initial 3.0.2 update
This commit is contained in:
80
jni/parted/libparted/fs/jfs/jfs.c
Executable file
80
jni/parted/libparted/fs/jfs/jfs.c
Executable file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
libparted - a library for manipulating disk partitions
|
||||
Copyright (C) 2001, 2007, 2009-2014, 2019-2023 Free Software Foundation,
|
||||
Inc.
|
||||
|
||||
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; 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <parted/parted.h>
|
||||
#include <parted/endian.h>
|
||||
|
||||
#define _JFS_UTILITY
|
||||
#include "jfs_types.h"
|
||||
#include "jfs_superblock.h"
|
||||
|
||||
#define JFS_SUPER_OFFSET 32768
|
||||
|
||||
#if ENABLE_NLS
|
||||
# include <libintl.h>
|
||||
# define _(String) dgettext (PACKAGE, String)
|
||||
#else
|
||||
# define _(String) (String)
|
||||
#endif /* ENABLE_NLS */
|
||||
|
||||
static PedGeometry*
|
||||
jfs_probe (PedGeometry* geom)
|
||||
{
|
||||
struct superblock *sb = alloca (geom->dev->sector_size);
|
||||
|
||||
if (geom->length * geom->dev->sector_size < JFS_SUPER_OFFSET)
|
||||
return NULL;
|
||||
if (!ped_geometry_read (geom, sb, JFS_SUPER_OFFSET / geom->dev->sector_size, 1))
|
||||
return NULL;
|
||||
|
||||
if (strncmp (sb->s_magic, JFS_MAGIC, 4) == 0) {
|
||||
PedSector block_size = PED_LE32_TO_CPU (sb->s_pbsize);
|
||||
PedSector block_count = PED_LE64_TO_CPU (sb->s_size);
|
||||
/* apparently jfs is retarded and always claims 512 byte
|
||||
sectors, with the block count as a multiple of that */
|
||||
return ped_geometry_new (geom->dev, geom->start,
|
||||
block_size * block_count / geom->dev->sector_size);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static PedFileSystemOps jfs_ops = {
|
||||
probe: jfs_probe,
|
||||
};
|
||||
|
||||
static PedFileSystemType jfs_type = {
|
||||
next: NULL,
|
||||
ops: &jfs_ops,
|
||||
name: "jfs",
|
||||
};
|
||||
|
||||
void
|
||||
ped_file_system_jfs_init ()
|
||||
{
|
||||
ped_file_system_type_register (&jfs_type);
|
||||
}
|
||||
|
||||
void
|
||||
ped_file_system_jfs_done ()
|
||||
{
|
||||
ped_file_system_type_unregister (&jfs_type);
|
||||
}
|
||||
144
jni/parted/libparted/fs/jfs/jfs_superblock.h
Executable file
144
jni/parted/libparted/fs/jfs/jfs_superblock.h
Executable file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) International Business Machines Corp., 2000
|
||||
*
|
||||
* 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; 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef _H_JFS_SUPERBLOCK
|
||||
#define _H_JFS_SUPERBLOCK
|
||||
/*
|
||||
* jfs_superblock.h
|
||||
*/
|
||||
|
||||
/*
|
||||
* make the magic number something a human could read
|
||||
*/
|
||||
#define JFS_MAGIC "JFS1" /* Magic word: Version 1 */
|
||||
|
||||
#define JFS_VERSION 1 /* Version number: Version 1 */
|
||||
|
||||
#define LV_NAME_SIZE 11 /* MUST BE 11 for OS/2 boot sector */
|
||||
|
||||
/*
|
||||
* aggregate superblock
|
||||
*
|
||||
* The name superblock is too close to super_block, so the name has been
|
||||
* changed to jfs_superblock. The utilities are still using the old name.
|
||||
*/
|
||||
#ifdef _JFS_UTILITY
|
||||
struct superblock
|
||||
#else
|
||||
struct jfs_superblock
|
||||
#endif
|
||||
{
|
||||
char s_magic[4]; /* 4: magic number */
|
||||
u32 s_version; /* 4: version number */
|
||||
|
||||
s64 s_size; /* 8: aggregate size in hardware/LVM blocks;
|
||||
* VFS: number of blocks
|
||||
*/
|
||||
s32 s_bsize; /* 4: aggregate block size in bytes;
|
||||
* VFS: fragment size
|
||||
*/
|
||||
s16 s_l2bsize; /* 2: log2 of s_bsize */
|
||||
s16 s_l2bfactor; /* 2: log2(s_bsize/hardware block size) */
|
||||
s32 s_pbsize; /* 4: hardware/LVM block size in bytes */
|
||||
s16 s_l2pbsize; /* 2: log2 of s_pbsize */
|
||||
s16 pad; /* 2: padding necessary for alignment */
|
||||
|
||||
u32 s_agsize; /* 4: allocation group size in aggr. blocks */
|
||||
|
||||
u32 s_flag; /* 4: aggregate attributes:
|
||||
* see jfs_filsys.h
|
||||
*/
|
||||
u32 s_state; /* 4: mount/unmount/recovery state:
|
||||
* see jfs_filsys.h
|
||||
*/
|
||||
s32 s_compress; /* 4: > 0 if data compression */
|
||||
|
||||
pxd_t s_ait2; /* 8: first extent of secondary
|
||||
* aggregate inode table
|
||||
*/
|
||||
|
||||
pxd_t s_aim2; /* 8: first extent of secondary
|
||||
* aggregate inode map
|
||||
*/
|
||||
u32 s_logdev; /* 4: device address of log */
|
||||
s32 s_logserial; /* 4: log serial number at aggregate mount */
|
||||
pxd_t s_logpxd; /* 8: inline log extent */
|
||||
|
||||
pxd_t s_fsckpxd; /* 8: inline fsck work space extent */
|
||||
|
||||
struct timestruc_t s_time; /* 8: time last updated */
|
||||
|
||||
s32 s_fsckloglen; /* 4: Number of file system blocks reserved for
|
||||
* the fsck service log.
|
||||
* N.B. These blocks are divided among the
|
||||
* versions kept. This is not a per
|
||||
* version size.
|
||||
* N.B. These blocks are included in the
|
||||
* length field of s_fsckpxd.
|
||||
*/
|
||||
s8 s_fscklog; /* 1: which fsck service log is most recent
|
||||
* 0 => no service log data yet
|
||||
* 1 => the first one
|
||||
* 2 => the 2nd one
|
||||
*/
|
||||
char s_fpack[11]; /* 11: file system volume name
|
||||
* N.B. This must be 11 bytes to
|
||||
* conform with the OS/2 BootSector
|
||||
* requirements
|
||||
*/
|
||||
|
||||
/* extendfs() parameter under s_state & FM_EXTENDFS */
|
||||
s64 s_xsize; /* 8: extendfs s_size */
|
||||
pxd_t s_xfsckpxd; /* 8: extendfs fsckpxd */
|
||||
pxd_t s_xlogpxd; /* 8: extendfs logpxd */
|
||||
/* - 128 byte boundary - */
|
||||
|
||||
/*
|
||||
* DFS VFS support (preliminary)
|
||||
*/
|
||||
char s_attach; /* 1: VFS: flag: set when aggregate is attached
|
||||
*/
|
||||
u8 rsrvd4[7]; /* 7: reserved - set to 0 */
|
||||
|
||||
u64 totalUsable; /* 8: VFS: total of 1K blocks which are
|
||||
* available to "normal" (non-root) users.
|
||||
*/
|
||||
u64 minFree; /* 8: VFS: # of 1K blocks held in reserve for
|
||||
* exclusive use of root. This value can be 0,
|
||||
* and if it is then totalUsable will be equal
|
||||
* to # of blocks in aggregate. I believe this
|
||||
* means that minFree + totalUsable = # blocks.
|
||||
* In that case, we don't need to store both
|
||||
* totalUsable and minFree since we can compute
|
||||
* one from the other. I would guess minFree
|
||||
* would be the one we should store, and
|
||||
* totalUsable would be the one we should
|
||||
* compute. (Just a guess...)
|
||||
*/
|
||||
|
||||
u64 realFree; /* 8: VFS: # of free 1K blocks can be used by
|
||||
* "normal" users. It may be this is something
|
||||
* we should compute when asked for instead of
|
||||
* storing in the superblock. I don't know how
|
||||
* often this information is needed.
|
||||
*/
|
||||
/*
|
||||
* graffiti area
|
||||
*/
|
||||
};
|
||||
|
||||
#endif /*_H_JFS_SUPERBLOCK */
|
||||
527
jni/parted/libparted/fs/jfs/jfs_types.h
Executable file
527
jni/parted/libparted/fs/jfs/jfs_types.h
Executable file
@@ -0,0 +1,527 @@
|
||||
/*
|
||||
* Copyright (c) International Business Machines Corp., 2000
|
||||
*
|
||||
* 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; 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _H_JFS_TYPES
|
||||
#define _H_JFS_TYPES
|
||||
|
||||
/*
|
||||
* jfs_types.h:
|
||||
*
|
||||
* basic type/utility definitions
|
||||
*
|
||||
* note: this header file must be the 1st include file
|
||||
* of JFS include list in all JFS .c file.
|
||||
*/
|
||||
|
||||
#ifdef _JFS_UTILITY
|
||||
/* this is defined in asm/byteorder.h for i386, but
|
||||
* is NOT defined in asm/byteorder.h for ppc (non-kernel).
|
||||
* Until that is changed, we'll define it here. */
|
||||
#define __BYTEORDER_HAS_U64__
|
||||
|
||||
#include <sys/types.h>
|
||||
//#include <asm/byteorder.h>
|
||||
typedef unsigned short UniChar;
|
||||
#else
|
||||
#include <linux/types.h>
|
||||
#include <linux/jfs_fs.h>
|
||||
#include <linux/nls.h>
|
||||
|
||||
#ifndef _ULS_UNICHAR_DEFINED
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0))
|
||||
typedef wchar_t UniChar;
|
||||
#else
|
||||
typedef unsigned short UniChar;
|
||||
#endif
|
||||
#define _ULS_UNICHAR_DEFINED
|
||||
#endif
|
||||
#endif
|
||||
/* #include "endian24.h" */
|
||||
|
||||
/*
|
||||
* primitive types
|
||||
*/
|
||||
#ifdef _JFS_UTILITY
|
||||
typedef int8_t s8;
|
||||
typedef uint8_t u8;
|
||||
typedef int16_t s16;
|
||||
typedef uint16_t u16;
|
||||
typedef int32_t s32;
|
||||
typedef uint32_t u32;
|
||||
typedef int64_t s64;
|
||||
typedef uint64_t u64;
|
||||
|
||||
#ifndef _UINT_TYPES
|
||||
/* unicode includes also define these */
|
||||
typedef u16 uint16;
|
||||
typedef u32 uint32;
|
||||
#define _UINT_TYPES
|
||||
#endif
|
||||
|
||||
typedef s8 int8;
|
||||
typedef u8 uint8;
|
||||
typedef s16 int16;
|
||||
typedef s32 int32;
|
||||
typedef s64 int64;
|
||||
typedef u64 uint64;
|
||||
|
||||
#endif /* _JFS_UTILITY */
|
||||
/*
|
||||
* Holdovers from OS/2. Try to get away from using these altogether.
|
||||
*/
|
||||
typedef unsigned long ULONG;
|
||||
typedef unsigned short USHORT;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef void *PVOID;
|
||||
#define MAXPATHLEN 255
|
||||
|
||||
|
||||
/*
|
||||
* Almost identical to Linux's timespec, but not quite
|
||||
*/
|
||||
struct timestruc_t {
|
||||
u32 tv_sec;
|
||||
u32 tv_nsec;
|
||||
};
|
||||
|
||||
/*
|
||||
* handy
|
||||
*/
|
||||
#undef MIN
|
||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
#undef MAX
|
||||
#define MAX(a,b) (((a)>(b))?(a):(b))
|
||||
#undef ROUNDUP
|
||||
#define ROUNDUP(x, y) ( ((x) + ((y) - 1)) & ~((y) - 1) )
|
||||
|
||||
#define LEFTMOSTONE 0x80000000
|
||||
#define HIGHORDER 0x80000000u /* high order bit on */
|
||||
#define ONES 0xffffffffu /* all bit on */
|
||||
|
||||
typedef int boolean_t;
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
/*
|
||||
* logical xd (lxd)
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned len:24;
|
||||
unsigned off1:8;
|
||||
u32 off2;
|
||||
} lxd_t;
|
||||
|
||||
/* lxd_t field construction */
|
||||
#define LXDlength(lxd, length32) ( (lxd)->len = length32 )
|
||||
#define LXDoffset(lxd, offset64)\
|
||||
{\
|
||||
(lxd)->off1 = ((s64)offset64) >> 32;\
|
||||
(lxd)->off2 = (offset64) & 0xffffffff;\
|
||||
}
|
||||
|
||||
/* lxd_t field extraction */
|
||||
#define lengthLXD(lxd) ( (lxd)->len )
|
||||
#define offsetLXD(lxd)\
|
||||
( ((s64)((lxd)->off1)) << 32 | (lxd)->off2 )
|
||||
|
||||
/* lxd list */
|
||||
typedef struct {
|
||||
s16 maxnlxd;
|
||||
s16 nlxd;
|
||||
lxd_t *lxd;
|
||||
} lxdlist_t;
|
||||
|
||||
/*
|
||||
* physical xd (pxd)
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned len:24;
|
||||
unsigned addr1:8;
|
||||
u32 addr2;
|
||||
} pxd_t;
|
||||
|
||||
/* xd_t field construction */
|
||||
|
||||
#define PXDlength(pxd, length32) ((pxd)->len = __cpu_to_le24(length32))
|
||||
#define PXDaddress(pxd, address64)\
|
||||
{\
|
||||
(pxd)->addr1 = ((s64)address64) >> 32;\
|
||||
(pxd)->addr2 = __cpu_to_le32((address64) & 0xffffffff);\
|
||||
}
|
||||
|
||||
/* xd_t field extraction */
|
||||
#define lengthPXD(pxd) __le24_to_cpu((pxd)->len)
|
||||
#define addressPXD(pxd)\
|
||||
( ((s64)((pxd)->addr1)) << 32 | __le32_to_cpu((pxd)->addr2))
|
||||
|
||||
/* pxd list */
|
||||
typedef struct {
|
||||
s16 maxnpxd;
|
||||
s16 npxd;
|
||||
pxd_t pxd[8];
|
||||
} pxdlist_t;
|
||||
|
||||
|
||||
/*
|
||||
* data extent descriptor (dxd)
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned flag:8; /* 1: flags */
|
||||
unsigned rsrvd:24; /* 3: */
|
||||
u32 size; /* 4: size in byte */
|
||||
unsigned len:24; /* 3: length in unit of fsblksize */
|
||||
unsigned addr1:8; /* 1: address in unit of fsblksize */
|
||||
u32 addr2; /* 4: address in unit of fsblksize */
|
||||
} dxd_t; /* - 16 - */
|
||||
|
||||
/* dxd_t flags */
|
||||
#define DXD_INDEX 0x80 /* B+-tree index */
|
||||
#define DXD_INLINE 0x40 /* in-line data extent */
|
||||
#define DXD_EXTENT 0x20 /* out-of-line single extent */
|
||||
#define DXD_FILE 0x10 /* out-of-line file (inode) */
|
||||
#define DXD_CORRUPT 0x08 /* Inconsistency detected */
|
||||
|
||||
/* dxd_t field construction
|
||||
* Conveniently, the PXD macros work for DXD
|
||||
*/
|
||||
#define DXDlength PXDlength
|
||||
#define DXDaddress PXDaddress
|
||||
#define lengthDXD lengthPXD
|
||||
#define addressDXD addressPXD
|
||||
|
||||
/*
|
||||
* directory entry argument
|
||||
*/
|
||||
typedef struct component_name {
|
||||
int namlen;
|
||||
UniChar *name;
|
||||
} component_t;
|
||||
|
||||
|
||||
/*
|
||||
* DASD limit information - stored in directory inode
|
||||
*/
|
||||
typedef struct dasd {
|
||||
u8 thresh; /* Alert Threshold (in percent) */
|
||||
u8 delta; /* Alert Threshold delta (in percent) */
|
||||
u8 rsrvd1;
|
||||
u8 limit_hi; /* DASD limit (in logical blocks) */
|
||||
u32 limit_lo; /* DASD limit (in logical blocks) */
|
||||
u8 rsrvd2[3];
|
||||
u8 used_hi; /* DASD usage (in logical blocks) */
|
||||
u32 used_lo; /* DASD usage (in logical blocks) */
|
||||
} dasd_t;
|
||||
|
||||
#define DASDLIMIT(dasdp) \
|
||||
(((u64)((dasdp)->limit_hi) << 32) + __le32_to_cpu((dasdp)->limit_lo))
|
||||
#define setDASDLIMIT(dasdp, limit)\
|
||||
{\
|
||||
(dasdp)->limit_hi = ((u64)limit) >> 32;\
|
||||
(dasdp)->limit_lo = __cpu_to_le32(limit);\
|
||||
}
|
||||
#define DASDUSED(dasdp) \
|
||||
(((u64)((dasdp)->used_hi) << 32) + __le32_to_cpu((dasdp)->used_lo))
|
||||
#define setDASDUSED(dasdp, used)\
|
||||
{\
|
||||
(dasdp)->used_hi = ((u64)used) >> 32;\
|
||||
(dasdp)->used_lo = __cpu_to_le32(used);\
|
||||
}
|
||||
|
||||
/*
|
||||
* circular doubly-linked list (cdll)
|
||||
*
|
||||
* A circular doubly-linked list (cdll) is anchored by a pair of pointers,
|
||||
* one to the head of the list and the other to the tail of the list.
|
||||
* The elements are doubly linked so that an arbitrary element can be
|
||||
* removed without a need to traverse the list.
|
||||
* New elements can be added to the list before or after an existing element,
|
||||
* at the head of the list, or at the tail of the list.
|
||||
* A circle queue may be traversed in either direction.
|
||||
*
|
||||
* +----------+ +-------------------------------------+
|
||||
* | | | |
|
||||
* +->+-----+ | +->+-----+ +->+-----+ +->+-----+ |
|
||||
* | | h +-+ | | h +--+ | n +----+ | n +--+
|
||||
* | +-----+ | +-----+ | +-----+ | +-----+
|
||||
* | | t +-+ +-----+ t | | | p +--+ | | p +--+
|
||||
* | +-----+ | | | +-----+ | +-----+ | | +-----+ |
|
||||
* +----------+ | +-----------------------+ | |
|
||||
* | | | |
|
||||
* | +-------------------------+
|
||||
* | |
|
||||
* +----------------------------+
|
||||
*/
|
||||
/*
|
||||
* define header
|
||||
*
|
||||
* list header field definition in header element:
|
||||
*
|
||||
* type - type of list element struct embedding the link field
|
||||
*/
|
||||
#define CDLL_HEADER(type)\
|
||||
struct {\
|
||||
struct type *head;\
|
||||
struct type *tail;\
|
||||
}
|
||||
|
||||
struct cdll_header {
|
||||
struct cdll_header *head;
|
||||
struct cdll_header *tail;
|
||||
};
|
||||
|
||||
/*
|
||||
* define link
|
||||
*
|
||||
* list link field definition in list element:
|
||||
*
|
||||
* type - type of parent list element struct embedding the link field
|
||||
*/
|
||||
#define CDLL_ENTRY(type)\
|
||||
struct {\
|
||||
struct type *next;\
|
||||
struct type *prev;\
|
||||
}
|
||||
|
||||
struct cdll_entry {
|
||||
struct cdll_entry *next;
|
||||
struct cdll_entry *prev;
|
||||
};
|
||||
|
||||
/*
|
||||
* initialize header
|
||||
*
|
||||
* header - ptr to the header field in the header element
|
||||
*/
|
||||
#define CDLL_INIT(header) {\
|
||||
(header)->head = (void *)(header);\
|
||||
(header)->tail = (void *)(header);\
|
||||
}
|
||||
|
||||
/*
|
||||
* scan list
|
||||
*
|
||||
* header - ptr to the header field in the header element
|
||||
* elm - ptr to the element to be inserted
|
||||
* field - name of the link field in the list element
|
||||
*
|
||||
* struct header_container *container;
|
||||
* struct header_type *header;
|
||||
* struct element_type *elm;
|
||||
*
|
||||
* header = &container->header_field;
|
||||
* for (elm = header->head; elm != (void *)header; elm = elm->field.next)
|
||||
*/
|
||||
|
||||
/*
|
||||
* insert <elm> at head of list anchored at <header>
|
||||
*
|
||||
* header - ptr to the header field in the header element
|
||||
* elm - ptr to the list element to be inserted
|
||||
* field - name of the link field in the list element
|
||||
*/
|
||||
#define CDLL_INSERT_HEAD(header, elm, field) {\
|
||||
(elm)->field.next = (header)->head;\
|
||||
(elm)->field.prev = (void *)(header);\
|
||||
if ((header)->tail == (void *)(header))\
|
||||
(header)->tail = (elm);\
|
||||
else\
|
||||
(header)->head->field.prev = (elm);\
|
||||
(header)->head = (elm);\
|
||||
}
|
||||
|
||||
/*
|
||||
* insert <elm> at tail of list anchored at <header>
|
||||
*
|
||||
* header - ptr to the header field in the header element
|
||||
* elm - ptr to the list element to be inserted
|
||||
* field - name of the link field in the list element
|
||||
*/
|
||||
#define CDLL_INSERT_TAIL(header, elm, field) {\
|
||||
(elm)->field.next = (void *)(header);\
|
||||
(elm)->field.prev = (header)->tail;\
|
||||
if ((header)->head == (void *)(header))\
|
||||
(header)->head = (elm);\
|
||||
else\
|
||||
(header)->tail->field.next = (elm);\
|
||||
(header)->tail = (elm);\
|
||||
}
|
||||
|
||||
/*
|
||||
* insert <elm> after <listelm> of list anchored at <header>
|
||||
*
|
||||
* header - ptr to the header field in the header element
|
||||
* listelm - ptr to the list element at insertion point
|
||||
* elm - ptr to the list element to be inserted
|
||||
* field - name of the link field in the list element
|
||||
*/
|
||||
#define CDLL_INSERT_AFTER(header, listelm, elm, field) {\
|
||||
(elm)->field.next = (listelm)->field.next;\
|
||||
(elm)->field.prev = (listelm);\
|
||||
if ((listelm)->field.next == (void *)(header))\
|
||||
(header)->tail = (elm);\
|
||||
else\
|
||||
(listelm)->field.next->field.prev = (elm);\
|
||||
(listelm)->field.next = (elm);\
|
||||
}
|
||||
|
||||
/*
|
||||
* insert <elm> before <listelm> of list anchored at <header>
|
||||
*
|
||||
* header - ptr to the header field in the header element
|
||||
* listelm - ptr to list element at insertion point
|
||||
* elm - ptr to the element to be inserted
|
||||
* field - name of the link field in the list element
|
||||
*/
|
||||
#define CDLL_INSERT_BEFORE(header, listelm, elm, field) {\
|
||||
(elm)->field.next = (listelm);\
|
||||
(elm)->field.prev = (listelm)->field.prev;\
|
||||
if ((listelm)->field.prev == (void *)(header))\
|
||||
(header)->head = (elm);\
|
||||
else\
|
||||
(listelm)->field.prev->field.next = (elm);\
|
||||
(listelm)->field.prev = (elm);\
|
||||
}
|
||||
|
||||
/*
|
||||
* remove <elm> from list anchored at <header>
|
||||
*
|
||||
* header - ptr to the header field in the header element
|
||||
* elm - ptr to the list element to be removed
|
||||
* field - name of the link field in the list element
|
||||
*/
|
||||
#define CDLL_REMOVE(header, elm, field) {\
|
||||
if ((elm)->field.next == (void *)(header))\
|
||||
(header)->tail = (elm)->field.prev;\
|
||||
else\
|
||||
(elm)->field.next->field.prev = (elm)->field.prev;\
|
||||
if ((elm)->field.prev == (void *)(header))\
|
||||
(header)->head = (elm)->field.next;\
|
||||
else\
|
||||
(elm)->field.prev->field.next = (elm)->field.next;\
|
||||
}
|
||||
|
||||
#define CDLL_MOVE_TO_HEAD(header, elm, field) {\
|
||||
if ((elm)->field.prev != (void *)(header))\
|
||||
{\
|
||||
if ((elm)->field.next == (void *)(header))\
|
||||
(header)->tail = (elm)->field.prev;\
|
||||
else\
|
||||
(elm)->field.next->field.prev = (elm)->field.prev;\
|
||||
(elm)->field.prev->field.next = (elm)->field.next;\
|
||||
(elm)->field.next = (header)->head;\
|
||||
(elm)->field.prev = (void *)(header);\
|
||||
(header)->head->field.prev = (elm);\
|
||||
(header)->head = (elm);\
|
||||
}\
|
||||
}
|
||||
|
||||
#define CDLL_MOVE_TO_TAIL(header, elm, field) {\
|
||||
if ((elm)->field.next != (void *)(header))\
|
||||
{\
|
||||
(elm)->field.next->field.prev = (elm)->field.prev;\
|
||||
if ((elm)->field.prev == (void *)(header))\
|
||||
(header)->head = (elm)->field.next;\
|
||||
else\
|
||||
(elm)->field.prev->field.next = (elm)->field.next;\
|
||||
(elm)->field.next = (void *)(header);\
|
||||
(elm)->field.prev = (header)->tail;\
|
||||
(header)->tail->field.next = (elm);\
|
||||
(header)->tail = (elm);\
|
||||
}\
|
||||
}
|
||||
|
||||
/*
|
||||
* orphan list element
|
||||
*/
|
||||
#define CDLL_SELF(elm, field)\
|
||||
(elm)->field.next = (elm)->field.prev = (elm);
|
||||
|
||||
|
||||
/*
|
||||
* single head doubly-linked list
|
||||
*
|
||||
* A list is headed by a single head pointer.
|
||||
* The elements are doubly linked so that an arbitrary element can be
|
||||
* removed without a need to traverse the list.
|
||||
* New elements can be added to the list at the head of the list, or
|
||||
* after an existing element (NO insert at tail).
|
||||
* A list may only be traversed in the forward direction.
|
||||
* (note: the list is NULL terminated in next field.)
|
||||
*
|
||||
* +-----+ +->+-----+ +->+-----+ +->+-----+
|
||||
* | NULL| | | h +--+ | n +----+ | NULL|
|
||||
* +-----+ | +-----+ | +-----+ +-----+
|
||||
* | | | p +--+ | p +--+
|
||||
* | | +-----+ | +-----+ |
|
||||
* +-----------------------+ |
|
||||
* | |
|
||||
* +-------------------------+
|
||||
*/
|
||||
#define LIST_HEADER(type)\
|
||||
struct {\
|
||||
struct type *head;\
|
||||
}
|
||||
|
||||
#define LIST_ENTRY(type)\
|
||||
struct {\
|
||||
struct type *next;\
|
||||
struct type **prev;\
|
||||
}
|
||||
|
||||
#define LIST_INIT(header) { (header)->head = NULL; }
|
||||
|
||||
/*
|
||||
* scan list
|
||||
*
|
||||
* header - ptr to the header (field in header element)
|
||||
* elm - ptr to the element to be inserted
|
||||
* field - name of the link field in list element
|
||||
*
|
||||
* struct header_container *container;
|
||||
* struct header_type *header;
|
||||
* struct element_type *elm;
|
||||
*
|
||||
* header = &container->header_field;
|
||||
* for (elm = header->head; elm; elm = elm->field.next)
|
||||
*/
|
||||
|
||||
#define LIST_INSERT_HEAD(header, elm, field) {\
|
||||
if (((elm)->field.next = (header)->head) != NULL)\
|
||||
(header)->head->field.prev = &(elm)->field.next;\
|
||||
(header)->head = (elm);\
|
||||
(elm)->field.prev = &(header)->head;\
|
||||
}
|
||||
|
||||
#define LIST_INSERT_AFTER(listelm, elm, field) {\
|
||||
if (((elm)->field.next = (listelm)->field.next) != NULL)\
|
||||
(listelm)->field.next->field.prev = &(elm)->field.next;\
|
||||
(listelm)->field.next = (elm);\
|
||||
(elm)->field.prev = &(listelm)->field.next;\
|
||||
}
|
||||
|
||||
#define LIST_REMOVE(elm, field) {\
|
||||
if ((elm)->field.next != NULL)\
|
||||
(elm)->field.next->field.prev = (elm)->field.prev;\
|
||||
*(elm)->field.prev = (elm)->field.next;\
|
||||
}
|
||||
|
||||
#define LIST_SELF(elm, field) {\
|
||||
(elm)->field.next = NULL;\
|
||||
(elm)->field.prev = &(elm)->field.next;\
|
||||
}
|
||||
|
||||
#endif /* !_H_JFS_TYPES */
|
||||
Reference in New Issue
Block a user