Skip to content

Commit

Permalink
cmd/sync: check the destination of the symbolic link
Browse files Browse the repository at this point in the history
  • Loading branch information
zhijian-pro committed Oct 7, 2023
1 parent 5bf6136 commit 63ee5a8
Show file tree
Hide file tree
Showing 36 changed files with 180 additions and 73 deletions.
23 changes: 15 additions & 8 deletions cmd/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,9 @@ func (j *juiceFS) Delete(key string) error {
}

type jObj struct {
key string
fi *fs.FileStat
key string
fi *fs.FileStat
linkPath string
}

func (o *jObj) Key() string { return o.key }
Expand All @@ -188,6 +189,7 @@ func (o *jObj) Owner() string { return utils.UserName(o.fi.Uid()) }
func (o *jObj) Group() string { return utils.GroupName(o.fi.Gid()) }
func (o *jObj) Mode() os.FileMode { return o.fi.Mode() }
func (o *jObj) StorageClass() string { return "" }
func (o *jObj) LinkPath() string { return o.linkPath }

func (j *juiceFS) Head(key string) (object.Object, error) {
fi, eno := j.jfs.Stat(ctx, j.path(key))
Expand All @@ -197,7 +199,7 @@ func (j *juiceFS) Head(key string) (object.Object, error) {
if eno != 0 {
return nil, eno
}
return &jObj{key, fi}, nil
return &jObj{key, fi, ""}, nil
}

func (j *juiceFS) List(prefix, marker, delimiter string, limit int64, followLink bool) ([]object.Object, error) {
Expand Down Expand Up @@ -233,7 +235,7 @@ func (j *juiceFS) List(prefix, marker, delimiter string, limit int64, followLink
if !strings.HasPrefix(key, prefix) || (marker != "" && key <= marker) {
continue
}
f := &jObj{key, e.fi}
f := &jObj{key, e.fi, e.linkPath}
objs = append(objs, f)
if len(objs) == int(limit) {
break
Expand All @@ -246,6 +248,7 @@ type mEntry struct {
fi *fs.FileStat
name string
isSymlink bool
linkPath string
}

// readDirSorted reads the directory named by dirname and returns
Expand All @@ -263,21 +266,25 @@ func (j *juiceFS) readDirSorted(dirname string, followLink bool) ([]*mEntry, sys
mEntries := make([]*mEntry, len(entries))
for i, e := range entries {
fi := fs.AttrToFileInfo(e.Inode, e.Attr)
var linkPath []byte
if fi.IsSymlink() {
linkPath, _ = j.jfs.Readlink(ctx, filepath.Join(dirname, string(e.Name)))
}
if fi.IsDir() {
mEntries[i] = &mEntry{fi, string(e.Name) + dirSuffix, false}
mEntries[i] = &mEntry{fi, string(e.Name) + dirSuffix, false, ""}
} else if fi.IsSymlink() && followLink {
fi2, err := j.jfs.Stat(ctx, filepath.Join(dirname, string(e.Name)))
if err != 0 {
mEntries[i] = &mEntry{fi, string(e.Name), true}
mEntries[i] = &mEntry{fi, string(e.Name), true, string(linkPath)}
continue
}
name := string(e.Name)
if fi2.IsDir() {
name += dirSuffix
}
mEntries[i] = &mEntry{fi2, name, false}
mEntries[i] = &mEntry{fi2, name, false, string(linkPath)}
} else {
mEntries[i] = &mEntry{fi, string(e.Name), fi.IsSymlink()}
mEntries[i] = &mEntry{fi, string(e.Name), fi.IsSymlink(), string(linkPath)}
}
}
sort.Slice(mEntries, func(i, j int) bool { return mEntries[i].name < mEntries[j].name })
Expand Down
2 changes: 2 additions & 0 deletions pkg/object/azure.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ func (b *wasb) Head(key string) (Object, error) {
*properties.LastModified,
strings.HasSuffix(key, "/"),
*properties.AccessTier,
"",
}, nil
}

Expand Down Expand Up @@ -171,6 +172,7 @@ func (b *wasb) List(prefix, marker, delimiter string, limit int64, followLink bo
*mtime,
strings.HasSuffix(*blob.Name, "/"),
string(*blob.Properties.AccessTier),
"",
}
}
return objs, nil
Expand Down
2 changes: 2 additions & 0 deletions pkg/object/b2.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ func (c *b2client) Head(key string) (Object, error) {
time.Unix(f.UploadTimestamp/1000, 0),
strings.HasSuffix(f.Name, "/"),
"",
"",
}, nil
}

Expand Down Expand Up @@ -145,6 +146,7 @@ func (c *b2client) List(prefix, marker, delimiter string, limit int64, followLin
time.Unix(f.UploadTimestamp/1000, 0),
strings.HasSuffix(f.Name, "/"),
"",
"",
}
}
c.nextMarker = resp.NextFileName
Expand Down
5 changes: 3 additions & 2 deletions pkg/object/bos.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ func (q *bosclient) Head(key string) (Object, error) {
mtime,
strings.HasSuffix(key, "/"),
r.StorageClass,
"",
}, nil
}

