Fórum Root.cz

Hlavní témata => Software => Téma založeno: meheh 08. 03. 2019, 17:49:31

Název: Nahradenie hex stringu
Přispěvatel: meheh 08. 03. 2019, 17:49:31
Chcel by som poprosit o radu. Hladam nejaky linuxovy prikaz/program, ktorym sa da zautomatizovat (pouzit v scripte) nahradenie urciteho hex retazcu inym retazcom. Teda programu dam povodny retazec, novy retazec, nazov suboru a program urobi tuto zmenu priamo v subore, bez vytvarania noveho/upraveneho suboru. Povodny aj novy hex string ma rovnaku velkost, takze velkost suboru sa nezmeni a malo by to byt okamzite. Takisto by sa hodilo, aby program po prvom vyskyte/nahradeni uz nepokracoval zbytocne dalej v hladani stringu v celom subore (kedze subory su velke).

Viem, ze hex stringy sa daju nahradit napr. cez sed:
Kód: [Vybrat]
sed 's/\x0A\x0B/\x0C\x0D/g'Avsak sed aj pri pouziti moznosti in-place (-i) vytvara novy subor, co zbytocne predlzuje cas. Tiez je tu ten problem, ze ak hexstring obsahuje newline character (0x0A), tak sed s tym ma problem a nic nenahradi. Da sa toto nejak vyriesit?

Dakujem za tipy.
Název: Re:Nahradenie hex stringu
Přispěvatel: Filip Jirsák 08. 03. 2019, 19:32:27
Pokud jste už zkoušel takový program hledat a nic jste nenašel, asi takový program k nalezení nebude. Je to dost netypická úloha, takže pokud to někdo potřeboval, nejspíš si na to napsal nějaký jednorázový nástroj a nezveřejnil ho.

Ale asi by to šlo poskládat – pro přepis té části soubory by asi šlo použít dd, a pak už jde jen o to najít, kde ten řetězec v souboru začíná.

Jinak požadavek na to, aby to bylo okamžitě, obecně není splnitelný – na CoW souborovém systému se příslušný blok stejně bude muset zapsat na nové místo.
Název: Re:Nahradenie hex stringu
Přispěvatel: meheh 09. 03. 2019, 01:53:08
No predpokladal som, ze nahradenie hex stringu v subore je vcelku trivialna a nie vynimocna zalezitost, takze ma celkom prekvapuje, ze na to nie je dostatok utilit...

Co sa tyka toho okamziteho zapisu, na Windows som pouzival HxD hexeditor, kde sa dal upravit priamo subor, tak som cakal, ze nieco podobne bude aj pre linux a v terminali...
Název: Re:Nahradenie hex stringu
Přispěvatel: Ink 09. 03. 2019, 08:45:25
Bez zaruky a bez krasy:

#!/usr/bin/env python3

import sys

def findIndex(f, sa):
    ri = 0
    ra = []
    sl = len(sa)
    while True:
        try:
            b = f.read(1)
            if (len(b) == 0):
                raise EOFError()
            ra.append(b[0])
        except EOFError:
            return -1
        ri += 1
        if (len(ra) > len(sa)):
            ra.pop(0)
        if (ra == sa):
            return ri - sl


def write(f, index, s):
    f.seek(index)
    f.write(s)


def replace(fn, ih, oh):
    f = open(fn, "rb+")
    index = findIndex(f, list(bytes.fromhex(ih)))
    if (index == -1):
        print("Not found")
    else:
        write(f, index, bytes.fromhex(oh))
    f.close()


if __name__ == '__main__':
    if (len(sys.argv) != 4):
        print("Usage: %s filename inhex outhex", sys.argv[0])
    else:
        replace(sys.argv[1], sys.argv[2], sys.argv[3])
Název: Re:Nahradenie hex stringu
Přispěvatel: Filip Jirsák 09. 03. 2019, 10:27:10
No predpokladal som, ze nahradenie hex stringu v subore je vcelku trivialna a nie vynimocna zalezitost, takze ma celkom prekvapuje, ze na to nie je dostatok utilit...
Za triviální a nikoli výjimečnou záležitost je v unixu považováno dokonce nahrazení textu v proudu bajtů, přičemž proud bajtů je obecnější věc, než jen soubor. Takže utilit na to existuje spousta. Vy ale na tu náhradu máte speciální předpoklady a speciální požadavky, ty obecné nástroje tedy nechcete použít.

