Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Folders with custom icons not deletable on Windows #3744

Closed
meztup opened this issue Nov 19, 2016 · 30 comments
Closed

Folders with custom icons not deletable on Windows #3744

meztup opened this issue Nov 19, 2016 · 30 comments
Labels
bug A problem with current functionality, as opposed to missing functionality (enhancement) frozen-due-to-age Issues closed and untouched for a long time, together with being locked for discussion
Milestone

Comments

@meztup
Copy link

meztup commented Nov 19, 2016

Syncing a folder with the read-only attribute set between Windows clients works as expected. However, when deleting the folder on one client, the other goes "Out of Sync" in the GUI with "access denied" in the Syncthing console.

The folder must then be manually deleted on the second machine (using explorer or "attrib" and "del" commands in the console.)

This seems similar to Issue #1610 only with folders rather than files.

Note: Windows sets the read-only attribute on folders automatically when you set a custom icon for said folder--that's how I initially discovered the issue. However, manually creating a read-only folder results in exactly the same behavior from Syncthing.

Syncthing Version: v0.14.11
OS Version: Windows 7

@canton7
Copy link
Member

canton7 commented Nov 19, 2016

So, "Read-only folders are read-only"?

@AudriusButkevicius AudriusButkevicius added the bug A problem with current functionality, as opposed to missing functionality (enhancement) label Nov 19, 2016
@AudriusButkevicius AudriusButkevicius added this to the Unplanned (Contributions Welcome) milestone Nov 19, 2016
@calmh
Copy link
Member

calmh commented Nov 19, 2016

This surprises me as we have a test that verifies that we can remove read only directories in read only directories on Windows:

https://github.com/syncthing/syncthing/blob/master/lib/osutil/osutil_test.go#L99

and we actually appear to be using that code to remove directories from the puller:

https://github.com/syncthing/syncthing/blob/master/lib/model/rwfolder.go#L696

although not, for example, for removing stale tempfiles in it first so there is some inconsistency we should clean up...

Is this generally reproducible by Windows folks?

@meztup
Copy link
Author

meztup commented Nov 19, 2016

Maybe os.remove should be osutil.remove?

@AudriusButkevicius
Copy link
Member

We should replace it everywhere, yes.

@meztup
Copy link
Author

meztup commented Nov 19, 2016

Oops.

osutil.remove was removed back in August (18cc7a6) because Go had apparently fixed os.remove

EDIT:
I just went back and tested Syncthing v0.14.4 from August 10th (release prior to the above changes) and it worked perfectly.

Also, it looks like the test might be relying on an error occurring -- perhaps os.remove itself is failing silently.

@calmh calmh changed the title Read-only folders not deletable on Windows lib/osutil: Read-only folders not deletable on Windows Nov 23, 2016
@calmh
Copy link
Member

calmh commented Mar 24, 2017

There's something else going on here beyond the read only bit. Read only directories can be deleted just fine. I tried to make a test for this, but if I create a read only folder, either from code or by creating it in Explorer and setting the read only bit:

screen shot 2017-03-23 at 21 08 39

it deletes just fine by our normal procedure. But setting a custom icon does something else. Note the "1 file" supposedly in the directory now:

screen shot 2017-03-23 at 21 07 32

That file isn't visible in cmd nor Explorer, but deleting the directory now indeed returns access denied. Maybe we manage to sync this custom icon anyway and this screws up the following delete.

Needs someone who likes getting involved in Windows internals, which is not me beyond this point. :)

@calmh calmh changed the title lib/osutil: Read-only folders not deletable on Windows Folders with custom icons not deletable on Windows Mar 24, 2017
@AudriusButkevicius
Copy link
Member

I think there should be a folder.jpg that's not visible in there.

@calmh
Copy link
Member

calmh commented Mar 24, 2017

Yeah I guess the only odd thing is the "access denied" vs the more reasonable "not empty" then. But this issue seems much more niche than I initially thought, and I'm leaving it for someone who cares more to figure out. :)

