process handles the file named path in srcFs, decrypting it into dstFs unless dstFs is nil.
(srcFs fs.Filesystem, dstFs fs.Filesystem, path string)
| 134 | // process handles the file named path in srcFs, decrypting it into dstFs |
| 135 | // unless dstFs is nil. |
| 136 | func (c *CLI) process(srcFs fs.Filesystem, dstFs fs.Filesystem, path string) error { |
| 137 | // Which filemode bits to preserve |
| 138 | const retainBits = fs.ModePerm | fs.ModeSetgid | fs.ModeSetuid | fs.ModeSticky |
| 139 | |
| 140 | if c.Verbose { |
| 141 | log.Printf("Processing %q", path) |
| 142 | } |
| 143 | |
| 144 | encFd, err := srcFs.Open(path) |
| 145 | if err != nil { |
| 146 | return err |
| 147 | } |
| 148 | defer encFd.Close() |
| 149 | |
| 150 | encFi, err := loadEncryptedFileInfo(encFd) |
| 151 | if err != nil { |
| 152 | return fmt.Errorf("%s: loading metadata trailer: %w", path, err) |
| 153 | } |
| 154 | |
| 155 | // Workaround for a bug in <= v1.15.0-rc.5 where we stored names |
| 156 | // in native format, while protocol expects wire format (slashes). |
| 157 | encFi.Name = osutil.NormalizedFilename(encFi.Name) |
| 158 | |
| 159 | plainFi, err := protocol.DecryptFileInfo(c.keyGen, *encFi, c.folderKey) |
| 160 | if err != nil { |
| 161 | return fmt.Errorf("%s: decrypting metadata: %w", path, err) |
| 162 | } |
| 163 | |
| 164 | if c.Verbose { |
| 165 | log.Printf("Plaintext filename is %q", plainFi.Name) |
| 166 | } |
| 167 | |
| 168 | var plainFd fs.File |
| 169 | if dstFs != nil { |
| 170 | if err := dstFs.MkdirAll(filepath.Dir(plainFi.Name), 0o700); err != nil { |
| 171 | return fmt.Errorf("%s: %w", plainFi.Name, err) |
| 172 | } |
| 173 | |
| 174 | plainFd, err = dstFs.Create(plainFi.Name) |
| 175 | if err != nil { |
| 176 | return fmt.Errorf("%s: %w", plainFi.Name, err) |
| 177 | } |
| 178 | defer plainFd.Close() // also closed explicitly in the return |
| 179 | if err := dstFs.Chmod(plainFi.Name, fs.FileMode(plainFi.Permissions&uint32(retainBits))); err != nil { |
| 180 | return fmt.Errorf("%s: %w", plainFi.Name, err) |
| 181 | } |
| 182 | } |
| 183 | |
| 184 | if err := c.decryptFile(encFi, &plainFi, encFd, plainFd); err != nil { |
| 185 | // Decrypting the file failed, leaving it in an inconsistent state. |
| 186 | // Delete it. Even --continue currently doesn't mean "leave broken |
| 187 | // stuff in place", it just means "try the next file instead of |
| 188 | // aborting". |
| 189 | if plainFd != nil { |
| 190 | _ = dstFs.Remove(plainFd.Name()) |
| 191 | } |
| 192 | return fmt.Errorf("%s: %s: %w", path, plainFi.Name, err) |
| 193 | } else if c.Verbose { |
no test coverage detected