add capctime flag to camput

I can recreate the file, set the modification time, but can't forge creation
time, thus cannot recreate the exact same uploaded file twice.
This change targets this problem.

As this is a very rarely used flag, this is enabled only if the CAMLI_DEBUG
environment variable is true - such as the other "gross" options
(statcache, sqlitecache...).

Change-Id: I99c7805898ed97883043de4e7dcec23a472e462c
This commit is contained in:
Tamás Gulácsi 2013-10-07 07:55:49 +02:00
parent 81acf521ce
commit e056081be1
3 changed files with 26 additions and 2 deletions

View File

@ -52,6 +52,7 @@ type fileCmd struct {
filePermanodes bool // make planned permanodes for each file (based on their digest)
vivify bool
exifTime bool // use metadata (such as in EXIF) to find the creation time of the file
capCtime bool // use mtime as creation time of the file, if it would be bigger than modification time
diskUsage bool // show "du" disk usage only (dry run mode), don't actually upload
argsFromInput bool // Android mode: filenames piped into stdin, one at a time.
@ -84,6 +85,7 @@ func init() {
flags.BoolVar(&cmd.havecache, "havecache", true, "Use the 'have cache', a cache keeping track of what blobs the remote server should already have from previous uploads.")
flags.BoolVar(&cmd.memstats, "debug-memstats", false, "Enter debug in-memory mode; collecting stats only. Doesn't upload anything.")
flags.StringVar(&cmd.histo, "debug-histogram-file", "", "Optional file to create and write the blob size for each file uploaded. For use with GNU R and hist(read.table(\"filename\")$V1). Requires debug-memstats.")
flags.BoolVar(&cmd.capCtime, "capctime", false, "For file blobs use file modification time as creation time if it would be bigger (newer) than modification time. For stable filenode creation (you can forge mtime, but can't forge ctime).")
flags.BoolVar(&flagUseSQLiteChildCache, "sqlitecache", false, "Use sqlite for the statcache and havecache instead of a flat cache.")
} else {
cmd.havecache = true
@ -148,6 +150,7 @@ func (c *fileCmd) RunCommand(args []string) error {
tag: c.tag,
vivify: c.vivify,
exifTime: c.exifTime,
capCtime: c.capCtime,
}
var (
@ -516,6 +519,9 @@ func (up *Uploader) uploadNodeRegularFile(n *node) (*client.PutResult, error) {
filebb.SetModTime(modtime)
}
}
if up.fileOpts.capCtime {
filebb.CapCreationTime()
}
var (
size = n.fi.Size()

View File

@ -54,8 +54,9 @@ type fileOptions struct {
// the above permanode.
tag string
// perform for the client the actions needing gpg signing when uploading a file.
vivify bool
exifTime bool // use the time in exif metadata as the modtime if possible.
vivify bool
exifTime bool // use the time in exif metadata as the modtime if possible.
capCtime bool // use mtime as ctime if ctime > mtime
}
func (o *fileOptions) tags() []string {
@ -73,6 +74,10 @@ func (o *fileOptions) wantVivify() bool {
return o != nil && o.vivify
}
func (o *fileOptions) wantCapCtime() bool {
return o != nil && o.capCtime
}
func (up *Uploader) uploadString(s string) (*client.PutResult, error) {
return up.Upload(client.NewUploadHandleFromString(s))
}

View File

@ -383,6 +383,19 @@ func (bb *Builder) SetModTime(t time.Time) *Builder {
return bb
}
// CapCreationTime caps the "unixCtime" field to be less or equal than "unixMtime"
func (bb *Builder) CapCreationTime() *Builder {
ctime, ok := bb.m["unixCtime"].(string)
if !ok {
return bb
}
mtime, ok := bb.m["unixMtime"].(string)
if ok && ctime > mtime {
bb.m["unixCtime"] = mtime
}
return bb
}
// ModTime returns the "unixMtime" modtime field, if set.
func (bb *Builder) ModTime() (t time.Time, ok bool) {
s, ok := bb.m["unixMtime"].(string)