making progress!
This commit is contained in:
		
							parent
							
								
									1e45ea3e24
								
							
						
					
					
						commit
						d4b3203f03
					
				
							
								
								
									
										201
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										201
									
								
								main.go
									
									
									
									
									
								
							| @ -63,6 +63,7 @@ func xsum() int { | ||||
| 	case "cron": | ||||
| 		x := xsfCheckAndUpdate(paths) | ||||
| 		if x != nil { | ||||
| 			log.Error(x) | ||||
| 			return -1 | ||||
| 		} else { | ||||
| 			return 0 | ||||
| @ -70,6 +71,7 @@ func xsum() int { | ||||
| 	case "check-and-update": | ||||
| 		x := xsfCheckAndUpdate(paths) | ||||
| 		if x != nil { | ||||
| 			log.Error(x) | ||||
| 			return -1 | ||||
| 		} else { | ||||
| 			return 0 | ||||
| @ -77,6 +79,7 @@ func xsum() int { | ||||
| 	case "check": | ||||
| 		x := xsfCheck(paths) | ||||
| 		if x != nil { | ||||
| 			log.Error(x) | ||||
| 			return -1 | ||||
| 		} else { | ||||
| 			return 0 | ||||
| @ -84,6 +87,7 @@ func xsum() int { | ||||
| 	case "update": | ||||
| 		x := xsfUpdate(paths) | ||||
| 		if x != nil { | ||||
| 			log.Error(x) | ||||
| 			return -1 | ||||
| 		} else { | ||||
| 			return 0 | ||||
| @ -101,7 +105,6 @@ func usage() { | ||||
| 
 | ||||
| func xsfCheck(paths []string) error { | ||||
| 	log.Debugf("check") | ||||
| 	log.Fatalf("not implemented") | ||||
| 	for _, path := range paths { | ||||
| 		x := newXsf(path) | ||||
| 		err := x.Check() | ||||
| @ -154,6 +157,15 @@ func HashFile(fp *os.File) (string, error) { | ||||
| 	return base58.Encode(mHashBuf), nil | ||||
| } | ||||
| 
 | ||||
| func stringInSlice(a string, list []string) bool { | ||||
| 	for _, b := range list { | ||||
| 		if b == a { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| /////////////////////////////////////////////////////////////////////////////////
 | ||||
| // type xsf
 | ||||
| /////////////////////////////////////////////////////////////////////////////////
 | ||||
| @ -180,21 +192,63 @@ func newXsf(path string) *xsf { | ||||
| 	return &x | ||||
| } | ||||
| 
 | ||||
| func (x *xsf) readXattrs(fp *os.File) error { | ||||
| 	log.Infof("reading xattrs") | ||||
| 	var xn string | ||||
| 	var err error | ||||
| 	var v []byte | ||||
| //FIXME calling .List() three times might be slow, memoize if necessary
 | ||||
| 
 | ||||
| 	xn = fmt.Sprintf("%s.%s", namespacePrefix, "mtime") | ||||
| 	v, err = xattr.FGet(x.fp, xn) | ||||
| func (x *xsf) hasMtimeXattr() bool { | ||||
| 	xn := fmt.Sprintf("%s.%s", namespacePrefix, "mtime") | ||||
| 	l, err := xattr.FList(x.fp) | ||||
| 	if err != nil { | ||||
| 		return false | ||||
| 	} | ||||
| 	return stringInSlice(xn, l) | ||||
| } | ||||
| 
 | ||||
| func (x *xsf) readMtimeXattr() error { | ||||
| 	log.Infof("reading mtime xattr") | ||||
| 	xn := fmt.Sprintf("%s.%s", namespacePrefix, "mtime") | ||||
| 
 | ||||
| 	v, err := xattr.FGet(x.fp, xn) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	x.xmtime = string(v) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| 	xn = fmt.Sprintf("%s.%s", namespacePrefix, "size") | ||||
| 	v, err = xattr.FGet(x.fp, xn) | ||||
| func (x *xsf) hasMultihashXattr() bool { | ||||
| 	xn := fmt.Sprintf("%s.%s", namespacePrefix, "multihash") | ||||
| 	l, err := xattr.FList(x.fp) | ||||
| 	if err != nil { | ||||
| 		return false | ||||
| 	} | ||||
| 	return stringInSlice(xn, l) | ||||
| } | ||||
| 
 | ||||
| func (x *xsf) readMultihashXattr() error { | ||||
| 	log.Infof("reading multihash xattr") | ||||
| 	xn := fmt.Sprintf("%s.%s", namespacePrefix, "multihash") | ||||
| 	v, err := xattr.FGet(x.fp, xn) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	x.xmultihash = string(v) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (x *xsf) hasSizeXattr() bool { | ||||
| 	xn := fmt.Sprintf("%s.%s", namespacePrefix, "size") | ||||
| 	l, err := xattr.FList(x.fp) | ||||
| 	if err != nil { | ||||
| 		return false | ||||
| 	} | ||||
| 	return stringInSlice(xn, l) | ||||
| } | ||||
| 
 | ||||
| func (x *xsf) readSizeXattr() error { | ||||
| 	log.Infof("reading size xattr") | ||||
| 	xn := fmt.Sprintf("%s.%s", namespacePrefix, "size") | ||||
| 	v, err := xattr.FGet(x.fp, xn) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @ -205,19 +259,10 @@ func (x *xsf) readXattrs(fp *os.File) error { | ||||
| 	} | ||||
| 
 | ||||
| 	x.xsize = uint64(a) | ||||
| 
 | ||||
| 	xn = fmt.Sprintf("%s.%s", namespacePrefix, "multihash") | ||||
| 	v, err = xattr.FGet(x.fp, xn) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	x.xmultihash = string(v) | ||||
| 
 | ||||
| 	return nil //FIXME
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (x *xsf) writeXattrs(fp *os.File) error { | ||||
| func (x *xsf) writeXattrs() error { | ||||
| 	log.Infof("writing xattrs") | ||||
| 
 | ||||
| 	var xn string | ||||
| @ -225,21 +270,21 @@ func (x *xsf) writeXattrs(fp *os.File) error { | ||||
| 
 | ||||
| 	xn = fmt.Sprintf("%s.%s", namespacePrefix, "mtime") | ||||
| 	log.Infof("writing xattr %s=%s", xn, x.mtime) | ||||
| 	err = xattr.FSet(fp, xn, []byte(x.mtime)) | ||||
| 	err = xattr.FSet(x.fp, xn, []byte(x.mtime)) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	xn = fmt.Sprintf("%s.%s", namespacePrefix, "size") | ||||
| 	log.Infof("writing xattr %s=%s", xn, fmt.Sprintf("%d", x.size)) | ||||
| 	err = xattr.FSet(fp, xn, []byte(fmt.Sprintf("%d", x.size))) | ||||
| 	err = xattr.FSet(x.fp, xn, []byte(fmt.Sprintf("%d", x.size))) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	xn = fmt.Sprintf("%s.%s", namespacePrefix, "multihash") | ||||
| 	log.Infof("writing xattr %s=%s", xn, x.multihash) | ||||
| 	err = xattr.FSet(fp, xn, []byte(x.multihash)) | ||||
| 	err = xattr.FSet(x.fp, xn, []byte(x.multihash)) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @ -247,8 +292,8 @@ func (x *xsf) writeXattrs(fp *os.File) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (x *xsf) stat(fp *os.File) error { | ||||
| 	fi, err := fp.Stat() | ||||
| func (x *xsf) stat() error { | ||||
| 	fi, err := x.fp.Stat() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @ -260,10 +305,10 @@ func (x *xsf) stat(fp *os.File) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (x *xsf) hash(fp *os.File) error { | ||||
| func (x *xsf) hash() error { | ||||
| 	log.Debugf("hashing...") | ||||
| 	var err error | ||||
| 	if x.multihash, err = HashFile(fp); err != nil { | ||||
| 	if x.multihash, err = HashFile(x.fp); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	log.Debugf("hash: %s", x.multihash) | ||||
| @ -276,14 +321,100 @@ func (x *xsf) Check() error { | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	x.stat(x.fp) | ||||
| 	return nil | ||||
| 	x.fp = fp | ||||
| 
 | ||||
| 	serr := x.stat() | ||||
| 	if serr != nil { | ||||
| 		log.Errorf("error stat(): %s", serr) | ||||
| 		return serr | ||||
| 	} | ||||
| 
 | ||||
| 	if x.missingXattrs() == true { | ||||
| 		log.Infof("can't check file %s, does not have appropriate xattrs", x.path) | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	//check to see if file needs update (wrong mtime, wrong size)
 | ||||
| 	if x.needsUpdate() == true { | ||||
| 		log.Infof("can't check file %s, needs update (xattrs not current)", x.path) | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	//finally hash the file
 | ||||
| 	err2 := x.readMultihashXattr() | ||||
| 	if err2 != nil { | ||||
| 		log.Errorf("error reading file hash: %s", err2) | ||||
| 		return err2 | ||||
| 	} | ||||
| 
 | ||||
| 	predictedHash := x.xmultihash | ||||
| 
 | ||||
| 	err3 := x.hash() | ||||
| 	if err3 != nil { | ||||
| 		log.Errorf("error hashing file: %s", err2) | ||||
| 		return err3 | ||||
| 	} | ||||
| 
 | ||||
| 	actualHash := x.multihash | ||||
| 
 | ||||
| 	if predictedHash != actualHash { | ||||
| 		log.Errorf("file corruption detected: expected=%s actual=%s", predictedHash, actualHash) | ||||
| 		return err | ||||
| 	} else { | ||||
| 		log.Infof("file OK hash=%s", actualHash) | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (x *xsf) missingXattrs() bool { | ||||
| 	if x.hasMtimeXattr() == false { | ||||
| 		log.Debugf("file needs update, missing mtime xattr") | ||||
| 		return true | ||||
| 	} | ||||
| 
 | ||||
| 	if x.hasMultihashXattr() == false { | ||||
| 		log.Debugf("file needs update, missing multihash xattr") | ||||
| 		return true | ||||
| 	} | ||||
| 
 | ||||
| 	if x.hasSizeXattr() == false { | ||||
| 		log.Debugf("file needs update, missing size xattr") | ||||
| 		return true | ||||
| 	} | ||||
| 
 | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| func (x *xsf) needsUpdate() bool { | ||||
| 	// this expects stat() to have been called on the xsf
 | ||||
| 	// by Update already, so we have x.mtime et al populated from the
 | ||||
| 	// filesystem
 | ||||
| 
 | ||||
| 	// if the file doesn't have all 3 xattrs, it needs an update.
 | ||||
| 	if x.missingXattrs() == false { | ||||
| 		return true | ||||
| 	} | ||||
| 
 | ||||
| 	// if the size doesn't match, it needs an update
 | ||||
| 	if x.size != x.xsize { | ||||
| 		log.Debugf("file needs update, size is %s, xattr size is %s", x.size, x.xsize) | ||||
| 		return true | ||||
| 	} | ||||
| 
 | ||||
| 	// if the mtime is not the same, it needs an update
 | ||||
| 	if x.mtime != x.xmtime { | ||||
| 		log.Debugf("file needs update, mtime is %s, xattr mtime is %s", x.mtime, x.xmtime) | ||||
| 		return true | ||||
| 	} | ||||
| 
 | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| func (x *xsf) Update() error { | ||||
| 	fp, err := os.Open(x.path) | ||||
| 	defer fp.Close() | ||||
| 	log.Debugf("updating file (path: %s)", x.path) | ||||
| 	fp, err := os.Open(x.path) | ||||
| 	x.fp = fp | ||||
| 	defer fp.Close() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @ -291,15 +422,15 @@ func (x *xsf) Update() error { | ||||
| 	//FIXME check if size/mtime are defined first
 | ||||
| 	//and skip update if match (and key 'multihash' exists)
 | ||||
| 
 | ||||
| 	if err = x.stat(fp); err != nil { | ||||
| 	if err = x.stat(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	if err = x.hash(fp); err != nil { | ||||
| 	if err = x.hash(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	if err = x.writeXattrs(fp); err != nil { | ||||
| 	if err = x.writeXattrs(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user