Expand Down Expand Up @@ -152,11 +153,11 @@ func (q *bosclient) List(prefix, marker, delimiter string, limit int64, followLi
for i := 0; i < n; i++ {
k := out.Contents[i]
mod, _ := time.Parse("2006-01-02T15:04:05Z", k.LastModified)
objs[i] = &obj{k.Key, int64(k.Size), mod, strings.HasSuffix(k.Key, "/"), k.StorageClass}
objs[i] = &obj{k.Key, int64(k.Size), mod, strings.HasSuffix(k.Key, "/"), k.StorageClass, ""}
}
if delimiter != "" {
for _, p := range out.CommonPrefixes {
objs = append(objs, &obj{p.Prefix, 0, time.Unix(0, 0), true, ""})
objs = append(objs, &obj{p.Prefix, 0, time.Unix(0, 0), true, "", ""})
}
sort.Slice(objs, func(i, j int) bool { return objs[i].Key() < objs[j].Key() })
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/object/ceph.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ func (c *ceph) Head(key string) (Object, error) {
if err != nil {
return err
}
o = &obj{key, int64(stat.Size), stat.ModTime, strings.HasSuffix(key, "/"), ""}
o = &obj{key, int64(stat.Size), stat.ModTime, strings.HasSuffix(key, "/"), "", ""}
return nil
})
if err == rados.ErrNotFound {
Expand Down Expand Up @@ -238,7 +238,7 @@ func (c *ceph) ListAll(prefix, marker string, followLink bool) (<-chan Object, e
logger.Errorf("Stat key %s: %s", key, err)
return
}
objs <- &obj{key, int64(st.Size), st.ModTime, strings.HasSuffix(key, "/"), ""}
objs <- &obj{key, int64(st.Size), st.ModTime, strings.HasSuffix(key, "/"), "", ""}
}
}()
return nil
Expand Down
6 changes: 3 additions & 3 deletions pkg/object/cos.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func (c *COS) Head(key string) (Object, error) {
// This header is returned only if the object is not STANDARD storage class.
sc = "STANDARD"
}
return &obj{key, size, mtime, strings.HasSuffix(key, "/"), sc}, nil
return &obj{key, size, mtime, strings.HasSuffix(key, "/"), sc, ""}, nil
}

func (c *COS) Get(key string, off, limit int64) (io.ReadCloser, error) {
Expand Down Expand Up @@ -182,15 +182,15 @@ func (c *COS) List(prefix, marker, delimiter string, limit int64, followLink boo
if err != nil {
return nil, errors.WithMessagef(err, "failed to decode key %s", o.Key)
}
objs[i] = &obj{key, int64(o.Size), t, strings.HasSuffix(key, "/"), o.StorageClass}
objs[i] = &obj{key, int64(o.Size), t, strings.HasSuffix(key, "/"), o.StorageClass, ""}
}
if delimiter != "" {
for _, p := range resp.CommonPrefixes {
key, err := cos.DecodeURIComponent(p)
if err != nil {
return nil, errors.WithMessagef(err, "failed to decode commonPrefixes %s", p)
}
objs = append(objs, &obj{key, 0, time.Unix(0, 0), true, ""})
objs = append(objs, &obj{key, 0, time.Unix(0, 0), true, "", ""})
}
sort.Slice(objs, func(i, j int) bool { return objs[i].Key() < objs[j].Key() })
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/object/etcd.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ func (c *etcdClient) Head(key string) (Object, error) {
time.Now(),
strings.HasSuffix(key, "/"),
"",
"",
}, nil
}
}
Expand Down Expand Up @@ -140,6 +141,7 @@ func (c *etcdClient) List(prefix, marker, delimiter string, limit int64, followL
time.Now(),
strings.HasSuffix(k, "/"),
"",
"",
})
}
return objs, nil
Expand Down
20 changes: 13 additions & 7 deletions pkg/object/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,10 @@ func (d *filestore) Head(key string) (Object, error) {
if err != nil {
return nil, err
}
return toFile(key, fi, false), nil
return toFile(key, fi, false, ""), nil
}

