This file is indexed.

/usr/lib/nodejs/tilelive/lib/copytask.js is in node-tilelive 4.5.0-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
var tilelive = require('..');
var url = require('url');
var fs = require('fs');
var Scheme = require('./scheme');

module.exports = CopyTask;
require('util').inherits(CopyTask, process.EventEmitter);
function CopyTask(from, to, scheme, job) {
    if (typeof from.getInfo === 'function') {
        this.source = from;
        from = 'temporary://';
    }
    if (typeof to.putInfo === 'function') {
        this.sink = to;
        to = 'temporary://';
    }
    this.from = typeof from === 'string' ? url.parse(from) : from;
    this.to = typeof to === 'string' ? url.parse(to) : to;
    this.scheme = scheme;
    this.started = null;
    this.ended = null;
    this.job = job || '/tmp/tilelive-' + (+new Date) + '.job';
    this.formats = [];
    this.cache = { tile: {}, grid: {} };
    this.initialize();
}

CopyTask.prototype.initialize = function() {
    var task = this;

    this.stats = this.scheme.stats;
    this.emit('progress', this.stats.snapshot());

    // Make sure this is non-enumerable;
    Object.defineProperty(this.scheme, 'task', { value: this });

    // State persistence
    console.warn('Persisting state in ' + this.job + ' every minute');

    // NOTE - This will no longer throw as of node v0.8.9
    // https://github.com/joyent/node/commit/ea1cba6246a8b1784e22d076139b9244a9ff42f8
    if ((process.platform !== 'win32')) {
        process.on('SIGINT', function() {
            task.pause(function(err) {
                if (err) throw err;
                console.warn('\nWrote state to ' + task.job);
            });
        });
    }
};

CopyTask.prototype.toJSON = function() {
    return {
        started: this.started,
        ended: this.ended,
        from: this.from,
        to: this.to,
        scheme: this.scheme
    };
};

CopyTask.prototype.finished = function() {
    var task = this;
    this.pause(function(err) {
        if (err) {
            if (err.stack) console.warn('\n' + err.stack);
            else console.warn('\n' + err.message);
        }
        task.emit('finished');
    });
};

CopyTask.prototype.pause = function(callback) {
    // Don't call the callback if already pausing as callers often
    // expect they are the only ones doing teardown operations.
    if (this.pausing) return;

    var task = this;
    this.pausing = true;

    this.scheme.once('paused', function() {
        clearInterval(task.progressInterval);
        clearInterval(task.stateInterval);
        task.emit('progress', task.stats.snapshot());

        task.sink.stopWriting(function(err) {
            task.ended = Date.now();
            task.emit('progress', task.stats.snapshot());
            if (err) return callback(err);
            fs.writeFile(task.job, JSON.stringify(task), function(err) {
                if (err) return callback(err);
                task.sink.close(function(err) {
                    if (err) return callback(err);
                    task.source.close(callback);
                });
            });
        });
    });

    this.scheme.pause();
};

CopyTask.prototype.start = function(callback) {
    callback = callback || new Function;

    var task = this
    if (!this.started) this.started = Date.now();

    this.progressInterval = setInterval(function() {
        task.emit('progress', task.stats.snapshot());
    }, 1000);

    this.stateInterval = setInterval(function() {
        fs.writeFile(task.job, JSON.stringify(task));
    }, 60000);

    var init = function() {
        if (!task.source) return tilelive.load(task.from, function(err, source) {
            if (err) return callback(err);
            task.source = source;
            init();
        });
        if (!task.formats.length) return task.source.getInfo(function(err, info) {
            if (err) return callback(err);
            // @TODO the tilelive API currently has no standard way
            // of determining whether a tilesource has tiles, grids
            // or both. See issue #44.
            task.formats.push('tile');
            // Use template as an indicator that grids are present.
            if (info.template) {
                task.formats.push('grid');
                task.stats.total = (task.stats.total || 0) * 2;
            }
            init();
        });
        if (!task.sink) return tilelive.load(task.to, function(err, sink) {
            if (err) return callback(err);
            task.sink = sink;
            init();
        });
        task.sink.startWriting(function(err) {
            if (err) return callback();

            // It is possible for a CopyTask to be paused before it
            // ever starts (SIGINT, exceptions, etc.) In these cases
            // respect the pause rather than forging ahead.
            if (task.pausing) return callback(null);

            task.scheme.start();
            callback(null);
        });
    };
    init();
};

CopyTask.prototype.render = function(tile, type) {
    var get = type === 'grid' ? 'getGrid' : 'getTile';
    var put = type === 'grid' ? 'putGrid' : 'putTile';
    var task = this;

    // If tile key is set and we have cached its buffer in memory,
    // skip rendering and use the existing buffer.
    if (tile.key !== false && task.cache[type][tile.key]) {
        var data = task.cache[type][tile.key];
        task.sink[put](tile.z, tile.x, tile.y, data, function(err) {
            if (err) {
                task.emit('error', err, tile);
                task.scheme.error(tile);
            } else {
                task.scheme.duplicate(tile);
            }
        });
    // Render the tile.
    } else {
        task.source[get](tile.z, tile.x, tile.y, function(err, data) {
            if (err) {
                if (err.message.match(/Tile|Grid does not exist/)) {
                    task.scheme.skip(tile);
                } else {
                    task.emit('error', err, tile);
                    task.scheme.error(tile);
                }
                return;
            }
            if (data.solid) switch(type) {
            case 'grid':
                // Empty grid.
                if (data.solid === '0') {
                    data.key = tile.key = 0;
                // String grid key.
                } else {
                    data.key = tile.key = data.solid;
                }
                task.cache[type][tile.key] = data;
                break;
            case 'tile':
                var color = data.solid.split(',');
                // Empty tile.
                if (color[3] === '0') {
                    data.key = tile.key = 0;
                // Negative encoded RGBA value.
                } else {
                    data.key = tile.key = -(color[0]*(1<<24) + ((color[1]<<16) | (color[2]<<8) | color[3]));
                }
                task.cache[type][tile.key] = data;
                break;
            }
            if (tile.key === 0) {
                task.scheme.skip(tile);
            } else {
                task.sink[put](tile.z, tile.x, tile.y, data, function(err) {
                    if (err) {
                        task.emit('error', err, tile);
                        task.scheme.error(tile);
                    } else if (tile.key === false) {
                        // This is a unique tile
                        task.scheme.unique(tile);
                    } else {
                        task.scheme.duplicate(tile);
                    }
                });
            }
        });
    }
};