Co sa tyka toho okamziteho zapisu, na Windows som pouzival HxD hexeditor, kde sa dal upravit priamo subor, tak som cakal, ze nieco podobne bude aj pre linux a v terminali...
A ten HxD jste mohl použít dávkově? Unix je založený na tom, že má spoustu jednoduchých nástrojů, které můžete kombinovat. Takže to, co chcete udělat, samozřejmě je možné, akorát si musíte pospojovat použití vhodných nástrojů. Díky tomu pak ty nástroje můžete snadno používat dávkově.
Název: Re:Nahradenie hex stringu
Přispěvatel: gill 10. 03. 2019, 09:34:23
Bez zaruky a bez krasy:

#!/usr/bin/env python3

import sys

def findIndex(f, sa):
    ri = 0
    ra = []
    sl = len(sa)
    while True:
        try:
            b = f.read(1)
            if (len(b) == 0):
                raise EOFError()
            ra.append(b[0])
        except EOFError:
            return -1
        ri += 1
        if (len(ra) > len(sa)):
            ra.pop(0)
        if (ra == sa):
            return ri - sl


def write(f, index, s):
    f.seek(index)
    f.write(s)


def replace(fn, ih, oh):
    f = open(fn, "rb+")
    index = findIndex(f, list(bytes.fromhex(ih)))
    if (index == -1):
        print("Not found")
    else:
        write(f, index, bytes.fromhex(oh))
    f.close()


if __name__ == '__main__':
    if (len(sys.argv) != 4):
        print("Usage: %s filename inhex outhex", sys.argv[0])
    else:
        replace(sys.argv[1], sys.argv[2], sys.argv[3])


to je hodne neefektivni. Pouzijte radeji mmap.
Název: Re:Nahradenie hex stringu
Přispěvatel: Ink 10. 03. 2019, 10:18:19
to je hodne neefektivni. Pouzijte radeji mmap.

Tohle mě zajímá. Soubor se čte sekvenčně, pravděpodobně s bufferováním. Zapisuje se stejně dlouhý řetězec, tudíž se v souboru nic neposouvá. Co na tom vylepší mmap?
Název: Re:Nahradenie hex stringu
Přispěvatel: Ink 10. 03. 2019, 10:29:16
to je hodne neefektivni. Pouzijte radeji mmap.

Tohle mě zajímá. Soubor se čte sekvenčně, pravděpodobně s bufferováním. Zapisuje se stejně dlouhý řetězec, tudíž se v souboru nic neposouvá. Co na tom vylepší mmap?

Asi bude rychlejší použít find(), o tom žádná. Ale pak člověk musí řešit přesahy apod. Já jsem napsal rychlořešení za dvě minuty, ani jsem netvrdil, že to je dokonalé řešení.
Název: Re:Nahradenie hex stringu
Přispěvatel: Ink 10. 03. 2019, 10:59:53
Tohle je výrazně optimálnější, i bez mmap()...

#!/usr/bin/env python3

import sys


def regions(f):
    chunkLength = 50000000
    offset = 0
    c1 = f.read(chunkLength)
    while (len(c1) == chunkLength):
        c2 = f.read(chunkLength)
        yield offset, c1 + c2
        c1 = c2
        offset += chunkLength
    yield offset, c1


def findIndex(f, s):
    for offset, chunk in regions(f):
        index = chunk.find(s)
        if (index >= 0):
            return offset + index

    return -1


def write(f, index, s):
    f.seek(index)
    f.write(s)


def replace(fn, ih, oh):
    f = open(fn, "rb+")
    index = findIndex(f, bytes.fromhex(ih))
    if (index == -1):
        print("Not found")
    else:
        write(f, index, bytes.fromhex(oh))
    f.close()


if __name__ == '__main__':
    if (len(sys.argv) != 4):
        print("Usage: %s filename inhex outhex", sys.argv[0])
    else:
        replace(sys.argv[1], sys.argv[2], sys.argv[3])
Název: Re:Nahradenie hex stringu
Přispěvatel: klobások 10. 03. 2019, 12:10:35
Tu mas Go verziu(2mb), ale moc som to netestoval takze za nic nerucim.

Kód: [Vybrat]
package main

import (
"flag"
"golang.org/x/exp/mmap"
"log"
"os"
"time"
)

var (
what, with, where string
)

func main() {
flag.StringVar(&what, "replace", "", "String to be replaced.")
flag.StringVar(&with, "with", "", "String to act as replacement.")
flag.StringVar(&where, "in", "", "Path to file.")
flag.Parse()

reader, err := mmap.Open(where)
if err != nil {
log.Fatal(err)
}
defer reader.Close()

file, err := os.OpenFile(where, os.O_WRONLY, 0666)
if err != nil {
log.Fatal(err)
}
defer file.Close()

start := time.Now()
defer func() {
log.Println("Elapsed time:", time.Now().Sub(start).String())
}()

var pos int
whatLen := len(what)
cpr := make([]byte, whatLen, whatLen)
first := what[0]
max := reader.Len()

for {
if pos >= max {
log.Println("no match found")
return
}

if reader.At(pos) == first {
if _, err := reader.ReadAt(cpr, int64(pos)); err != nil {
log.Fatal(err)
}
if string(cpr) == what {
if _, err := file.WriteAt([]byte(with), int64(pos)); err != nil {
log.Fatal(err)
} else {
log.Println("Success")
}
return
} else {
pos += whatLen
continue
}
}

pos++
}
}

