Menu

#478 Write protected files aren't passed through as read-only to the application

SVN
wont-fix
1
2018-04-20
2018-04-19
krcroft
No

On the host OS, write protecting files that an application opens in read-write-mode but never writes to, should result in the read-only behavior. That is, the application's fileopen call should succeed, and, because the application never writes to the file, operate as expected.

There's also the scenario where the application may write to the file, such as described in DOS's attrib man-page: If a file has an attribute of +R, it can be read from, but not written to (for example, you can use your word processor to look at it but not to alter it).

https://web.csulb.edu/~murdock/attrib.html

Dosbox would also not permit this scenario because the word processor will be blocked from opening the read-only document in the first place.

I beleive the fix is to downgrade application requests for "rb+" fileopen calls to "rb" calls if the file is in indeed read-only on the host filesystem. How the application behaves with a read-only file is up to the application, and not preempted by dosbox.

(I will follow up with a list of games that open their data files read-write without ever writing to them, to show this behavior in action)

Discussion

  • krcroft

    krcroft - 2018-04-19

    Here's a list of games that attempt open "data" files read-write but never write to them.
    To reproduce the behavior, chmod -w the list of files, then launch the game in dosbox.

    Champions of Krynn will stall at a black screen after making two attempts to open its first .dax file; but when read-only pass-thru is permitted, the game loads as expected (the only writes it actually performs are only within its "save" directory)

    AD&D Dragonlance I Champions of Krynn:
    8x8d1.dax
    comspr.dax
    cursor.dax
    items
    sky.dax

    AD&D Dragonlance II Death Knights of Krynn:
    8x8d1.dax
    8x8d4.dax
    back4.dax
    comspr.dax
    cpic1.dax
    ecl1.dax
    geo1.dax
    item0.dax
    items
    mon1cha.dax
    mon1itm.dax
    mon1spc.dax
    mon1wiz.dax
    music.dax
    pic4.dax
    skygrnd.dax
    title.dax
    walldef4.dax

    AD&D Forgotten Realms II Curse of the Azure Bonds:
    8x8d1.dax
    comspr.dax
    items
    sky.dax
    title.dax

    AD&D Forgotten Realms III Secret of The Silver Blades:
    8x8d1.dax
    8x8d5.dax
    comspr.dax
    items
    sky.dax
    sound.dax
    title.dax

    AD&D Legend III Eye of the Beholder III Assault of Myth Drannor:
    intro.gff

    AD&D Savage Frontier I Gateway to the Savage Frontier:
    8x8d1.dax
    8x8d.dax
    comspr.dax
    dungcom.dax
    items.1
    music.dax
    randcom.dax
    sky.dax
    title.dax
    zounds.dax

    AD&D Savage Frontier II Treasures of the Savage Frontier:
    8x8d0.dax
    bord.dax
    cursor.dax
    item0.dax
    items
    music.dax
    title.dax
    zounds.dax

    Air Duel 80 Years of Dogfighting:
    _dog_a
    _dog_b
    _dog_c
    _index

    B-17 Flying Fortress:
    _fonts
    _front
    _index
    _intro
    _music

    Blood:
    blood000.dem
    surface.dat
    tiles000.art
    tiles001.art
    tiles002.art
    tiles003.art
    tiles004.art
    tiles005.art
    tiles006.art
    tiles007.art
    tiles008.art
    tiles009.art
    tiles010.art
    tiles011.art
    tiles012.art
    tiles013.art
    tiles014.art
    tiles015.art
    voxel.dat

    Boston Bomb Club:
    blancpc.io

    Brix:
    brix0.dat
    brixb.dat

    Caesar I:
    houses2.pl8
    imprlogo.256
    romfont.pl8
    shade.256
    title3.256

    Cruise for a Corpse:
    d1
    delphine.lng
    system.fnt
    vgadrv.bin
    vol.1
    vol.cnf

    Darklands:
    cine.gff
    darkrun.gff
    gpldata.gff
    resource.gff
    rgnff.gff
    segobjex.gff

    Duke Nukem 3D:
    duke3d.grp

    Duke Nukem II:
    nukem2.cmp
    nukem2.f2
    nukem2.f5

    Epic Pinball:
    ep1.dat
    ep1.exe
    ep2.dat
    ep2.exe
    ep3.dat
    ep3.exe
    ep4.dat
    ep4.exe
    ep5.dat
    ep5.exe
    ep6.dat
    ep6.exe
    ep7.dat
    ep7.exe
    ep8.dat
    ep8.exe
    id1.dat
    id2.dat
    id3.dat
    id4.dat
    id5.dat
    id6.dat
    id7.dat
    id8.dat
    intro.pin
    pinball.exe
    reg.dat
    sfx0.pin

    Fury of the Furries:
    dat
    lang.dat

    Highway Hunter:
    123.dat

    Hoyle Official Book of Games 1:
    hoyle.set

    Hoyle Official Book of Games 3:
    version

    Hoyle's Classic Card Games:
    version

    IndyCar Series:
    cars
    effects
    tracks
    a32mt32.dll
    a32sbdg.dll
    calib.val
    fat.mt
    main.dat

    Lemmings 1:
    russell.dat
    (write protecting this file foils the copy-protection)

    Lode Runner:
    lr.usr

    Lotus The Ultimate Challenge:
    lotus.dat

    MechWarrior 1:
    6x6.fnt
    fox88.fnt
    mech.mus
    mw_2pics.bin
    mw_apics.bin
    mw_cpics.bin
    mw_gpics.bin
    mw_tpics.bin

    Metaltech Battledrome:
    data

    Metaltech EarthSiege:
    data

    Might and Magic II Gates to Another World:
    master.16
    mcga.drv
    mm2.ch
    nwcp.16
    timer.drv

    Might and Magic III Isles of Terra:
    mm3.cc

    NASCAR Racing:
    cars
    effects
    objs
    rol
    sound
    tracks
    calendar
    main.dat

    Operation Carnage:
    resource.1
    resource.2
    resource.3
    resource.4
    resource.5
    resource.6
    resource.des

    Pinball Dreams II:
    21stlogo.vga
    font.spr
    presents.vga
    spider.vga
    title.vga

    Pizza Tycoon:
    pizza

    Project Space Station:
    opening.bin
    q7t.dat
    screen2.bin
    screen3.bin
    text1.dat
    t.vit

    Prophecy of the Shadow:
    font.jrm
    pattern.jrm
    pointer.jrm
    pots8.jrm
    splash.jrm
    stone.jrm
    title.jrm

    Realms of Arkania I Blade of Destiny:
    introdat.dir
    introdat.vol

    Redneck Rampage:
    redneck.grp

    Rise of the Triad Dark War:
    darkwar.wad
    remote1.rts

    Secret Agent Mission 1:
    sam101e.snd
    sam101.gfx
    sam102e.snd
    sam102.gfx
    sam103e.snd

    Secret Agent Mission 2 Kill Again Island:
    sam201e.snd
    sam201.gfx
    sam202e.snd
    sam202.gfx
    sam203e.snd

    Shadow Warrior:
    sw.grp

    SimAnt The Electronic Ant Colony:
    hcegant.dat
    hcegant.ndx
    shared.dat
    shared.ndx
    sound.dat
    sound.ndx

    SimEarth The Living Planet:
    hcegaia.dat
    hcegaia.ndx
    shared.dat
    shared.ndx

    SimFarm:
    megadata.eea
    megadata.idx

    SimLife:
    cpl4life.dat
    cpl4life.ndx

    Space Quest I (1991) The Sarien Encounter:
    version

    Space Quest IV The Time Rippers:
    version

    Space Quest VI The Spinal Frontier:
    version

    Space Quest V The Next Mutation:
    version

    Terminator (1993) Rampage:
    logo1.flc
    logo2.flc

    Terminator 2 The Arcade Game:
    arena.lbm
    probprod.lbm
    roland.bin
    virgin.lbm
    xfontbig.bin
    xfonthud.bin
    xfontit.bin
    xfontsml.bin
    xmisc.bin
    xshrap1.bin

    Tex Murphy Martian Memorandum:
    adlib.drv
    music.ap
    title.ap

    The Games Winter Challenge:
    winter.exe

    The Smurfs:
    drum.bnk
    melodic.bnk

    Tyrian 2000:
    music.mus
    newsh1.shp
    newsh$.shp
    palette.dat
    tyrian.hdt
    tyrian.pic
    tyrian.shp
    tyrian.snd
    voices.snd

    Ultima 6 The False Prophet:
    blocks.shp
    bootup.m
    intro_1.shp
    intro.ptr
    mainmenu.shp
    mcgadrv.bin
    midi.dat
    palettes.int
    titles.shp
    u6roland.drv
    u6.set
    ultima.m

    Ultima 7 Part One The Black Gate:
    static
    install.prm

    Ultima 7 Part Two Serpent Isle:
    static
    install.prm

    Ultima 8 Pagan:
    static
    usecode
    ailxmi.dll

    Ultima Worlds of Adventure 1 The Savage Empire:
    create.lzc
    music.lzc
    savage.fnt
    savage.pal
    savage.tim
    strax.drv
    supertm.drv
    title.lzc
    tm.drv

    Ultima Worlds of Adventure 2 Martian Dreams:
    fonts.lzc
    mdd_mus.lzc
    md.tim
    strax.drv
    strx_mus.lzc
    supertm.drv
    title.lzc
    tm.drv

    Vette!:
    bigvet.bin
    egapic.bin
    egaskill.bin
    garage.bin
    highsc.bin
    horizon0.bin
    horizon1.bin
    horizon2.bin
    mappic.bin
    redvette.bin
    spetrum.bin
    title.bin
    vx.bin

    Warlords II:
    data
    erythea
    pics
    sound
    udb
    black.pal
    chance17.fin
    chance17.fnt
    chance36.fin
    chance36.fnt
    sound.dat
    standard.pal
    stand.pck
    text.fin
    text.fnt

    Wasteland:
    colorf.fnt
    curs
    ic0_9.wlf
    masks.wlf
    title.pic
    transtbl
    wla.bin

    Witchaven:
    palette.dat
    setup.dat
    tables.dat

    Wizardry 1 Proving Grounds of the Mad Overlord:
    wiz1.dsk

    Wizardry 2 Knight of Diamonds:
    wiz2.dsk

    Wizardry 3 Legacy of Llylgamyn:
    wiz3.dsk

    Wizardry 4 The Return of Werdna:
    wiz4.dsk

    Wizardry 5 Heart of the Maelstrom:
    wiz5.dsk

    Wrath of Earth:
    woe.rsc

    Zone 66:
    font.z66
    m03gmuz.z66
    mapadat3.z66
    mapapic.z66
    mapbdat3.z66
    mapbpic.z66
    mapcdat3.z66
    mapcpic.z66
    mapdat.z66
    mapddat3.z66
    mapdpic.z66
    mapedat3.z66
    mapepic.z66
    mapfdat3.z66
    mapfpic.z66
    mapgdat3.z66
    mapgpic.z66
    maphdat3.z66
    maphpic.z66
    mpal.z66
    prefs.z66
    shipdat0.z66
    shipdat1.z66
    title.z66
    tpal.z66
    zil0.z66
    zim2.z66

     
  • krcroft

    krcroft - 2018-04-19

    Here's a small patch that permits read-only pass through.

    The "isWriteProtectedFileNew(filename)" member function keeps a simple vector<string> record of read-only files already encountered to avoid redudant log messages, as some games repeatedly open and close the same file(s) in read-write mode.

    Here's the output from a clean run of Champions of Krynn with all files write-protected except for its "save" directory.

    DOSBox version SVN
    Copyright 2002-2017 DOSBox Team, published under GNU GPL.
    CONFIG:Loading primary settings from config file /home/kcroft/.dosbox/dosbox-SVN.conf
    ALSA:Client initialised [128:0]
    MIDI: Opened device:alsa
    FILESYSTEM: protecting ./8x8d1.dax from writes because it's read-only
    FILESYSTEM: protecting ./comspr.dax from writes because it's read-only
    FILESYSTEM: protecting ./sky.dax from writes because it's read-only
    FILESYSTEM: protecting ./cursor.dax from writes because it's read-only
    FILESYSTEM: protecting ./items from writes because it's read-only
    FILESYSTEM: protecting ./chead.dax from writes because it's read-only
    FILESYSTEM: protecting ./cbody.dax from writes because it's read-only
    FILESYSTEM: protecting ./ecl1.dax from writes because it's read-only
    FILESYSTEM: protecting ./bigpic1.dax from writes because it's read-only

     
  • ripsaw8080

    ripsaw8080 - 2018-04-20

    In real DOS, attempting to open a file for write (or read/write) access when the file has the read-only attribute results in "access denied" (error code 5); and DOSBox emulates this behavior. DOS programs handle file open errors with varying degrees of grace -- and hanging at a black screen is indeed one of the more ungraceful. In any case, the message that DOSBox prints in its status window regarding why the file failed to open is a courtesy users of real DOS do not receive.

    If I'm not mistaken, you're suggesting that DOSBox take a "hope for the best" approach by proceeding to open read-only files even though write access has been requested, and maybe the DOS program won't try to write to it. However, if the program does try to write, then what should DOSBox do? An access denied error, I suppose; but since the file couldn't be opened in the first place in real DOS, that'd be just making something up. Besides, a DOS program that doesn't handle open errors gracefully may not handle write errors any better.

     
    • krcroft

      krcroft - 2018-04-20

      Thanks Ripsaw, yes - that's the behavior I was thinking should occur.

      The hope-for-the-best approach shifts the point of failure from the read event to the write event, which might never happen (in the case of the file lists I sent), or would only happen if the user did something to trigger an actual write (save game). It's an interesting feature but because DOS programmers didn't have to deal with it, it shouldn't be allowed.

      I had infered from that Attrib documentation that DOS itself permitted the reading of write-protecting file that applications attempt to open read-write, without confirming actual behavior on DOS. Indeed, DOSBox is doing the right thing.

      It's unfortunate so many games from that era attempt to open strict data files with read & write flags, but it goes with the times.. single-user-system (no concept of separating application data vs. user files besides simple sub-directories), no concept of security or trying to minimize the "rights" a given operation needs to get its task done; and for these early games, they likely re-used a single "do-everything" file handler function.

      But in most cases, I think it was just lazy programming.

      Please feel free to close this false-positive issue!

       

      Last edit: krcroft 2018-04-20
  • Qbix

    Qbix - 2018-04-20
    • status: open --> wont-fix
    • assigned_to: ripsaw8080
     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.