@sharelist/node-smb-server
Version:
Sharelist SMB Server Implementation Base On node-smb-server
289 lines (252 loc) • 8.17 kB
JavaScript
/*
* Copyright 2015 Adobe Systems Incorporated. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
'use strict';
var logger = require('winston').loggers.get('spi'),
async = require('async');
var common = require('./common');
/**
* Represents a file opened by an SMB command.
*
* @param {File} spiFile
* @param {SMBTree} smbTree
* @param {Number} [createAction = FILE_OPENED]
* @param {Number} [fid = 0]
* @constructor
*/
function SMBFile(spiFile, smbTree, createAction, fid) {
this.spiFile = spiFile;
this.smbTree = smbTree;
this.createAction = createAction === undefined ? common.FILE_OPENED : createAction;
this.attributes = 0;
if (spiFile.isDirectory()) {
this.attributes |= common.ATTR_DIRECTORY;
} else if (spiFile.isFile()) {
this.attributes |= common.ATTR_NORMAL;
}
if (spiFile.isHidden()) {
this.attributes |= common.ATTR_HIDDEN;
}
if (spiFile.isReadOnly()) {
this.attributes |= common.ATTR_READ_ONLY;
}
this.fid = fid === undefined ? 0 : fid;
this.deleteOnClose = false;
}
SMBFile.prototype.getId = function () {
return this.fid;
};
SMBFile.prototype.getTree = function () {
return this.smbTree;
};
SMBFile.prototype.getCreateAction = function () {
return this.createAction;
};
SMBFile.prototype.getAttributes = function () {
return this.attributes;
};
/**
* Return the file name.
*
* @return {String} file name
*/
SMBFile.prototype.getName = function () {
return this.spiFile.getName();
};
/**
* Return the file path.
*
* @return {String} file path
*/
SMBFile.prototype.getPath = function () {
return this.spiFile.getPath();
};
/**
* Return a flag indicating whether this is a file.
*
* @return {Boolean} <code>true</code> if this is a file;
* <code>false</code> otherwise
*/
SMBFile.prototype.isFile = function () {
return this.spiFile.isFile();
};
/**
* Return a flag indicating whether this is a directory.
*
* @return {Boolean} <code>true</code> if this is a directory;
* <code>false</code> otherwise
*/
SMBFile.prototype.isDirectory = function () {
return this.spiFile.isDirectory();
};
/**
* Return a flag indicating whether this file is read-only.
*
* @return {Boolean} <code>true</code> if this file is read-only;
* <code>false</code> otherwise
*/
SMBFile.prototype.isReadOnly = function () {
return this.spiFile.isReadOnly();
};
/**
* Return the file length in bytes or 0 in the case of a directory.
*
* @return {Number} file length, in bytes
*/
SMBFile.prototype.getDataSize = function () {
return this.spiFile.isFile() ? this.spiFile.size() : 0;
};
/**
* Return the number of bytes that are allocated to the file or 0 in the case of a directory.
*
* @return {Number} allocation size, in bytes
*/
SMBFile.prototype.getAllocationSize = function () {
return this.spiFile.isFile() ? this.spiFile.allocationSize() : 0;
};
/**
* Return the create time, in milliseconds since Jan 1, 1970, 00:00:00.0.
*
* @return {Number} time created
*/
SMBFile.prototype.getCreatedTime = function () {
return this.spiFile.created();
};
/**
* Return the time of last modification, in milliseconds since
* Jan 1, 1970, 00:00:00.0.
*
* @return {Number} time created
*/
SMBFile.prototype.getLastModifiedTime = function () {
return this.spiFile.lastModified();
};
/**
* Sets the time of last modification, in milliseconds since
* Jan 1, 1970, 00:00:00.0.
*
* @param {Number} ms
* @return {Number} time of last modification
*/
SMBFile.prototype.setLastModifiedTime = function (ms) {
this.spiFile.setLastModified(ms);
};
/**
* Return the time when file status was last changed, in milliseconds since
* Jan 1, 1970, 00:00:00.0.
*
* @return {Number} when file status was last changed
*/
SMBFile.prototype.getLastChangedTime = function () {
return this.spiFile.lastChanged();
};
/**
* Return the time of last access, in milliseconds since Jan 1, 1970, 00:00:00.0.
*
* @return {Number} time of last access
*/
SMBFile.prototype.getLastAccessedTime = function () {
return this.spiFile.lastAccessed();
};
/**
* Read bytes at a certain position inside the file.
*
* @param {Buffer} buffer the buffer that the data will be written to
* @param {Number} offset the offset in the buffer to start writing at
* @param {Number} length the number of bytes to read
* @param {Number} position offset where to begin reading from in the file
* @param {Function} cb callback called with the bytes actually read
* @param {SMBError} cb.error error (non-null if an error occurred)
* @param {Number} cb.bytesRead number of bytes actually read
* @param {Buffer} cb.buffer buffer holding the bytes actually read
*/
SMBFile.prototype.read = function (buffer, offset, length, position, cb) {
logger.debug('[fid=%d] file.read %s offset=%d, length=%d, position=%d', this.fid, this.getPath(), offset, length, position);
this.spiFile.read(buffer, offset, length, position, cb);
};
/**
* Write bytes at a certain position inside the file.
*
* @param {Buffer} data buffer to write
* @param {Number} position position inside file
* @param {Function} cb callback called on completion
* @param {SMBError} cb.error error (non-null if an error occurred)
*/
SMBFile.prototype.write = function (data, position, cb) {
logger.debug('[fid=%d] file.write %s data.length=%d, position=%d', this.fid, this.getPath(), data.length, position);
this.spiFile.write(data, position, cb);
};
/**
* Delete this file or directory. If this file denotes a directory, it must
* be empty in order to be deleted.
*
* @param {Function} cb callback called on completion
* @param {SMBError} cb.error error (non-null if an error occurred)
*/
SMBFile.prototype.delete = function (cb) {
logger.debug('[fid=%d] file.delete %s', this.fid, this.getPath());
this.spiFile.delete(cb);
// notify registered change listeners
this.smbTree.notifyChangeListeners(common.FILE_ACTION_REMOVED, this.getPath());
};
/**
* Sets the length of the file.
*
* @param {Number} length new length of file
* @param {Function} cb callback called on completion
* @param {SMBError} cb.error error (non-null if an error occurred)
*/
SMBFile.prototype.setLength = function (length, cb) {
logger.debug('[fid=%d] file.setLength %s length=%d', this.fid, this.getPath(), length);
this.spiFile.setLength(length, cb);
};
/**
* Delete this file when it will be closed.
*/
SMBFile.prototype.setDeleteOnClose = function () {
logger.debug('[fid=%d] file.setDeleteOnClose %s', this.fid, this.getPath());
this.deleteOnClose = true;
};
/**
* Flush the contents of the file to disk.
*
* @param {Function} cb callback called on completion
* @param {SMBError} cb.error error (non-null if an error occurred)
*/
SMBFile.prototype.flush = function (cb) {
logger.debug('[fid=%d] file.flush %s', this.fid, this.getPath());
this.spiFile.flush(cb);
// notify registered change listeners
this.smbTree.notifyChangeListeners(common.FILE_ACTION_MODIFIED, this.getPath());
};
/**
* Close this file, releasing any resources.
*
* @param {Function} cb callback called on completion
* @param {SMBError} cb.error error (non-null if an error occurred)
*/
SMBFile.prototype.close = function (cb) {
logger.debug('[fid=%d] file.close %s deleteOnClose=%d', this.fid, this.getPath(), this.deleteOnClose);
var self = this;
async.series([
function (callback) {
self.spiFile.close(callback);
},
function (callback) {
if (self.deleteOnClose) {
self.delete(callback);
} else {
callback();
}
}
], cb);
};
module.exports = SMBFile;