Název: Re:Nahradenie hex stringu
Přispěvatel: Kamil Podlešák 10. 03. 2019, 12:11:16
mmap verze, python 3

Kód: [Vybrat]
#!/usr/bin/env python3
# vim:ts=4 sw=4:

import sys
import os
import mmap

if len(sys.argv) < 4:
    print("Usage: "+sys.argv[0]+" file searchHex replaceHex")
    sys.exit(-1)

(repl_from, repl_to) = [bytearray.fromhex(h) for h in sys.argv[2:4]]
repl_len = len(repl_from)
if repl_len != len(repl_to):
    print("Error: search and replacement strings have different lengths")
    sys.exit(-2)
filename=sys.argv[1]

with open(filename, "r+b") as f:
    map = mmap.mmap(f.fileno(), 0)
    idx = 0
    while True:
        idx=map.find(repl_from, idx)
        if idx<0:
            break;
        map.seek(idx)
        map.write(repl_to)
        idx += repl_len
    map.close()
Název: Re:Nahradenie hex stringu
Přispěvatel: Kamil Podlešák 10. 03. 2019, 12:17:01
Tu mas Go verziu(2mb), ale moc som to netestoval takze za nic nerucim.
Při zběžném pohledu se mi zdá, že to bude fungovat korektně jen pokud je v hledaném řetězci každý byte unikátní.
Název: Re:Nahradenie hex stringu
Přispěvatel: Ink 10. 03. 2019, 13:32:53
Hm, nevadí vám, že se soubor při takto jednoduchém použití mmap musí celý vejít do RAM? Nebo mi něco uniká?
Název: Re:Nahradenie hex stringu
Přispěvatel: klobások 10. 03. 2019, 13:51:47
https://en.wikipedia.org/wiki/Demand_paging

Cele nacitanie suboru vznika len v pripade ak robis "read all" operacie. Cize bezne sa subory prechadzaju riadok za riadkom, pripadne v blokoch, len malokedy sa nacitaju cele do pamete. Je jedno o aky jazyk ide.
Název: Re:Nahradenie hex stringu
Přispěvatel: Ink 10. 03. 2019, 14:11:15
https://en.wikipedia.org/wiki/Demand_paging

Cele nacitanie suboru vznika len v pripade ak robis "read all" operacie. Cize bezne sa subory prechadzaju riadok za riadkom, pripadne v blokoch, len malokedy sa nacitaju cele do pamete. Je jedno o aky jazyk ide.

To mi nedává moc smysl:

1. Jestli si načtu do paměti obsah celého souboru najednou, nebo po kouskách, do toho mmapu nic není. To je věc aplikace.

2. Hledání podřetězce v souboru přece je v nejhorším případě opravdu "read all".

3. Dovedu si samozřejmě představit, že je OS "chytrý" a dokáže podle potřeby uvolňovat kusy paměti, ale přijde mi to celé proti filosofii a smyslu toho mechanismu. Jednak on nemůže vědět, kam si budu chtít sáhnout hned v další operaci (tudíž se to celé může dost prodražit) a vůbec asi pro rychlou práci nechci takto nedeterministické chování systému.
Název: Re:Nahradenie hex stringu
Přispěvatel: Filip Jirsák 10. 03. 2019, 16:31:20
3. Dovedu si samozřejmě představit, že je OS "chytrý" a dokáže podle potřeby uvolňovat kusy paměti, ale přijde mi to celé proti filosofii a smyslu toho mechanismu. Jednak on nemůže vědět, kam si budu chtít sáhnout hned v další operaci (tudíž se to celé může dost prodražit) a vůbec asi pro rychlou práci nechci takto nedeterministické chování systému.
Smysl mmapu je právě v tom, že k datům přistupujete jako k souvislému bloku paměti, a OS se na pozadí stará o nahrávání příslušných bloků z disku do paměti a opačně o zápis na disk. Je to vlastně podobný mechanismus, jako swap, akorát se na disk zapisují jen změněná data a zapisují se do toho původního souboru.
Název: Re:Nahradenie hex stringu
Přispěvatel: Ink 10. 03. 2019, 16:50:19
3. Dovedu si samozřejmě představit, že je OS "chytrý" a dokáže podle potřeby uvolňovat kusy paměti, ale přijde mi to celé proti filosofii a smyslu toho mechanismu. Jednak on nemůže vědět, kam si budu chtít sáhnout hned v další operaci (tudíž se to celé může dost prodražit) a vůbec asi pro rychlou práci nechci takto nedeterministické chování systému.
Smysl mmapu je právě v tom, že k datům přistupujete jako k souvislému bloku paměti, a OS se na pozadí stará o nahrávání příslušných bloků z disku do paměti a opačně o zápis na disk. Je to vlastně podobný mechanismus, jako swap, akorát se na disk zapisují jen změněná data a zapisují se do toho původního souboru.

