@@ -386,9 +386,47 @@ func (v *Validator) CheckLinux() (msgs []string) {
386386 msgs = append (msgs , fmt .Sprintf ("On Linux, hostname requires a new UTS namespace to be specified as well" ))
387387 }
388388
389+ // Linux devices validation
390+ devList := make (map [string ]bool )
391+ typeList := make (map [string ]bool )
389392 for index := 0 ; index < len (v .spec .Linux .Devices ); index ++ {
390- if ! deviceValid (v .spec .Linux .Devices [index ]) {
391- msgs = append (msgs , fmt .Sprintf ("device %v is invalid." , v .spec .Linux .Devices [index ]))
393+ device := v .spec .Linux .Devices [index ]
394+ if ! deviceValid (device ) {
395+ msgs = append (msgs , fmt .Sprintf ("device %v is invalid." , device ))
396+ }
397+
398+ if _ , exists := devList [device .Path ]; exists {
399+ msgs = append (msgs , fmt .Sprintf ("device %s is duplicated" , device .Path ))
400+ } else {
401+ var rootfsPath string
402+ if filepath .IsAbs (v .spec .Root .Path ) {
403+ rootfsPath = v .spec .Root .Path
404+ } else {
405+ rootfsPath = filepath .Join (v .bundlePath , v .spec .Root .Path )
406+ }
407+ absPath := filepath .Join (rootfsPath , device .Path )
408+ _ , err := os .Stat (absPath )
409+ if os .IsNotExist (err ) {
410+ devList [device .Path ] = true
411+ } else if err != nil {
412+ msgs = append (msgs , err .Error ())
413+ } else {
414+ msgs = append (msgs , fmt .Sprintf ("%s already exists in filesystem" , device .Path ))
415+ }
416+ }
417+
418+ // unify u->c when comparing, they are synonyms
419+ var devId string
420+ if device .Type == "u" {
421+ devId = fmt .Sprintf ("%s:%d:%d" , "c" , device .Major , device .Minor )
422+ } else {
423+ devId = fmt .Sprintf ("%s:%d:%d" , device .Type , device .Major , device .Minor )
424+ }
425+
426+ if _ , exists := typeList [devId ]; exists {
427+ logrus .Warnf ("type:%s, major:%d and minor:%d for linux devices is duplicated" , device .Type , device .Major , device .Minor )
428+ } else {
429+ typeList [devId ] = true
392430 }
393431 }
394432
0 commit comments