(ctx context.Context, file model.Obj, _ model.LinkArgs)
| 235 | const fileHeaderSize = 32 |
| 236 | |
| 237 | func (d *Crypt) Link(ctx context.Context, file model.Obj, _ model.LinkArgs) (*model.Link, error) { |
| 238 | remoteStorage, remoteActualPath, err := op.GetStorageAndActualPath(file.GetPath()) |
| 239 | if err != nil { |
| 240 | return nil, err |
| 241 | } |
| 242 | remoteLink, remoteFile, err := op.Link(ctx, remoteStorage, remoteActualPath, model.LinkArgs{}) |
| 243 | if err != nil { |
| 244 | return nil, err |
| 245 | } |
| 246 | |
| 247 | remoteSize := remoteLink.ContentLength |
| 248 | if remoteSize <= 0 { |
| 249 | remoteSize = remoteFile.GetSize() |
| 250 | } |
| 251 | rrf, err := stream.GetRangeReaderFromLink(remoteSize, remoteLink) |
| 252 | if err != nil { |
| 253 | _ = remoteLink.Close() |
| 254 | return nil, fmt.Errorf("the remote storage driver need to be enhanced to support encrytion") |
| 255 | } |
| 256 | |
| 257 | mu := &sync.Mutex{} |
| 258 | var fileHeader []byte |
| 259 | rangeReaderFunc := func(ctx context.Context, offset, limit int64) (io.ReadCloser, error) { |
| 260 | length := limit |
| 261 | if offset == 0 && limit > 0 { |
| 262 | mu.Lock() |
| 263 | if limit <= fileHeaderSize { |
| 264 | defer mu.Unlock() |
| 265 | if fileHeader != nil { |
| 266 | return io.NopCloser(bytes.NewReader(fileHeader[:limit])), nil |
| 267 | } |
| 268 | length = fileHeaderSize |
| 269 | } else if fileHeader == nil { |
| 270 | defer mu.Unlock() |
| 271 | } else { |
| 272 | mu.Unlock() |
| 273 | } |
| 274 | } |
| 275 | |
| 276 | remoteReader, err := rrf.RangeRead(ctx, http_range.Range{Start: offset, Length: length}) |
| 277 | if err != nil { |
| 278 | return nil, err |
| 279 | } |
| 280 | |
| 281 | if offset == 0 && limit > 0 { |
| 282 | fileHeader = make([]byte, fileHeaderSize) |
| 283 | n, err := io.ReadFull(remoteReader, fileHeader) |
| 284 | if n != fileHeaderSize { |
| 285 | fileHeader = nil |
| 286 | return nil, fmt.Errorf("failed to read all data: (expect =%d, actual =%d) %w", fileHeaderSize, n, err) |
| 287 | } |
| 288 | if limit <= fileHeaderSize { |
| 289 | remoteReader.Close() |
| 290 | return io.NopCloser(bytes.NewReader(fileHeader[:limit])), nil |
| 291 | } else { |
| 292 | remoteReader = utils.ReadCloser{ |
| 293 | Reader: io.MultiReader(bytes.NewReader(fileHeader), remoteReader), |
| 294 | Closer: remoteReader, |
nothing calls this directly
no test coverage detected