@@ -95,24 +95,57 @@ func GetCapacity(mountPoint string) (*Capacity, error) {
9595 }, nil
9696}
9797
98- // GetDeviceName extracts the base device name from a device path
99- // e.g., /dev/sda1 -> sda1, /dev/mapper/foo -> dm-X (via symlink resolution)
100- func GetDeviceName (devicePath string ) (string , error ) {
101- // Resolve symlinks
102- resolved , err := os . Readlink (devicePath )
98+ // ResolveDevice resolves a device path (following symlinks) and returns both
99+ // the resolved path and the device name for diskstats
100+ func ResolveDevice (devicePath string ) (resolvedPath , deviceName string ) {
101+ // Try to fully resolve symlinks
102+ resolved , err := evalSymlinks (devicePath )
103103 if err != nil {
104- // Not a symlink, use basename
105- parts := strings .Split (devicePath , "/" )
106- return parts [len (parts )- 1 ], nil
104+ resolved = devicePath
107105 }
108106
109- // If relative path, it's relative to /dev
110- if ! strings .HasPrefix (resolved , "/" ) {
111- resolved = "/dev/" + resolved
107+ // Extract device name (basename)
108+ parts := strings .Split (resolved , "/" )
109+ name := parts [len (parts )- 1 ]
110+
111+ return resolved , name
112+ }
113+
114+ // evalSymlinks resolves all symlinks in a path
115+ func evalSymlinks (path string ) (string , error ) {
116+ // Use filepath.EvalSymlinks equivalent
117+ for i := 0 ; i < 255 ; i ++ { // limit iterations to prevent infinite loops
118+ fi , err := os .Lstat (path )
119+ if err != nil {
120+ return path , err
121+ }
122+
123+ if fi .Mode ()& os .ModeSymlink == 0 {
124+ return path , nil
125+ }
126+
127+ target , err := os .Readlink (path )
128+ if err != nil {
129+ return path , err
130+ }
131+
132+ if ! strings .HasPrefix (target , "/" ) {
133+ // Relative symlink - resolve relative to parent dir
134+ dir := path [:strings .LastIndex (path , "/" )+ 1 ]
135+ path = dir + target
136+ } else {
137+ path = target
138+ }
112139 }
113140
114- parts := strings .Split (resolved , "/" )
115- return parts [len (parts )- 1 ], nil
141+ return path , fmt .Errorf ("too many symlinks" )
142+ }
143+
144+ // GetDeviceName extracts the base device name from a device path
145+ // e.g., /dev/sda1 -> sda1, /dev/mapper/foo -> dm-X (via symlink resolution)
146+ func GetDeviceName (devicePath string ) (string , error ) {
147+ _ , name := ResolveDevice (devicePath )
148+ return name , nil
116149}
117150
118151// FindMountByPath finds a mount that contains the given path
0 commit comments