@wweich
Copy link
Member

wweich commented Mar 24, 2017

Setting a custom icon will create a hidden desktop.ini file. You can see it with dir /a or by unchecking "hide system files" in the Windows Explorer settings.
Deleting that file will unlock the folder.

@Ferroin
Copy link

Ferroin commented Mar 24, 2017

Expanding on what @wweich said: Properties like custom icons get put into a file called desktop.ini that has the 'system' attribute bit set, which means that it is hidden unless you have the 'Hide Protected Operating System Files' option disabled in your Folder Settings. The file itself is essentially equivalent to an OS X resource fork for a directory. It originated back when Windows still used FAT as the default filesystem (and thus didn't have alternative data streams to stuff the data in), and has stuck around because Microsoft are too lazy and obsessed with making ancient software continue working to update it to do things right.

Deletion of folders with this file in it works from the Windows file manager because it checks for this file and deletes it before deleting the folder if there is nothing else in the folder. Syncthing should probably do the same.

@meztup
Copy link
Author

meztup commented Mar 24, 2017

@calmh Setting the attribute using the properties dialog only makes the files within the folder read-only. The folder itself is still just a regular folder. Creating a custom icon changes the attibute of the actual folder. Try using attrib from the command-line to create a "real" read-only folder.

@wweich
Copy link
Member

wweich commented Mar 25, 2017

Deletion of folders with this file in it works from the Windows file manager because it checks for this file and deletes it before deleting the folder if there is nothing else in the folder.

Actually, I couldn't delete the folder with custom icon in Windows Explorer until I remove the desktop.ini file manually.

@AudriusButkevicius
Copy link
Member

I tried os.RemoveAll, which deletes the desktop.ini, but the folder is still not deletable.
I think we should raise this as a bug in the standard library.

@calmh calmh removed this from the Unplanned (Contributions Welcome) milestone Feb 11, 2018
@Nnnes
Copy link

Nnnes commented Jul 9, 2018

Since nobody else seems to have submitted this as a Go issue yet: golang/go#26295

@TigersWay
Copy link

Sorry to bump this old unsolved issue, but ...
Read-only folders simply do not exist on Windows. The attribute exists but has nothing to do with reading only, but stating the fact - on Windows only - that these folders are special/customized.

It seems just plain wrong then to sync that attribute or its changes (from Windows only again)!

@calmh
Copy link
Member

calmh commented Oct 30, 2018

We don't and that's not the problem here.

I also suspect the standard library fix (linked from the issue above) misses the point as it just does a chmod of the directory before remove, which as far as I remember does not solve this problem with the custom icon.

@Nnnes
Copy link

Nnnes commented Mar 10, 2020

@calmh Now that Go 1.14 is out, I can confirm you are correct that the standard library fix does not solve the problem for Syncthing. But why not?

I have an otherwise empty test folder with a custom icon C:\sync\test_folder_with_icon. When synced to a Windows machine that is running Syncthing built with Go 1.14 (syncthing v1.4.0-rc.11+38-g20aaa592 "Fermium Flea" (go1.14 windows-amd64)) and then deleted on the original machine, Syncthing fails to delete the folder, just as before. However, I can successfully delete the very same folder (regardless of whether or not the desktop.ini has already been deleted) using a simple Go program built with Go 1.14:

package main

import (
	"os"
)

func main() {
	err := os.RemoveAll("C:/sync/test_folder_with_icon")
	if err != nil {
		panic(err)
	}
}

My Go knowledge is limited. What is the difference between what Syncthing does and what the short program above does? It seems to me that Syncthing uses os.RemoveAll() to delete directories.

@AudriusButkevicius
Copy link
Member

We do Remove, not RemoveAll, as RemoveAll would delete ignored files, hence we rely on Remove to tell us that the directory is not empty and preventing us from deleting it.

@calmh
Copy link
Member

calmh commented Mar 11, 2020

func (f *sendReceiveFolder) deleteDirOnDisk(dir string, snap *db.Snapshot, scanChan chan<- string) error {

@john8329
Copy link

john8329 commented Dec 20, 2020

Hopefully it's not an issue to add details to a months old discussion, but I'm having a similar problem. I'm using Google Drive to sync my folder to a windows machine, and Syncthing to "bridge" the syncing to other workstations. Google drive puts custom icons on every folder synchronised, and I'm having frequent issues described by "Access is denied."

The files and folders have "everyone" set to full control, so it's not a permission thing. Oddly if I delete the folders and restore them, they stop being a problem, but that has to be manual. I'm still researching this, but it appears to happen systematically with this setup:

  • Windows machine with syncthing and google drive, syncthing reads and writes to the google drive folder (ignoring and deleting .DS_Store and desktop.ini). Permissions are ignored for sync
  • macOS machine with just syncthing, adding a .mindnode bundle (which is a folder with other folders) makes it sync correctly (it's added to a google drive SHARED folder, so it adds the icons at windows side)
  • when removing the bundle, it fails to delete it at the windows side, giving "Access is denied." errors on every folder contained by it, files are removed
  • If I delete the folders manually everything's okay

Hope it could help reproducing what I think is a quite nasty bug. It doesn't seem to happen outside Drive, but I presume it's linked to the custom icons, when Drive isn't syncing the issue doesn't arise.

Screenshot 2020-12-20 at 12 25 34

I can confirm the problem is 100% reproducible on demand.

@djjaeger82
Copy link

Hopefully it's not an issue to add details to a months old discussion, but I'm having a similar problem. I'm using Google Drive to sync my folder to a windows machine, and Syncthing to "bridge" the syncing to other workstations. Google drive puts custom icons on every folder synchronised, and I'm having frequent issues described by "Access is denied."

I'm having this exact same issue. My mother has a desktop and a laptop she uses in her house. I use syncthings to sync files between the two machines locally. And then on the desktop I also backup the same folders to google drive. I am constantly getting this access denied error, I believe due to the google drive and custom icons it imposes. If I uninstall google drive then all of a sudden syncthings can do its job without issue.

Has there been any fix to this problem? Any workaround? Please help. I want to have local sync + cloud backup both.

@calmh
Copy link
Member

calmh commented Sep 5, 2022

I haven't tried but maybe an ignore pattern like (?d)desktop.ini would work (ignore desktop.ini and remove it if it's in the way of directory deletion).

@AlexandreAlvesDB
Copy link
Contributor

AlexandreAlvesDB commented Nov 6, 2022

As stated in Go repository : golang/go#26295

RemoveAll should be used instead of Remove for windows directories because Go returns an error in one case and not in the other when removing the same directory because of this issue with "custom" folders

Also preventing with an ignore desktop.ini does not work.

Example :

if err := f.mtimefs.Remove(dirsToDelete[len(dirsToDelete)-1-i]); err != nil && delErr == nil {
Changing it to RemoveAll should fix this long-standing issue for send and receive folders

Most of the tests I saw in the syncthing repo are done with RemoveAll instead of Remove but most of the code used in production uses Remove

@calmh
Copy link
Member

calmh commented Nov 6, 2022

We should look at what RemoveAll does under the hood to handle this and adopt the relevant parts. (We want the remove to fail if there are unexpected items in the directory, as a safety measure, so we can't just start using RemoveAll everywhere.)

@AlexandreAlvesDB
Copy link
Contributor

I opened a pull request on Go repository to patch Remove : golang/go#56615
So I guess you will not need to modify the code to fix the issue when the patch will get in a public release

@calmh
Copy link
Member

calmh commented Nov 6, 2022

The "read only" part is a red herring, your chmod will do nothing to enable the removal of that directory. Removing desktop.ini should resolve it, but if I remember correctly the next level of problem is that the desktop.ini file isn't visible to us or isn't removable of a combination of the two. (If it were visible, the suggested (?d)desktop.ini pattern would work, because that means "delete that file before deleting the directory".)

@AlexandreAlvesDB
Copy link
Contributor

AlexandreAlvesDB commented Nov 6, 2022

If it really is a red herring as you think, you have to use RemoveAll as my first proposition to remove the desktop.ini and the folder
If the bug was still open, it was for a reason, you have probably not read the thread but even without desktop.ini, os.Remove in Golang doesn't work for folder who had an icon, that's why I proposed the patch

@calmh calmh closed this as completed in a296057 Nov 7, 2022
calmh added a commit to imsodin/syncthing that referenced this issue Nov 8, 2022
* main: (36 commits)
  lib/protocol: Ignore inode time when xattr&ownership is ignored (fixes syncthing#8654) (syncthing#8655)
  lib/fs: Try to remove read only Windows files (fixes syncthing#3744) (syncthing#8650)
  gui: Add copy to clipboard, share by email, and share by SMS buttons to device IDs (fixes syncthing#2771, ref syncthing#3868) (syncthing#7984)
  gui, man, authors: Update docs, translations, and contributors
  build: Add GitHub actions build for Windows (syncthing#8627)
  gui: Fix connection type icon width (fixes syncthing#8592) (syncthing#8644)
  gui: Adjust connection type icon size scaling and alignment (syncthing#8645)
  docker: Use healthcheck endpoint (syncthing#8640)
  lib/connections: Use adaptive write size for rate limited connections (fixes syncthing#8630) (syncthing#8631)
  gui: Mark devices that haven't connected for a long time (fixes syncthing#7703) (syncthing#8530)
  gui: Fix rescan interval when add encrypted folder with watch for changes enabled (fixes syncthing#8570) (syncthing#8571)
  gui: Always show Out of Sync Items for remote devices (syncthing#8632)
  lib/fs: Let xattr test avoid non-test attributes (fixes syncthing#8601) (syncthing#8628)
  build: Add GitHub actions build for Windows
  gui, man, authors: Update docs, translations, and contributors
  gui: Display folder and device count number (syncthing#8615)
  gui, man, authors: Update docs, translations, and contributors
  lib/model, lib/protocol: Fix file comparisons (fixes syncthing#8594) (syncthing#8603)
  lib/scanner: More sensible debug output (syncthing#8596)
  gui: Allow automatic device ID selection on WebKit browsers (ref syncthing#8544) (syncthing#8597)
  ...
@calmh calmh added this to the v1.22.2 milestone Nov 9, 2022
calmh added a commit to calmh/syncthing that referenced this issue Nov 22, 2022
* main: (23 commits)
  lib/fs: Optimize WindowsInvalidFilename (syncthing#8687)
  gui, man, authors: Update docs, translations, and contributors
  cmd/syncthing: Use main logger in generate subcommand (fixes syncthing#8682) (syncthing#8685)
  build: Update all dependencies (fixes syncthing#8679) (syncthing#8680)
  gui, man, authors: Update docs, translations, and contributors
  lib/model: Correctly set xattrs on temp files (fixes syncthing#8667) (syncthing#8670)
  gui: Automatically dismiss authentication reminder when in LDAP mode (fixes syncthing#8661) (syncthing#8663)
  lib/model: Correctly handle xattrs on directories (fixes syncthing#8657) (syncthing#8658)
  lib/protocol: Ignore inode time when xattr&ownership is ignored (fixes syncthing#8654) (syncthing#8655)
  lib/fs: Try to remove read only Windows files (fixes syncthing#3744) (syncthing#8650)
  gui: Add copy to clipboard, share by email, and share by SMS buttons to device IDs (fixes syncthing#2771, ref syncthing#3868) (syncthing#7984)
  gui, man, authors: Update docs, translations, and contributors
  build: Add GitHub actions build for Windows (syncthing#8627)
  gui: Fix connection type icon width (fixes syncthing#8592) (syncthing#8644)
  gui: Adjust connection type icon size scaling and alignment (syncthing#8645)
  docker: Use healthcheck endpoint (syncthing#8640)
  lib/connections: Use adaptive write size for rate limited connections (fixes syncthing#8630) (syncthing#8631)
  gui: Mark devices that haven't connected for a long time (fixes syncthing#7703) (syncthing#8530)
  gui: Fix rescan interval when add encrypted folder with watch for changes enabled (fixes syncthing#8570) (syncthing#8571)
  gui: Always show Out of Sync Items for remote devices (syncthing#8632)
  ...
@AlexandreAlvesDB
Copy link
Contributor

Hello, I've seen my code added to the repo but I've not been added to the Authors file

calmh added a commit to calmh/syncthing that referenced this issue Dec 7, 2022
The authorship script didn't pick up people who were only ever
"co-authors" of a commit, such as when they wrote stuff which was later
included in a PR by someone else, or added code during code review.

This modified the script to look closer in the commit bodies for
"Co-authored-by:"-lines and adds those found to the set of authors.
@calmh
Copy link
Member

calmh commented Dec 7, 2022

@AlexandreAlvesDB sorry about that, the script I was hoping to pick that up wasn't smart enough, I've fixed it in the PR above.

@AlexandreAlvesDB
Copy link
Contributor

@AlexandreAlvesDB sorry about that, the script I was hoping to pick that up wasn't smart enough, I've fixed it in the PR above.

No problem :)

calmh added a commit that referenced this issue Dec 21, 2022
The authorship script didn't pick up people who were only ever
"co-authors" of a commit, such as when they wrote stuff which was later
included in a PR by someone else, or added code during code review.

This modified the script to look closer in the commit bodies for
"Co-authored-by:"-lines and adds those found to the set of authors.
calmh added a commit to calmh/syncthing that referenced this issue Jan 23, 2023
* main: (69 commits)
  Handle relay connect timeout (fixes syncthing#8749) (syncthing#8755)
  gui, man, authors: Update docs, translations, and contributors
  build: Go 1.19.5
  gui, man, authors: Update docs, translations, and contributors
  script: Add weblatedl.go for downloading updated translations (syncthing#8723)
  gui: Allow to translate action and type in Recent Changes modal (syncthing#8548)
  gui, man, authors: Update docs, translations, and contributors
  gui: Fix undefined lastSeenDays error in disconnected-inactive status check (ref syncthing#8530) (syncthing#8730)
  gui, man, authors: Update docs, translations, and contributors
  gui, api: Indicate running under container (syncthing#8728)
  lib/fs: Use io/fs errors as recommended in std lib (syncthing#8726)
  build: Handle co-authors (ref syncthing#3744) (syncthing#8708)
  lib/fs: Watching is unsupported on android/amd64 (fixes syncthing#8709) (syncthing#8710)
  lib/model: Only log at info level if setting change time fails (syncthing#8725)
  lib/model: Don't lower rescan interval from default on auto accepted enc folder (fixes syncthing#8572) (syncthing#8573)
  gui, man, authors: Update docs, translations, and contributors
  gui: Remove unmaintained language variant nl-BE (syncthing#8722)
  gui, script: Fix indentation in lang-en.json to match others (syncthing#8721)
  docker: Ensure entrypoint is executable (syncthing#8719)
  Go 1.19.4
  ...
@st-review st-review added the frozen-due-to-age Issues closed and untouched for a long time, together with being locked for discussion label Nov 8, 2023
@syncthing syncthing locked and limited conversation to collaborators Nov 8, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug A problem with current functionality, as opposed to missing functionality (enhancement) frozen-due-to-age Issues closed and untouched for a long time, together with being locked for discussion
Projects
None yet
Development

No branches or pull requests