NixOS / nixpkgs

Nix Packages collection & NixOS
MIT License
16.59k stars 13.07k forks source link

factorio: unable to run the campaign #91409

Open mweinelt opened 4 years ago

mweinelt commented 4 years ago

Describe the bug As soon as I enter a campaign I get an error, that factorio does not have the permission to copy files inside the nix store, which drops me back inside the menu.

The application logs this to shell:

 144.368 Error MainLoop.cpp:1195: Exception at tick 5158719: Error while running reload_script: filesystem error: copy_file "/nix/store/q4g4v32p6fmv0xs1lzc40lx0fjf7708q-factorio-alpha-0.17.79/share/factorio/data/base/campaigns/npe/locale/af/npe.cfg" to "/home/hexa/.factorio/temp/currently-playing/campaign-locale/af/npe.cfg" failed: Permission denied [/nix/store/q4g4v32p6fmv0xs1lzc40lx0fjf7708q-factorio-alpha-0.17.79/share/factorio/data/base/campaigns/npe/locale/af/npe.cfg] [/home/hexa/.factorio/temp/currently-playing/campaign-locale/af/npe.cfg]

To Reproduce Steps to reproduce the behavior:

  1. Start the game
  2. Choose Play
  3. Start Campaign
  4. Pick "Introduction" (or any other entry)
  5. Press Play
  6. Press Play again

Expected behavior The introduction should be playable. A clear and concise description of what you expected to happen.

Notify maintainers

@Baughn @elitak @erictapen

Metadata

 - system: `"x86_64-linux"`
 - host os: `Linux 5.7.4, NixOS, 20.09.git.647821e8e0e (Nightingale)`
 - multi-user?: `yes` - system: `"x86_64-linux"`
 - host os: `Linux 5.7.4, NixOS, 20.09.git.647821e8e0e (Nightingale)`
 - multi-user?: `yes`
 - sandbox: `yes`
 - version: `nix-env (Nix) 2.3.6`
 - channels(root): `"nixos-20.09pre223023.fce7562cf46, nixos-unstable-20.09pre223023.fce7562cf46"`
 - channels(hexa): `""`
 - nixpkgs: `/nix/var/nix/profiles/per-user/root/channels/nixos`

Maintainer information:

# a list of nixpkgs attributes affected by the problem
attribute: factorio
# a list of nixos modules affected by the problem
module:
mweinelt commented 4 years ago

The same is the case for the ingame mini-tutorials sadly.

6320.971 Error AppManager.cpp:677: Failed to load tutorial: Error while running reload_script: filesystem error: copy_file "/nix/store/q4g4v32p6fmv0xs1lzc40lx0fjf7708q-factorio-alpha-0.17.79/share/factorio/data/base/tutorials/stack-transfers/control.lua" to "/home/hexa/.factorio/temp/currently-playing-tutorial/control.lua" failed: Permission denied [/nix/store/q4g4v32p6fmv0xs1lzc40lx0fjf7708q-factorio-alpha-0.17.79/share/factorio/data/base/tutorials/stack-transfers/control.lua] [/home/hexa/.factorio/temp/currently-playing-tutorial/control.lua]
akamaus commented 4 years ago

Looks like it's a known issue, See https://github.com/NixOS/nixpkgs/pull/73165#issuecomment-615916107 for (ugly) workaround.

priegger commented 4 years ago

Thanks for the bug report, @mweinelt!

I remember hacking around this once with something like:

while true; do chmod -R +rw /home/hexa/.factorio/temp; done

But this is ugly and not guaranteed to work.

From #73165:

This is actually a common problem that happens with NixOS. It sounds like factorio copies these files from the nix store to some temp directory and wants to write to them, but it doesn't chmod them and make them owned by the proper user. I bet you can fix this on your own by fixing the permissions, and this is a pretty reasonable bug report to submit (I make one for it all the time).

(by @worldofpeace)

I see three possible ways. Only the third one being correct, imho.

  • Somehow fix the permissions inside /nix/store. I guess it may be hard because AFAIK they're reset to 444 on last installation stage
  • Implement some weird hook using LD_PRELOAD or something like that. We should detect copy being created and fix permissions on the fly.
  • Solve the problem upstream, I would say it's perfectly ok to have master-copy of files read-only. If not, why to copy them in the first place? It's responsibility of Factorio to ensure paths it's going to write to have appropriate permissions.

(by @akamaus)

I'll add a 4th way:

So, the first step would be to file a bug upstream and if they can't fix it or don't want to fix it, I'd try no. 4 next.

stale[bot] commented 3 years ago

I marked this as stale due to inactivity. → More info

Jiehong commented 2 years ago

Opened upstream: https://forums.factorio.com/viewtopic.php?f=7&t=102351&p=570484#p570484

9p4 commented 11 months ago

I have a marginally better hacky workaround. This mounts a filesystem that does not follow Unix permissions (Fat32) and uses that for the temp directory.

#!/usr/bin/env bash

set -e

FACTORIO_CONFIG="$HOME/.factorio"

AUTH_PROGRAM=sudo # Replace with pkexec if you want

img_path="$FACTORIO_CONFIG/temp.img"

if [ ! -f "$img_path" ]; then
    dd if=/dev/zero of="$img_path" bs=4M count=16
    mkfs.fat -F32 "$img_path"
fi

loop_dev=$($AUTH_PROGRAM losetup -f)

$AUTH_PROGRAM losetup $loop_dev "$img_path"

if [ -d "$FACTORIO_CONFIG/temp" ]; then
    rmdir "$FACTORIO_CONFIG/temp"
fi

mkdir "$FACTORIO_CONFIG/temp"

$AUTH_PROGRAM mount $loop_dev "$FACTORIO_CONFIG/temp" -o uid=$(id -u) -o gid=$(id -g)

factorio || true

$AUTH_PROGRAM umount $loop_dev
$AUTH_PROGRAM losetup -d $loop_dev
AleXoundOS commented 10 months ago

Maybe LD_PRELOAD the file copy function to restore the writable flag for each file/directory, copied from /nix/store...

AleXoundOS commented 8 months ago

Another variant might be to run a bash script with inotifywait in parallel. inotifywait will wait till new file creation event to trigger chmod.

9p4 commented 8 months ago

I did put together an inotify based bash script (and also a version in C) but it didn't activate fast enough before factorio errored out. factorio_chowner.c