mirror of
https://github.com/SickGear/SickGear.git
synced 2024-11-30 08:23:37 +00:00
120 lines
3.8 KiB
Python
120 lines
3.8 KiB
Python
|
"""
|
||
|
Linux swap file.
|
||
|
|
||
|
Documentation: Linux kernel source code, files:
|
||
|
- mm/swapfile.c
|
||
|
- include/linux/swap.h
|
||
|
|
||
|
Author: Victor Stinner
|
||
|
Creation date: 25 december 2006 (christmas ;-))
|
||
|
"""
|
||
|
|
||
|
from hachoir.parser import Parser
|
||
|
from hachoir.field import (ParserError, GenericVector,
|
||
|
UInt32, String,
|
||
|
Bytes, NullBytes, RawBytes)
|
||
|
from hachoir.core.endian import LITTLE_ENDIAN
|
||
|
from hachoir.core.tools import humanFilesize
|
||
|
from hachoir.core.bits import str2hex
|
||
|
|
||
|
PAGE_SIZE = 4096
|
||
|
|
||
|
# Definition of MAX_SWAP_BADPAGES in Linux kernel:
|
||
|
# (__swapoffset(magic.magic) - __swapoffset(info.badpages)) / sizeof(int)
|
||
|
MAX_SWAP_BADPAGES = ((PAGE_SIZE - 10) - 1536) // 4
|
||
|
|
||
|
|
||
|
class Page(RawBytes):
|
||
|
static_size = PAGE_SIZE * 8
|
||
|
|
||
|
def __init__(self, parent, name):
|
||
|
RawBytes.__init__(self, parent, name, PAGE_SIZE)
|
||
|
|
||
|
|
||
|
class UUID(Bytes):
|
||
|
static_size = 16 * 8
|
||
|
|
||
|
def __init__(self, parent, name, *args, **kwargs):
|
||
|
Bytes.__init__(self, parent, name, 16, *args, **kwargs)
|
||
|
|
||
|
def createDisplay(self):
|
||
|
text = str2hex(self.value, format=r"%02x")
|
||
|
return "%s-%s-%s-%s-%s" % (
|
||
|
text[:8], text[8:12], text[12:16], text[16:20], text[20:])
|
||
|
|
||
|
|
||
|
class LinuxSwapFile(Parser):
|
||
|
PARSER_TAGS = {
|
||
|
"id": "linux_swap",
|
||
|
"file_ext": ("",),
|
||
|
"category": "file_system",
|
||
|
"min_size": PAGE_SIZE * 8,
|
||
|
"description": "Linux swap file",
|
||
|
"magic": (
|
||
|
(b"SWAP-SPACE", (PAGE_SIZE - 10) * 8),
|
||
|
(b"SWAPSPACE2", (PAGE_SIZE - 10) * 8),
|
||
|
(b"S1SUSPEND\0", (PAGE_SIZE - 10) * 8),
|
||
|
),
|
||
|
}
|
||
|
endian = LITTLE_ENDIAN
|
||
|
|
||
|
def validate(self):
|
||
|
magic = self.stream.readBytes((PAGE_SIZE - 10) * 8, 10)
|
||
|
if magic not in (b"SWAP-SPACE", b"SWAPSPACE2", b"S1SUSPEND\0"):
|
||
|
return "Unknown magic string"
|
||
|
if MAX_SWAP_BADPAGES < self["nb_badpage"].value:
|
||
|
return "Invalid number of bad page (%u)" % self["nb_badpage"].value
|
||
|
return True
|
||
|
|
||
|
def getPageCount(self):
|
||
|
"""
|
||
|
Number of pages which can really be used for swapping:
|
||
|
number of page minus bad pages minus one page (used for the header)
|
||
|
"""
|
||
|
# -1 because first page is used for the header
|
||
|
return self["last_page"].value - self["nb_badpage"].value - 1
|
||
|
|
||
|
def createDescription(self):
|
||
|
if self["magic"].value == "S1SUSPEND\0":
|
||
|
text = "Suspend swap file version 1"
|
||
|
elif self["magic"].value == "SWAPSPACE2":
|
||
|
text = "Linux swap file version 2"
|
||
|
else:
|
||
|
text = "Linux swap file version 1"
|
||
|
nb_page = self.getPageCount()
|
||
|
return "%s, page size: %s, %s pages" % (
|
||
|
text, humanFilesize(PAGE_SIZE), nb_page)
|
||
|
|
||
|
def createFields(self):
|
||
|
# First kilobyte: boot sectors
|
||
|
yield RawBytes(self, "boot", 1024, "Space for disklabel etc.")
|
||
|
|
||
|
# Header
|
||
|
yield UInt32(self, "version")
|
||
|
yield UInt32(self, "last_page")
|
||
|
yield UInt32(self, "nb_badpage")
|
||
|
yield UUID(self, "sws_uuid")
|
||
|
yield UUID(self, "sws_volume")
|
||
|
yield NullBytes(self, "reserved", 117 * 4)
|
||
|
|
||
|
# Read bad pages (if any)
|
||
|
count = self["nb_badpage"].value
|
||
|
if count:
|
||
|
if MAX_SWAP_BADPAGES < count:
|
||
|
raise ParserError("Invalid number of bad page (%u)" % count)
|
||
|
yield GenericVector(self, "badpages", count, UInt32, "badpage")
|
||
|
|
||
|
# Read magic
|
||
|
padding = self.seekByte(PAGE_SIZE - 10, "padding", null=True)
|
||
|
if padding:
|
||
|
yield padding
|
||
|
yield String(self, "magic", 10, charset="ASCII")
|
||
|
|
||
|
# Read all pages
|
||
|
yield GenericVector(self, "pages", self["last_page"].value, Page, "page")
|
||
|
|
||
|
# Padding at the end
|
||
|
padding = self.seekBit(self.size, "end_padding", null=True)
|
||
|
if padding:
|
||
|
yield padding
|