func toFile(key string, fi fs.FileInfo, isSymlink bool) *file {
func toFile(key string, fi fs.FileInfo, isSymlink bool, linkPath string) *file {
size := fi.Size()
if fi.IsDir() {
size = 0
Expand All @@ -97,6 +97,7 @@ func toFile(key string, fi fs.FileInfo, isSymlink bool) *file {
fi.ModTime(),
fi.IsDir(),
"",
linkPath,
},
owner,
group,
Expand Down Expand Up @@ -202,6 +203,7 @@ type mEntry struct {
name string
fi os.FileInfo
isSymlink bool
linkPath string
}

func (m *mEntry) Name() string {
Expand Down Expand Up @@ -237,21 +239,25 @@ func readDirSorted(dirname string, followLink bool) ([]*mEntry, error) {

mEntries := make([]*mEntry, len(entries))
for i, e := range entries {
var linkPath string
if !e.Mode().IsRegular() {
linkPath, _ = os.Readlink(filepath.Join(dirname, e.Name()))
}
if e.IsDir() {
mEntries[i] = &mEntry{e, e.Name() + dirSuffix, nil, false}
mEntries[i] = &mEntry{e, e.Name() + dirSuffix, nil, false, ""}
} else if !e.Mode().IsRegular() && followLink {
fi, err := os.Stat(filepath.Join(dirname, e.Name()))
if err != nil {
mEntries[i] = &mEntry{e, e.Name(), nil, true}
mEntries[i] = &mEntry{e, e.Name(), nil, true, linkPath}
continue
}
name := e.Name()
if fi.IsDir() {
name = e.Name() + dirSuffix
}
mEntries[i] = &mEntry{e, name, fi, false}
mEntries[i] = &mEntry{e, name, fi, false, linkPath}
} else {
mEntries[i] = &mEntry{e, e.Name(), nil, !e.Mode().IsRegular()}
mEntries[i] = &mEntry{e, e.Name(), nil, !e.Mode().IsRegular(), linkPath}
}
}
sort.Slice(mEntries, func(i, j int) bool { return mEntries[i].Name() < mEntries[j].Name() })
Expand Down Expand Up @@ -299,7 +305,7 @@ func (d *filestore) List(prefix, marker, delimiter string, limit int64, followLi
continue
}
info := e.Info()
f := toFile(key, info, e.isSymlink)
f := toFile(key, info, e.isSymlink, e.linkPath)
objs = append(objs, f)
if len(objs) == int(limit) {
break
Expand Down
9 changes: 5 additions & 4 deletions pkg/object/gluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ func (d *gluster) toFile(key string, fi fs.FileInfo, isSymlink bool) *file {
fi.ModTime(),
fi.IsDir(),
"",
"",
},
owner,
group,
Expand Down Expand Up @@ -179,19 +180,19 @@ func (d *gluster) readDirSorted(dirname string, followLink bool) ([]*mEntry, err
continue
}
if e.IsDir() {
mEntries = append(mEntries, &mEntry{nil, name + dirSuffix, e, false})
mEntries = append(mEntries, &mEntry{nil, name + dirSuffix, e, false, ""})
} else if !e.Mode().IsRegular() && followLink {
fi, err := v.Stat(filepath.Join(dirname, name))
if err != nil {
mEntries = append(mEntries, &mEntry{nil, name, e, true})
mEntries = append(mEntries, &mEntry{nil, name, e, true, ""})
continue
}
if fi.IsDir() {
name += dirSuffix
}
mEntries = append(mEntries, &mEntry{nil, name, fi, false})
mEntries = append(mEntries, &mEntry{nil, name, fi, false, ""})
} else {
mEntries = append(mEntries, &mEntry{nil, name, e, !e.Mode().IsRegular()})
mEntries = append(mEntries, &mEntry{nil, name, e, !e.Mode().IsRegular(), ""})
}
}
sort.Slice(mEntries, func(i, j int) bool { return mEntries[i].Name() < mEntries[j].Name() })
Expand Down
5 changes: 3 additions & 2 deletions pkg/object/gs.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ func (g *gs) Head(key string) (Object, error) {
attrs.Updated,
strings.HasSuffix(key, "/"),
attrs.StorageClass,
"",
}, nil
}

Expand Down Expand Up @@ -159,9 +160,9 @@ func (g *gs) List(prefix, marker, delimiter string, limit int64, followLink bool
for i := 0; i < n; i++ {
item := entries[i]
if delimiter != "" && item.Prefix != "" {
objs[i] = &obj{item.Prefix, 0, time.Unix(0, 0), true, item.StorageClass}
objs[i] = &obj{item.Prefix, 0, time.Unix(0, 0), true, item.StorageClass, ""}
} else {
objs[i] = &obj{item.Name, item.Size, item.Updated, strings.HasSuffix(item.Name, "/"), item.StorageClass}
objs[i] = &obj{item.Name, item.Size, item.Updated, strings.HasSuffix(item.Name, "/"), item.StorageClass, ""}
}
}
if delimiter != "" {
Expand Down
1 change: 1 addition & 0 deletions pkg/object/hdfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ func (h *hdfsclient) toFile(key string, info os.FileInfo) *file {
info.ModTime(),
info.IsDir(),
"",
"",
},
hinfo.Owner(),
hinfo.OwnerGroup(),
Expand Down
5 changes: 3 additions & 2 deletions pkg/object/ibmcos.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ func (s *ibmcos) Head(key string) (Object, error) {
*r.LastModified,
strings.HasSuffix(key, "/"),
*r.StorageClass,
"",
}, nil
}

Expand Down Expand Up @@ -188,15 +189,15 @@ func (s *ibmcos) List(prefix, marker, delimiter string, limit int64, followLink
if err != nil {
return nil, errors.WithMessagef(err, "failed to decode key %s", *o.Key)
}
objs[i] = &obj{oKey, *o.Size, *o.LastModified, strings.HasSuffix(oKey, "/"), *o.StorageClass}
objs[i] = &obj{oKey, *o.Size, *o.LastModified, strings.HasSuffix(oKey, "/"), *o.StorageClass, ""}
}
if delimiter != "" {
for _, p := range resp.CommonPrefixes {
prefix, err := url.QueryUnescape(*p.Prefix)
if err != nil {
return nil, errors.WithMessagef(err, "failed to decode commonPrefixes %s", *p.Prefix)
}
objs = append(objs, &obj{prefix, 0, time.Unix(0, 0), true, ""})
objs = append(objs, &obj{prefix, 0, time.Unix(0, 0), true, "", ""})
}
sort.Slice(objs, func(i, j int) bool { return objs[i].Key() < objs[j].Key() })
}
Expand Down
13 changes: 8 additions & 5 deletions pkg/object/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,16 @@ type Object interface {
IsDir() bool
IsSymlink() bool
StorageClass() string
LinkPath() string
}

type obj struct {
key string
size int64
mtime time.Time
isDir bool
sc string
key string
size int64
mtime time.Time
isDir bool
sc string
linkPath string
}

func (o *obj) Key() string { return o.key }
Expand All @@ -44,6 +46,7 @@ func (o *obj) Mtime() time.Time { return o.mtime }
func (o *obj) IsDir() bool { return o.isDir }
func (o *obj) IsSymlink() bool { return false }
func (o *obj) StorageClass() string { return o.sc }
func (o *obj) LinkPath() string { return o.linkPath }

type MultipartUpload struct {
MinPartSize int
Expand Down
Loading

0 comments on commit 63ee5a8

Please sign in to comment.