Jo, a jak poznám, kdy mi to odswapuje a kolik to skutečně sežere paměti? Co jsi mi chtěl vlastně sdělit konkrétního?
Název: Re:Nahradenie hex stringu
Přispěvatel: gill 10. 03. 2019, 16:54:21
Jo, a jak poznám, kdy mi to odswapuje a kolik to skutečně sežere paměti? Co jsi mi chtěl vlastně sdělit konkrétního?

to nepotrebujete vedet. Ani pri tom "sekvencnim" cteni neznate velikost bufferu.
Název: Re:Nahradenie hex stringu
Přispěvatel: Ink 10. 03. 2019, 17:15:13
Jo, a jak poznám, kdy mi to odswapuje a kolik to skutečně sežere paměti? Co jsi mi chtěl vlastně sdělit konkrétního?

to nepotrebujete vedet. Ani pri tom "sekvencnim" cteni neznate velikost bufferu.

OK, řešení Kamila P. funguje, 16 GB  soubor to prohrabalo, sežralo cca 4,5 GB RAM a nespadlo to.
Název: Re:Nahradenie hex stringu
Přispěvatel: Filip Jirsák 10. 03. 2019, 17:27:35
Jo, a jak poznám, kdy mi to odswapuje a kolik to skutečně sežere paměti?
Linux (a další systémy) funguje tak, že používá tzv. virtuální paměť. Každý proces má k dispozici svůj vlastní prostor virtuální paměti – třeba na x86 zařízeních má ta virtuální paměť standardně 4 GB, bez ohledu na to, že máte v počítači třeba jen 256 MB RAM. Operační systém se pak stará o mapování mezi touhle virtuální pamětí procesu a skutečnou RAM. A při tomhle mapování může dělat i to, že data nejsou fyzicky v paměti, ale dostanou se tam až v okamžiku, kdy chce proces k příslušné části paměti přistupovat. Dostat se tam mohou například i z disku – např. ze swapu, kam si je před tím operační systém odložil, když potřeboval fyzickou RAM pro jiné účely, a nebo ze souboru, který tvoří „podklad“ pod pamětí mapovanou mmapem.

V aplikaci nepoznáte, kdy swapuje nebo načítá soubor z disku / zapisuje na disk (samozřejmě pokud si nebudete měřit čas), operační systém to dělá transparentně na pozadí. Když aplikace chce přistoupit k paměti, která není právě mapovaná na reálnou RAM, ta aplikace se uspí, vyvolá se stránkování, data ze umístí někam do fyzické paměti, ta se namapuje na adresní prostor procesu a proces se probudí. Takže z pohledu procesu to vypadá tak, že dá požadavek na přístup k paměti a data v paměti jsou, akorát kdyby si proces měřil čas, zjistí, že někdy uběhlo hodně času, o kterém nic neví (což ale může nastat i ze spousty jiných důvodů, např. CPU využíval prioritnější proces).

Kolik to skutečně sežere paměti také z procesu nepoznáte. Vtip je právě v tom, že si to celé řídí samotný OS, který má přehled o všech aplikacích v systému. Takže například může data dlouho nechávat v cache, protože ví, že nikdo RAM nepotřebuje, nebo naopak zapíše data do swapu, protože potřebuje RAM uvolnit pro jiný proces.

Co jsi mi chtěl vlastně sdělit konkrétního?
Jak doopravdy funguje mmap, a že funguje jinak, než si myslíte. Že při použití mmapu neřídí načítání ze souboru do paměti a zápis z paměti do souboru aplikace, ale operační systém. A že i když má aplikace přes mmap zpřístupněný celý soubor ve svém virtuálním adresním prostoru (ve virtuální paměti), neznamená to, že je celý ten soubor načtený ve fyzické RAM.
Název: Re:Nahradenie hex stringu
Přispěvatel: Ink 10. 03. 2019, 18:45:01
OK, tohle mi smysl dává, dík.