// Saves Meta data from dirTree to meta File func saveMeta(data *ReveloData) error { var Meta *horcrux.Meta var err error data.lock.RLock() Meta, err = dirTree.GetMeta(data.Root) Meta.Config = data.Config Meta.CurrVer = data.CurrVer data.lock.RUnlock() if err != nil { log.Error("saveMeta: Cannot get Meta data") return err } js, err := json.MarshalIndent(Meta, "", " ") if err != nil { log.WithFields( log.Fields{"Meta": Meta, "Error": err}).Error("saveMeta: Cannot marshal meta") return err } metaFile, err := os.OpenFile(data.cacheDir+"/"+data.metaName, os.O_WRONLY|os.O_SYNC, 0600) if err != nil { log.WithFields(log.Fields{"Meta File": data.metaName, "Error": err}).Error("saveMeta: Cannot open meta file") return err } defer metaFile.Close() // XXX Using File EX lock to avoid multiple access for err = syscall.Flock(int(metaFile.Fd()), syscall.LOCK_EX); err == syscall.EINTR; { } if err != nil { log.WithFields(log.Fields{"Error": err}).Error("saveMeta: Cannot lock meta file") return err } defer syscall.Flock(int(metaFile.Fd()), syscall.LOCK_UN) metaFile.Truncate(0) //XXX: Do Truncate(n) after write succeeds!! n, err := metaFile.Write(js) if err != nil { log.WithFields(log.Fields{ "Meta file": data.metaName, "Wrote": n, "Size": len(js), "Error": err, }).Error("saveMeta: Cannot write to meta file") return err } log.Debug("saveMeta: Done") return nil }