davidgohel / officer

:cop: officer: office documents from R
https://ardata-fr.github.io/officeverse/
Other
592 stars 106 forks source link

Saving files fails if officer is installed read-only #549

Closed alexvorobiev closed 7 months ago

alexvorobiev commented 7 months ago

These lines in read_docx: https://github.com/davidgohel/officer/blob/bfedc496c01fd5d6f4ed349959f84625bf29e43a/R/read_docx.R#L97 https://github.com/davidgohel/officer/blob/bfedc496c01fd5d6f4ed349959f84625bf29e43a/R/read_docx.R#L113 copy the respective files from the package's installation directory and then modify them before saving the output, so if Officer is installed read-only, the saving fails:

library(officer)

d <- read_docx()
d <- body_add_par(d, 'title')
print(d, target = 'test.docx')
> print(d, target = 'test.docx')
Error in write_xml.xml_document(private$doc, file = private$filename) : 
  Error closing file
In addition: Warning messages:
1: In write_xml.xml_document(private$doc, file = private$filename) :
  Permission denie [1501]
2: In write_xml.xml_document(private$doc, file = private$filename) :
  Permission denie [1501]

One solution would be to add copy.mode = FALSE to the file.copy calls, so that the file mode attributes are not preserved.

In enterprise settings it is not uncommon to have a centralized library of packages where everything is installed read-only and maintained by designated users/teams. Another use case which is quickly gaining popularity is using Nix package manager for maintaining data science environments. Nix also installs everything read-only.

davidgohel commented 7 months ago

I am not able to reproduce and it's been years that I am using it in enterprise context, so I am a little suspicious :)

where everything is installed read-only

This is from a docker on my machine - packages are in /opt/R/4.3.2/lib/R/library own by root:

Capture d’écran 2024-02-03 à 09 39 06

I can run your example with shiny user (I just had this machine ready so I used it with shiny user)

shiny@ddf0f64eef52:~$ R

R version 4.3.2 (2023-10-31) -- "Eye Holes"
Copyright (C) 2023 The R Foundation for Statistical Computing
Platform: x86_64-pc-linux-gnu (64-bit)

R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.

  Natural language support but running in an English locale

R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.

Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.

> library(officer)
ar(d, 'title')
print(d, target = 'test.docx')> 
> d <- read_docx()
> d <- body_add_par(d, 'title')
> print(d, target = 'test.docx')
> getwd()
[1] "/home/shiny"
> file.info(system.file(package = "officer"))
                                   size isdir mode               mtime
/opt/R/4.3.2/lib/R/library/officer 4096  TRUE  755 2024-02-03 08:35:11
                                                 ctime               atime uid
/opt/R/4.3.2/lib/R/library/officer 2024-02-03 08:35:43 2024-02-03 08:35:58   0
                                   gid uname grname
/opt/R/4.3.2/lib/R/library/officer   0  root   root

I think instead the issue is in your system where you set tempdir() as read only. https://github.com/davidgohel/officer/blob/bfedc496c01fd5d6f4ed349959f84625bf29e43a/R/read_docx.R#L66

alexvorobiev commented 7 months ago

The crucial part in your case is that you have the write permission for the owner of the files, so that bit will be carried over when the files are copied (by default copy.mode is T, so it preserves all the permission bits). Depending on how the centralized library is deployed it could be not the case. For instance, the "Nix store" (the immutable (subject only to garbage collection) storage for all the packaged Nix manages) doesn't have the "w" bit set even for the owner. Actually, the problem is even documented on the official Nix wiki https://nixos.wiki/wiki/R (scroll all the way down), I just decided to step through the execution in the debugger to see what is going on. Try removing the w bit on the two template xml files in the directory where the package is installed and you will get the behavior I described.

❯ ls -l /nix/store/*-r-officer-*/library/officer
total 72
-r--r--r-- 1 root root  3436 Dec 31  1969 DESCRIPTION
dr-xr-xr-x 2 root root  4096 Dec 31  1969 doc_examples
dr-xr-xr-x 3 root root  4096 Dec 31  1969 help
dr-xr-xr-x 2 root root  4096 Dec 31  1969 html
-r--r--r-- 1 root root  6549 Dec 31  1969 INDEX
-r--r--r-- 1 root root    36 Dec 31  1969 LICENSE
dr-xr-xr-x 2 root root  4096 Dec 31  1969 Meta
-r--r--r-- 1 root root  9061 Dec 31  1969 NAMESPACE
-r--r--r-- 1 root root 18837 Dec 31  1969 NEWS.md
dr-xr-xr-x 2 root root  4096 Dec 31  1969 R
dr-xr-xr-x 2 root root  4096 Dec 31  1969 template
❯ ls -ld /nix/store/*-r-officer-*/library/officer
dr-xr-xr-x 8 root root 4096 Dec 31  1969 /nix/store/ci1v4gcwhx9mwnshqxab7pb0d8vs6cn5-r-officer-0.6.3/library/officer
davidgohel commented 7 months ago

OK, I did the requested changes, is it possible for you to test?

alexvorobiev commented 7 months ago

It looks like the problem is fixed!

The current CRAN version (with the issue):

❯ nix-shell -p R -p rPackages.officer --run 'Rscript -e "library(officer); d <- read_docx(); d <- body_add_par(d, \"title\"); print(d, target = \"~/test.docx\")"'
Error in write_xml.xml_document(private$doc, file = private$filename) : 
  Error closing file
Calls: print ... print.rdocx -> <Anonymous> -> write_xml -> write_xml.xml_document
In addition: Warning messages:
1: In write_xml.xml_document(private$doc, file = private$filename) :
  Permission denie [1501]
2: In write_xml.xml_document(private$doc, file = private$filename) :
  Permission denie [1501]
Execution halted

The latest Github commit:

❯ nix-shell -p R -p '(rPackages.officer.overrideAttrs (_: {src = (fetchTarball "https://github.com/davidgohel/officer/archive/dbb27faa10e6a520092716748992d69271bf3c94.tar.gz");}))' --run 'Rscript -e "library(officer); d <- read_docx(); d <- body_add_par(d, \"title\"); print(d, target = \"~/test.docx\"); system(\"ls -l ~/test.docx\")"'
-rw-r--r-- 1 alex users 12567 Feb  5 12:50 /home/alex/test.docx

Thank you!

davidgohel commented 7 months ago

cool, thank you for taking the time to test it

github-actions[bot] commented 1 month ago

This old thread has been automatically locked. If you think you have found something related to this, please open a new issue and link to this old issue if necessary.