1/* 2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15// @ts-nocheck 16import Extension from '@ohos.application.FileAccessExtensionAbility'; 17import fs from '@ohos.file.fs'; 18import type { Filter } from '@ohos.file.fs'; 19import fileAccess from '@ohos.file.fileAccess'; 20import fileExtensionInfo from '@ohos.file.fileExtensionInfo'; 21import hilog from '@ohos.hilog'; 22import { getListFileInfos, getScanFileInfos, buildFilterOptions, buildNoFilterOptions, hasFilter } from './ListScanFileInfo'; 23import type { Fileinfo } from './Common'; 24import { getPath, checkUri, uriReturnObject, encodePathOfUri, decodeUri, BUNDLE_NAME, DOMAIN_CODE, fileinfoReturnObject } from './Common'; 25import { FILE_PREFIX_NAME, TAG, fdReturnObject, boolReturnObject, rootsReturnObject } from './Common'; 26import { infosReturnObject, resultsResultObject } from './Common'; 27 28 29const deviceFlag = fileExtensionInfo.DeviceFlag; 30const documentFlag = fileExtensionInfo.DocumentFlag; 31const deviceType = fileExtensionInfo.DeviceType; 32const MOVEFILEOVERWRITE = 2; 33const FILEOVERWRITE = 1; 34const THROWEXCEPTION = 0; 35 36const ERR_OK = 0; 37const ERR_ERROR = -1; 38const EXCEPTION = -1; 39const NOEXCEPTION = -2; 40const E_PERM = 13900001; 41const E_NOEXIST = 13900002; 42const E_FAULT = 13900013; 43const E_EXIST = 13900015; 44const E_NOT_DIR = 13900018; 45const E_IS_DIR = 13900019; 46const E_INVAL = 13900020; 47const E_URIS = 14300002; 48const E_GETRESULT = 14300004; 49const CREATE_EVENT_CODE = 0x00000100; 50const IN_DELETE_EVENT_CODE = 0x00000200; 51const DELETE_SELF_EVENT_CODE = 0x00000400; 52const MOVE_TO_CODE = 0x00000080; 53const MOVED_FROM_CODE = 0x00000040; 54const MOVE_SELF_CODE = 0x00000800; 55const MOVE_MODLE_CODE = 3; 56const CREATE_EVENT = 0; 57const DELETE_EVENT = 1; 58const MOVED_TO = 2; 59const MOVED_FROM = 3; 60const MOVED_SELF = 4; 61const DEVICE_ONLINE = 5; 62const DEVICE_OFFLINE = 6; 63const CURRENT_USER_PATH_LEN = 4; 64const CURRENT_USER_PATH = '/storage/Users/currentUser'; 65const USER_PATH = '/storage/Users/'; 66const TRASH_SUB_FODER = '/oh_trash_content'; 67const EXTERNAL_PATH = '/storage/External'; 68let observerMap = new Map(); 69let eventMap = new Map([ 70 [CREATE_EVENT_CODE, CREATE_EVENT], 71 [IN_DELETE_EVENT_CODE, DELETE_EVENT], 72 [DELETE_SELF_EVENT_CODE, DELETE_EVENT], 73 [MOVE_TO_CODE, MOVED_TO], 74 [MOVED_FROM_CODE, MOVED_FROM], 75 [MOVE_SELF_CODE, MOVED_SELF] 76]); 77 78let deviceOnlineMap = new Map([ 79 [CREATE_EVENT_CODE, DEVICE_ONLINE], 80 [IN_DELETE_EVENT_CODE, DEVICE_OFFLINE] 81]); 82 83// ['IN_ACCESS', 0x00000001], 84// ['IN_MODIFY', 0x00000002], 85// ['IN_ATTRIB', 0x00000004], 86// ['IN_CLOSE_WRITE', 0x00000008], 87// ['IN_CLOSE_NOWRITE', 0x00000010], 88// ['IN_OPE', 0x00000020], 89// ['IN_MOVED_FROM', 0x00000040], 90// ['IN_MOVED_TO', 0x00000080], 91// ['IN_CREATE', 0x00000100], 92// ['IN_DELETE', 0x00000200], 93// ['IN_DELETE_SELF', 0x00000400], 94// ['IN_MOVE_SELF', 0x00000800] 95 96export default class FileExtAbility extends Extension { 97 onCreate(want): void { 98 hilog.info(DOMAIN_CODE, TAG, 'Extension init process'); 99 } 100 101 102 genNewFileUri(uri, displayName) { 103 let newFileUri = uri; 104 if (uri.charAt(uri.length - 1) === '/') { 105 newFileUri += displayName; 106 } else { 107 newFileUri += '/' + displayName; 108 } 109 return newFileUri; 110 } 111 112 getFileName(uri): string { 113 let arr = uri.split('/'); 114 let name = arr.pop(); 115 if (name === '') { 116 name = arr.pop(); 117 } 118 return name; 119 } 120 121 renameUri(uri, displayName): string { 122 let arr = uri.split('/'); 123 let newFileUri = ''; 124 if (arr.pop() === '') { 125 arr.pop(); 126 arr.push(displayName); 127 arr.push(''); 128 } else { 129 arr.push(displayName); 130 } 131 for (let index = 0; index < arr.length; index++) { 132 if (arr[index] === '') { 133 newFileUri += '/'; 134 } else if (index === arr.length - 1) { 135 newFileUri += arr[index]; 136 } else { 137 newFileUri += arr[index] + '/'; 138 } 139 } 140 return newFileUri; 141 } 142 143 recurseDir(path, cb): void { 144 try { 145 let stat = fs.statSync(path); 146 if (stat.isDirectory()) { 147 let fileName = fs.listFileSync(path); 148 for (let fileLen = 0; fileLen < fileName.length; fileLen++) { 149 stat = fs.statSync(path + '/' + fileName[fileLen]); 150 if (stat.isDirectory()) { 151 this.recurseDir(path + '/' + fileName[fileLen], cb); 152 } else { 153 cb(path + '/' + fileName[fileLen], false); 154 } 155 } 156 } else { 157 cb(path, false); 158 } 159 } catch (e) { 160 hilog.error(DOMAIN_CODE, TAG, 'recurseDir error ' + e.message); 161 cb(path, true); 162 } 163 } 164 165 openFile(sourceFileUri, flags): {number, number} { 166 sourceFileUri = decodeUri(sourceFileUri); 167 if (!checkUri(sourceFileUri)) { 168 return fdReturnObject(ERR_ERROR, E_URIS); 169 } 170 try { 171 let path = getPath(sourceFileUri); 172 let file = fs.openSync(path, flags); 173 return fdReturnObject(file.fd, ERR_OK); 174 } catch (e) { 175 hilog.error(DOMAIN_CODE, TAG, 'openFile error ' + e.message); 176 return fdReturnObject(ERR_ERROR, e.code); 177 } 178 } 179 180 createFile(parentUri, displayName): {string, number} { 181 parentUri = decodeUri(parentUri); 182 if (!checkUri(parentUri)) { 183 return uriReturnObject('', E_URIS); 184 } 185 try { 186 hilog.info(DOMAIN_CODE, TAG, 'createFile, uri is ' + parentUri); 187 let newFileUri = this.genNewFileUri(parentUri, displayName); 188 let path = getPath(newFileUri); 189 if (fs.accessSync(path)) { 190 return uriReturnObject('', E_EXIST); 191 } 192 let file = fs.openSync(path, fs.OpenMode.CREATE); 193 fs.closeSync(file); 194 newFileUri = encodePathOfUri(newFileUri); 195 return uriReturnObject(newFileUri, ERR_OK); 196 } catch (e) { 197 hilog.error(DOMAIN_CODE, TAG, 'createFile error ' + e.message); 198 return uriReturnObject('', e.code); 199 } 200 } 201 202 mkdir(parentUri, displayName): {string, number} { 203 parentUri = decodeUri(parentUri); 204 if (!checkUri(parentUri)) { 205 return uriReturnObject('', E_URIS); 206 } 207 try { 208 let newFileUri = this.genNewFileUri(parentUri, displayName); 209 let path = getPath(newFileUri); 210 fs.mkdirSync(path); 211 newFileUri = encodePathOfUri(newFileUri); 212 return uriReturnObject(newFileUri, ERR_OK); 213 } catch (e) { 214 hilog.error(DOMAIN_CODE, TAG, 'mkdir error ' + e.message); 215 return uriReturnObject('', e.code); 216 } 217 } 218 219 mkdirs(path): void { 220 if (path.length > 0) { 221 // argument uri is dir, add '/' 222 path = path + '/'; 223 for (let i = 1; i < path.length; ++i) { 224 if (path.charAt(i) === '/') { 225 let subDir = path.substring(0, i); 226 hilog.info(DOMAIN_CODE, TAG, 'mkdirs: subDir path = ' + subDir); 227 try { 228 let isAccess = fs.accessSync(subDir); 229 if (!isAccess) { 230 fs.mkdirSync(subDir); 231 } 232 } catch (e) { 233 hilog.error(DOMAIN_CODE, TAG, 'mkdirs error ' + e.message); 234 } 235 } 236 } 237 } 238 } 239 240 getUserPath(path): string { 241 let i; 242 let num = 0; 243 if (path.indexOf(USER_PATH) !== 0) { 244 return CURRENT_USER_PATH; 245 } 246 for (i = 0; i < path.length; i++) { 247 if (path[i] === '/') { 248 num ++; 249 if (num === CURRENT_USER_PATH_LEN) { 250 return path.substring(0, i); 251 } 252 } 253 } 254 return path; 255 } 256 257 deleteToTrash(path): number { 258 let code = ERR_OK; 259 let pathLen = path.length; 260 if (path.charAt(pathLen - 1) === '/') { 261 path = path.substring(0, pathLen - 1); 262 } 263 // 取最后一级和前一层目录 264 let posLastSlash = path.lastIndexOf('/'); 265 if (posLastSlash === -1) { 266 hilog.error(DOMAIN_CODE, TAG, 'Mkdirs: invalid uri'); 267 return E_URIS; 268 } 269 270 let selectPathOnly = path.substring(0, posLastSlash); 271 // 获取时间戳 272 let curTime = new Date().getTime(); 273 try { 274 // 拼接新路径 275 let currentTrashParentPath = this.getUserPath(path) + '/.Trash/' + curTime + selectPathOnly + TRASH_SUB_FODER + curTime; 276 // 创建回收站目录 277 this.mkdirs(currentTrashParentPath); 278 let stat = fs.statSync(path); 279 if (!stat.isDirectory()) { 280 let selectFileOnly = path.substring(posLastSlash); 281 hilog.info(DOMAIN_CODE, TAG, 'deleteToTrash: selectFileOnly:' + selectFileOnly); 282 let newFileName = currentTrashParentPath + selectFileOnly; 283 // 移动文件 284 fs.moveFileSync(path, newFileName, 0); 285 } else { 286 // 待删除文件夹 287 let toDeleteDir = path.substring(posLastSlash); 288 // 移动待删除文件夹 289 fs.moveDirSync(selectPathOnly + toDeleteDir, currentTrashParentPath, MOVE_MODLE_CODE); 290 if (fs.accessSync(path)) { 291 fs.rmdirSync(path); 292 } 293 } 294 } catch (e) { 295 hilog.error(DOMAIN_CODE, TAG, 'deleteToTrash error ' + e.message); 296 return e.code; 297 } 298 return code; 299 } 300 301 delete(selectFileUri): number { 302 selectFileUri = decodeUri(selectFileUri); 303 if (!checkUri(selectFileUri)) { 304 return E_URIS; 305 } 306 let path = getPath(selectFileUri); 307 308 if (!path.startsWith(EXTERNAL_PATH)) { 309 return this.deleteToTrash(path); 310 } 311 312 let code = ERR_OK; 313 try { 314 let stat = fs.statSync(path); 315 if (stat.isDirectory()) { 316 fs.rmdirSync(path); 317 } else { 318 fs.unlinkSync(path); 319 } 320 } catch (e) { 321 hilog.error(DOMAIN_CODE, TAG, 'deleteFile error ' + e.message); 322 return e.code; 323 } 324 return code; 325 } 326 327 move(sourceFileUri, targetParentUri): {string, number} { 328 sourceFileUri = decodeUri(sourceFileUri); 329 targetParentUri = decodeUri(targetParentUri); 330 if (!checkUri(sourceFileUri) || !checkUri(targetParentUri)) { 331 return uriReturnObject('', E_URIS); 332 } 333 let displayName = this.getFileName(sourceFileUri); 334 let newFileUri = this.genNewFileUri(targetParentUri, displayName); 335 let oldPath = getPath(sourceFileUri); 336 let newPath = getPath(newFileUri); 337 newFileUri = encodePathOfUri(newFileUri); 338 if (newFileUri === '') { 339 return uriReturnObject('', E_URIS); 340 } 341 if (oldPath === newPath) { 342 // move to the same directory 343 return { 344 uri: newFileUri, 345 code: ERR_OK, 346 }; 347 } else if (newPath.indexOf(oldPath) === 0 && newPath.charAt(oldPath.length) === '/') { 348 // move to a subdirectory of the source directory 349 return uriReturnObject('', E_GETRESULT); 350 } 351 try { 352 // The source file does not exist or the destination is not a directory 353 let isAccess = fs.accessSync(oldPath); 354 let stat = fs.statSync(getPath(targetParentUri)); 355 let statOld = fs.statSync(oldPath); 356 if (!isAccess || !stat || !stat.isDirectory() || !statOld) { 357 return uriReturnObject('', E_GETRESULT); 358 } 359 // isDir 360 if (statOld.isDirectory()) { 361 fs.moveDirSync(oldPath, getPath(targetParentUri), MOVE_MODLE_CODE); 362 return uriReturnObject(newFileUri, ERR_OK); 363 } 364 // when targetFile is exist, delete it 365 let isAccessNewPath = fs.accessSync(newPath); 366 if (isAccessNewPath) { 367 fs.unlinkSync(newPath); 368 } 369 fs.moveFileSync(oldPath, newPath, 0); 370 return uriReturnObject(newFileUri, ERR_OK); 371 } catch (e) { 372 hilog.error(DOMAIN_CODE, TAG, 'move error ' + e.message); 373 return uriReturnObject('', e.code); 374 } 375 } 376 377 rename(sourceFileUri, displayName): {string, number} { 378 sourceFileUri = decodeUri(sourceFileUri); 379 if (!checkUri(sourceFileUri)) { 380 return uriReturnObject('', E_URIS); 381 } 382 try { 383 let newFileUri = this.renameUri(sourceFileUri, displayName); 384 let oldPath = getPath(sourceFileUri); 385 let newPath = getPath(newFileUri); 386 let isAccess = fs.accessSync(newPath); 387 if (isAccess) { 388 return uriReturnObject('', E_EXIST); 389 } 390 fs.renameSync(oldPath, newPath); 391 newFileUri = encodePathOfUri(newFileUri); 392 return uriReturnObject(newFileUri, ERR_OK); 393 } catch (e) { 394 hilog.error(DOMAIN_CODE, TAG, 'rename error ' + e.message); 395 return uriReturnObject('', e.code); 396 } 397 } 398 399 getReturnValue(sourceUri, destUri, errCode, errMsg, ret): {[], number} { 400 let copyResult = [ 401 { 402 sourceUri: sourceUri, 403 destUri: destUri, 404 errCode: errCode, 405 errMsg: errMsg, 406 }, 407 ]; 408 return resultsResultObject(copyResult, ret); 409 } 410 411 checkCopyArguments(sourceFileUri, targetParentUri): {[], number} { 412 if (!checkUri(sourceFileUri) || !checkUri(targetParentUri)) { 413 hilog.error(DOMAIN_CODE, TAG, 'check arguments error, invalid arguments'); 414 return this.getReturnValue(sourceFileUri, targetParentUri, E_URIS, '', EXCEPTION); 415 } 416 417 let displayName = this.getFileName(sourceFileUri); 418 let newFileOrDirUri = this.genNewFileUri(targetParentUri, displayName); 419 let oldPath = getPath(sourceFileUri); 420 let newPath = getPath(newFileOrDirUri); 421 if (oldPath === newPath) { 422 hilog.error(DOMAIN_CODE, TAG, 'the source and target files are the same file'); 423 return this.getReturnValue(sourceFileUri, targetParentUri, E_INVAL, '', NOEXCEPTION); 424 } else if (newPath.indexOf(oldPath) === 0 && newPath.charAt(oldPath.length) === '/') { 425 hilog.error(DOMAIN_CODE, TAG, 'copy to a subdirectory of the source directory'); 426 return this.getReturnValue(sourceFileUri, targetParentUri, E_FAULT, '', EXCEPTION); 427 } 428 429 try { 430 let isExist = fs.accessSync(oldPath); 431 if (!isExist) { 432 hilog.error(DOMAIN_CODE, TAG, 'source uri is not exist, invalid arguments'); 433 return this.getReturnValue(sourceFileUri, '', E_INVAL, '', NOEXCEPTION); 434 } 435 436 let stat = fs.statSync(getPath(targetParentUri)); 437 if (!stat || !stat.isDirectory()) { 438 hilog.error(DOMAIN_CODE, TAG, 'target is not directory, invalid arguments'); 439 return this.getReturnValue('', targetParentUri, E_INVAL, '', NOEXCEPTION); 440 } 441 } catch (e) { 442 hilog.error(DOMAIN_CODE, TAG, 'copy error ' + e.message); 443 return this.getReturnValue(sourceFileUri, targetParentUri, e.code, '', EXCEPTION); 444 } 445 return resultsResultObject([], ERR_OK); 446 } 447 448 processReturnValue(ret, copyRet): void { 449 if (ret.code === EXCEPTION) { 450 copyRet = ret; 451 } 452 if (ret.code === NOEXCEPTION) { 453 for (let index in ret.results) { 454 copyRet.results.push(ret.results[index]); 455 } 456 copyRet.code = ret.code; 457 } 458 } 459 460 copyFile(sourceFilePath, newFilePath): {[], number} { 461 let copyRet = { 462 results: [], 463 code: ERR_OK, 464 }; 465 466 try { 467 let isExist = fs.accessSync(newFilePath); 468 if (isExist) { 469 fs.unlinkSync(newFilePath); 470 } 471 fs.copyFileSync(sourceFilePath, newFilePath); 472 } catch (err) { 473 hilog.error(DOMAIN_CODE, TAG, 474 'copyFileSync failed with error message: ' + err.message + ', error code: ' + err.code); 475 return this.getReturnValue(encodePathOfUri(this.relativePath2uri(sourceFilePath)), '', err.code, err.message, EXCEPTION); 476 } 477 return copyRet; 478 } 479 480 copyDirectory(sourceFilePath, targetFilePath, mode): {[], number} { 481 let copyRet = { 482 results: [], 483 code: ERR_OK, 484 }; 485 try { 486 fs.copyDirSync(sourceFilePath, targetFilePath, mode); 487 } catch (err) { 488 if (err.code === E_EXIST) { 489 for (let i = 0; i < err.data.length; i++) { 490 hilog.error(DOMAIN_CODE, TAG, 491 'copy directory failed with conflicting files: ' + err.data[i].srcFile + ' ' + err.data[i].destFile); 492 let ret = this.getReturnValue( 493 encodePathOfUri(this.relativePath2uri(err.data[i].srcFile)), 494 encodePathOfUri(this.relativePath2uri(err.data[i].destFile)), 495 err.code, err.message, NOEXCEPTION); 496 this.processReturnValue(ret, copyRet); 497 } 498 return copyRet; 499 } 500 hilog.error(DOMAIN_CODE, TAG, 501 'copy directory failed with error message: ' + err.message + ', error code: ' + err.code); 502 return this.getReturnValue( 503 this.relativePath2uri(sourceFilePath), this.relativePath2uri(targetFilePath), 504 err.code, err.message, EXCEPTION); 505 } 506 return copyRet; 507 } 508 509 copy(sourceFileUri, targetParentUri, force): {[], number} { 510 sourceFileUri = decodeUri(sourceFileUri); 511 targetParentUri = decodeUri(targetParentUri); 512 let checkRet = this.checkCopyArguments(sourceFileUri, targetParentUri); 513 if (checkRet.code !== ERR_OK) { 514 return checkRet; 515 } 516 517 let sourceFilePath = getPath(sourceFileUri); 518 let targetFilePath = getPath(targetParentUri); 519 let displayName = this.getFileName(sourceFileUri); 520 let newFileOrDirUri = this.genNewFileUri(targetParentUri, displayName); 521 let newFilePath = getPath(newFileOrDirUri); 522 523 let stat = fs.statSync(sourceFilePath); 524 if (stat.isFile()) { 525 let isExist = fs.accessSync(newFilePath); 526 if (isExist && force === false) { 527 return this.getReturnValue(encodePathOfUri(sourceFileUri), encodePathOfUri(newFileOrDirUri), E_EXIST, '', NOEXCEPTION); 528 } 529 return this.copyFile(sourceFilePath, newFilePath); 530 } else if (stat.isDirectory()) { 531 let mode = force ? FILEOVERWRITE : THROWEXCEPTION; 532 let copyRet = this.copyDirectory(sourceFilePath, targetFilePath, mode); 533 return copyRet; 534 } else { 535 hilog.error(DOMAIN_CODE, TAG, 'the copy operation is not permitted'); 536 return this.getReturnValue(sourceFileUri, targetParentUri, E_PERM, '', EXCEPTION); 537 } 538 } 539 540 copyFileByFileName(sourceFileUri, targetParentUri, fileName): {string, number } { 541 sourceFileUri = decodeUri(sourceFileUri); 542 targetParentUri = decodeUri(targetParentUri); 543 if (!checkUri(sourceFileUri) || !checkUri(targetParentUri)) { 544 return uriReturnObject('', E_URIS); 545 } 546 547 let displayName = this.getFileName(sourceFileUri); 548 let newFileUri = this.genNewFileUri(targetParentUri, displayName); 549 let newFilePath = getPath(newFileUri); 550 newFileUri = encodePathOfUri(newFileUri); 551 552 if (newFileUri === '') { 553 return uriReturnObject('', E_URIS); 554 } 555 556 try { 557 let sourceFilePath = getPath(sourceFileUri); 558 let isAccess = fs.accessSync(sourceFilePath); 559 if (!isAccess) { 560 hilog.error(DOMAIN_CODE, TAG, 'sourceFilePath is not exist'); 561 return uriReturnObject('', E_GETRESULT); 562 } 563 let stat = fs.statSync(sourceFilePath); 564 if (!stat || stat.isDirectory()) { 565 hilog.error(DOMAIN_CODE, TAG, 'sourceFilePath is not file'); 566 return uriReturnObject('', E_URIS); 567 } 568 let statNew = fs.statSync(getPath(targetParentUri)); 569 if (!statNew || !statNew.isDirectory()) { 570 hilog.error(DOMAIN_CODE, TAG, 'targetParentUri is not directory'); 571 return uriReturnObject('', E_GETRESULT); 572 } 573 574 let isAccessNewFilePath = fs.accessSync(newFilePath); 575 if (isAccessNewFilePath) { 576 newFileUri = this.genNewFileUri(targetParentUri, fileName); 577 newFilePath = getPath(newFileUri); 578 if (fs.accessSync(newFilePath)) { 579 hilog.error(DOMAIN_CODE, TAG, 'fileName is exist'); 580 return uriReturnObject('', E_EXIST); 581 } 582 } 583 newFileUri = encodePathOfUri(newFileUri); 584 fs.copyFileSync(sourceFilePath, newFilePath); 585 return uriReturnObject(newFileUri, ERR_OK); 586 } catch (e) { 587 hilog.error(DOMAIN_CODE, TAG, 'copyFile error :' + e.message); 588 return uriReturnObject('', e.code); 589 } 590 } 591 592 access(sourceFileUri): {boolean, number} { 593 sourceFileUri = decodeUri(sourceFileUri); 594 if (sourceFileUri === '') { 595 return uriReturnObject('', E_URIS); 596 } 597 if (!checkUri(sourceFileUri)) { 598 hilog.error(DOMAIN_CODE, TAG, 'access checkUri fail'); 599 return boolReturnObject(false, E_URIS); 600 } 601 let isAccess = false; 602 try { 603 let path = getPath(sourceFileUri); 604 isAccess = fs.accessSync(path); 605 if (!isAccess) { 606 return boolReturnObject(false, ERR_OK); 607 } 608 } catch (e) { 609 hilog.error(DOMAIN_CODE, TAG, 'access error ' + e.message); 610 return boolReturnObject(false, e.code); 611 } 612 return boolReturnObject(true, ERR_OK); 613 } 614 615 getFileInfoNum(sourceFileUri: string, filter: Filter, recursion: boolean) : {boolean, number} { 616 let path = getPath(sourceFileUri); 617 try { 618 let statPath = fs.statSync(path); 619 if (!statPath.isDirectory()) { 620 return {success: false, counts: 0}; 621 } 622 let options; 623 if (hasFilter(filter)) { 624 options = buildFilterOptions(filter, 0, recursion); 625 } else { 626 options = buildNoFilterOptions(0, recursion); 627 } 628 let fileNameList = fs.listFileSync(path, options); 629 return {success: true, counts: fileNameList.length}; 630 } catch (e) { 631 hilog.error(DOMAIN_CODE, TAG, `getFileInfoNum error: ${e.message},code: ${e.code}`); 632 return {success: false, counts: 0}; 633 } 634 } 635 636 listFile(sourceFileUri: string, offset: number, count: number, filter: Filter) : 637 {infos: Fileinfo[], code: number} { 638 let infos : Fileinfo[] = []; 639 sourceFileUri = decodeUri(sourceFileUri); 640 if (!checkUri(sourceFileUri)) { 641 return infosReturnObject([], E_URIS); 642 } 643 return getListFileInfos(sourceFileUri, offset, count, filter, false); 644 } 645 646 scanFile(sourceFileUri: string, offset: number, count: number, filter: Filter) : 647 {infos: Fileinfo[], code: number} { 648 let infos : Fileinfo[] = []; 649 sourceFileUri = decodeUri(sourceFileUri); 650 if (!checkUri(sourceFileUri)) { 651 return infosReturnObject([], E_URIS); 652 } 653 654 return getScanFileInfos(sourceFileUri, offset, count, filter, true); 655 } 656 657 getFileInfoFromUri(selectFileUri) { 658 selectFileUri = decodeUri(selectFileUri); 659 if (selectFileUri === '') { 660 return uriReturnObject('', E_URIS); 661 } 662 663 if (!checkUri(selectFileUri)) { 664 return fileinfoReturnObject({}, E_URIS); 665 } 666 let fileInfo = {}; 667 try { 668 let path = getPath(selectFileUri); 669 let fileName = this.getFileName(path); 670 let stat = fs.statSync(path); 671 let mode = documentFlag.SUPPORTS_READ | documentFlag.SUPPORTS_WRITE; 672 if (stat.isDirectory()) { 673 mode |= documentFlag.REPRESENTS_DIR; 674 } else { 675 mode |= documentFlag.REPRESENTS_FILE; 676 } 677 selectFileUri = encodePathOfUri(selectFileUri); 678 fileInfo = { 679 uri: selectFileUri, 680 relativePath: path, 681 fileName: fileName, 682 mode: mode, 683 size: stat.size, 684 mtime: stat.mtime, 685 mimeType: '', 686 }; 687 } catch (e) { 688 hilog.error(DOMAIN_CODE, TAG, 'getFileInfoFromUri error ' + e.message); 689 return fileinfoReturnObject({}, e.code); 690 } 691 return fileinfoReturnObject(fileInfo, ERR_OK); 692 } 693 694 checkRelativePath(selectFileRelativePath): boolean { 695 try { 696 // Processing format: The first character is '/' 697 if (selectFileRelativePath !== undefined && selectFileRelativePath.indexOf('/') === 0) { 698 hilog.info(DOMAIN_CODE, TAG, 'checkRelativePath-path is ' + selectFileRelativePath); 699 return true; 700 } else { 701 hilog.error(DOMAIN_CODE, TAG, 'checkRelativePath error, path is ' + selectFileRelativePath); 702 return false; 703 } 704 } catch (error) { 705 hilog.error(DOMAIN_CODE, TAG, 'checkRelativePath error, path is ' + selectFileRelativePath); 706 return false; 707 } 708 } 709 710 /* 711 * selectFileRelativePath formate: /storage/Users/currentUser/filename 712 */ 713 getFileInfoFromRelativePath(selectFileRelativePath): {fileInfo:object, code:number} { 714 let fileInfo = {}; 715 if (!this.checkRelativePath(selectFileRelativePath)) { 716 return fileinfoReturnObject({}, E_INVAL); 717 } 718 try { 719 // Processing format: Delete the last '/' 720 if (selectFileRelativePath.charAt(selectFileRelativePath.length - 1) === '/') { 721 selectFileRelativePath = selectFileRelativePath.substr(0, selectFileRelativePath.length - 1); 722 } 723 let fileName = this.getFileName(selectFileRelativePath); 724 let stat = fs.statSync(selectFileRelativePath); 725 let mode = documentFlag.SUPPORTS_READ | documentFlag.SUPPORTS_WRITE; 726 if (stat.isDirectory()) { 727 mode |= documentFlag.REPRESENTS_DIR; 728 } else { 729 mode |= documentFlag.REPRESENTS_FILE; 730 } 731 let selectFileUri = encodePathOfUri(this.relativePath2uri(selectFileRelativePath)); 732 fileInfo = { 733 uri: selectFileUri, 734 relativePath: selectFileRelativePath, 735 fileName: fileName, 736 mode: mode, 737 size: stat.size, 738 mtime: stat.mtime, 739 mimeType: '', 740 }; 741 } catch (e) { 742 hilog.error(DOMAIN_CODE, TAG, 'getFileInfoFromRelativePath error ' + e.message); 743 return fileinfoReturnObject({}, e.code); 744 } 745 return fileinfoReturnObject(fileInfo, ERR_OK); 746 } 747 748 relativePath2uri(path): string { 749 return `file://docs${path}`; 750 } 751 752 volumePath2uri(path): string { 753 return `file://docs/storage/External/${path}`; 754 } 755 756 hmdfsPath2uri(path): string { 757 return `file://docs/storage/hmdfs/${path}`; 758 } 759 760 getHmdfsPath(): {}[] { 761 let rootPathHmdfs = '/storage/hmdfs'; 762 let hmdfsInfoList = []; 763 let hmdfsName = fs.listFileSync(rootPathHmdfs); 764 for (let i = 0; i < hmdfsName.length; i++) { 765 let hmdfsInfo = { 766 uri: this.hmdfsPath2uri(hmdfsName[i]), 767 displayName: hmdfsName[i], 768 relativePath: '/storage/hmdfs/' + hmdfsName[i], 769 deviceType: deviceType.DEVICE_SHARED_TERMINAL, 770 deviceFlags: deviceFlag.SUPPORTS_READ | deviceFlag.SUPPORTS_WRITE, 771 }; 772 hilog.info(DOMAIN_CODE, TAG, `df count: ${hmdfsInfo.length}`); 773 hmdfsInfoList.push(hmdfsInfo); 774 } 775 return hmdfsInfoList; 776 } 777 778 getRoots() { 779 let roots = [ 780 { 781 uri: 'file://docs/storage/Users/currentUser', 782 displayName: 'currentUser', 783 relativePath: '/storage/Users/currentUser', 784 deviceType: deviceType.DEVICE_LOCAL_DISK, 785 deviceFlags: deviceFlag.SUPPORTS_READ | deviceFlag.SUPPORTS_WRITE, 786 }, 787 { 788 uri: 'file://docs/storage/Share', 789 displayName: 'shared_disk', 790 relativePath: '/storage/Share', 791 deviceType: deviceType.DEVICE_SHARED_DISK, 792 deviceFlags: deviceFlag.SUPPORTS_READ | deviceFlag.SUPPORTS_WRITE, 793 } 794 ]; 795 try { 796 let rootPath = '/storage/External'; 797 let volumeInfoList = []; 798 let volumeName = fs.listFileSync(rootPath); 799 for (let i = 0; i < volumeName.length; i++) { 800 let volumeInfo = { 801 uri: this.volumePath2uri(volumeName[i]), 802 displayName: volumeName[i], 803 relativePath: '/storage/External/' + volumeName[i], 804 deviceType: deviceType.DEVICE_EXTERNAL_USB, 805 deviceFlags: deviceFlag.SUPPORTS_READ | deviceFlag.SUPPORTS_WRITE, 806 }; 807 volumeInfoList.push(volumeInfo); 808 } 809 roots = roots.concat(volumeInfoList); 810 hilog.info(DOMAIN_CODE, TAG, `External file count: ${volumeInfoList.length}`); 811 try { 812 roots = roots.concat(getHmdfsPath()); 813 } catch (e) { 814 hilog.info(DOMAIN_CODE, TAG, 'getRoots errorcode: ' + e.code, ' message: ' + e.message); 815 } 816 817 return rootsReturnObject(roots, ERR_OK); 818 } catch (e) { 819 hilog.error(DOMAIN_CODE, TAG, 'getRoots errorcode: ' + e.code, ' message: ' + e.message); 820 return rootsReturnObject([], e.code); 821 } 822 } 823 824 getNormalResult(dirPath, column, queryResults): void { 825 if (column === 'display_name') { 826 let index = dirPath.lastIndexOf('/'); 827 let target = dirPath.substring(index + 1, ); 828 queryResults.push(String(target)); 829 } else if (column === 'relative_path') { 830 queryResults.push(dirPath); 831 } else { 832 queryResults.push(''); 833 } 834 } 835 836 getResultFromStat(dirPath, column, stat, queryResults): void { 837 if (column === 'size' && stat.isDirectory()) { 838 let size = 0; 839 this.recurseDir(dirPath, function (filePath, isDirectory) { 840 if (!isDirectory) { 841 let fileStat = fs.statSync(filePath); 842 size += fileStat.size; 843 } 844 }); 845 queryResults.push(String(size)); 846 } else { 847 queryResults.push(String(stat[column])); 848 } 849 } 850 851 query(uri, columns): {[], number} { 852 uri = decodeUri(uri); 853 if (uri === '') { 854 return uriReturnObject('', E_URIS); 855 } 856 857 if (!checkUri(uri)) { 858 return resultsResultObject([], E_URIS); 859 } 860 861 fs.access(uri, (err, res) => { 862 if (err) { 863 return { 864 results: [], 865 code: E_NOEXIST, 866 }; 867 } else { 868 if (res) { 869 console.info('file exists'); 870 } 871 } 872 }); 873 874 let queryResults = []; 875 try { 876 let dirPath = getPath(uri); 877 let stat = fs.statSync(dirPath); 878 for (let index in columns) { 879 let column = columns[index]; 880 if (column in stat) { 881 this.getResultFromStat(dirPath, column, stat, queryResults); 882 } else { 883 this.getNormalResult(dirPath, column, queryResults); 884 } 885 } 886 } catch (e) { 887 hilog.error(DOMAIN_CODE, TAG, 'query error ' + e.message); 888 return resultsResultObject([], E_GETRESULT); 889 } 890 return resultsResultObject(queryResults, ERR_OK); 891 } 892 893 isDeviceUri(uri): boolean { 894 let tempUri = uri.slice(0, uri.lastIndexOf('/')); 895 let deviceUris = fileAccess.DeviceRoots; 896 if (deviceUris.indexOf(tempUri) !== -1) { 897 return true; 898 } 899 return false; 900 } 901 902 startWatcher(uri, callback): number { 903 uri = decodeUri(uri); 904 if (!checkUri(uri)) { 905 return E_URIS; 906 } 907 let watchPath = getPath(uri); 908 try { 909 if (!observerMap.has(uri)) { 910 let watcher = fs.createWatcher(watchPath, CREATE_EVENT_CODE | IN_DELETE_EVENT_CODE | DELETE_SELF_EVENT_CODE | 911 MOVE_TO_CODE | MOVED_FROM_CODE | MOVE_SELF_CODE, (data) => { 912 try { 913 let eventCode = -1; 914 let targetUri = FILE_PREFIX_NAME + BUNDLE_NAME + data.fileName; 915 let tempMap = eventMap; 916 if (this.isDeviceUri(targetUri)) { 917 tempMap = deviceOnlineMap; 918 } 919 tempMap.forEach((value, key) => { 920 if (data.event & key) { 921 eventCode = value; 922 } 923 }); 924 targetUri = encodePathOfUri(targetUri); 925 if (eventCode >= 0) { 926 callback(targetUri, eventCode); 927 } 928 } catch (error) { 929 hilog.error(DOMAIN_CODE, TAG, 'onchange error ' + error.message); 930 } 931 }); 932 watcher.start(); 933 observerMap.set(uri, watcher); 934 } else { 935 hilog.warn(DOMAIN_CODE, TAG, 'uri already exists'); 936 } 937 } catch (e) { 938 hilog.error(DOMAIN_CODE, TAG, 'startWatcher error ' + e.message); 939 return E_GETRESULT; 940 } 941 return ERR_OK; 942 } 943 944 stopWatcher(uri): number { 945 uri = decodeUri(uri); 946 if (!checkUri(uri)) { 947 return E_URIS; 948 } 949 try { 950 if (!observerMap.has(uri)) { 951 return E_GETRESULT; 952 } 953 let watcher = observerMap.get(uri); 954 if (typeof watcher !== undefined) { 955 watcher.stop(); 956 observerMap.delete(uri); 957 } 958 } catch (e) { 959 hilog.error(DOMAIN_CODE, TAG, 'stopWatcher error ' + e.message); 960 return E_GETRESULT; 961 } 962 return ERR_OK; 963 } 964 965 moveForFile(sourceFilePath, newFilePath): { [], number } { 966 let copyRet = { 967 results: [], 968 code: ERR_OK, 969 }; 970 971 try { 972 let isExist = fs.accessSync(newFilePath); 973 if (isExist) { 974 fs.unlinkSync(newFilePath); 975 } 976 fs.moveFileSync(sourceFilePath, newFilePath, 1); 977 } catch (err) { 978 hilog.error(DOMAIN_CODE, TAG, 'moveFileSync failed with error message: ' + err.message + ', error code: ' + err.code); 979 return this.getReturnValue(encodePathOfUri(this.relativePath2uri(sourceFilePath)), '', err.code, err.message, NOEXCEPTION); 980 } 981 return copyRet; 982 } 983 984 moveDirectory(sourceFilePath, targetFilePath, force): { [], number } { 985 let copyRet = { 986 results: [], 987 code: ERR_OK, 988 }; 989 let mode = force ? MOVEFILEOVERWRITE : FILEOVERWRITE; 990 try { 991 fs.moveDirSync(sourceFilePath, targetFilePath, mode); 992 } catch (err) { 993 if (err.code === E_EXIST) { 994 for (let i = 0; i < err.data.length; i++) { 995 hilog.error(DOMAIN_CODE, TAG, 996 'move directory failed with conflicting files: ' + err.data[i].srcFile + ' ' + err.data[i].destFile); 997 let srcStat = fs.statSync(err.data[i].srcFile); 998 let dstStat = fs.statSync(err.data[i].destFile); 999 let errCode = undefined; 1000 if (srcStat.isDirectory() && dstStat.isFile()) { 1001 errCode = E_NOT_DIR; 1002 } else if (srcStat.isFile() && dstStat.isDirectory()) { 1003 errCode = E_IS_DIR; 1004 } else { 1005 errCode = err.code; 1006 } 1007 let ret = this.getReturnValue( 1008 encodePathOfUri(this.relativePath2uri(err.data[i].srcFile)), 1009 encodePathOfUri(this.relativePath2uri(err.data[i].destFile)), 1010 errCode, err.message, NOEXCEPTION); 1011 this.processReturnValue(ret, copyRet); 1012 } 1013 return copyRet; 1014 } 1015 return this.getReturnValue( 1016 this.relativePath2uri(sourceFilePath), this.relativePath2uri(targetFilePath), 1017 err.code, err.message, EXCEPTION); 1018 } 1019 return copyRet; 1020 } 1021 1022 moveItem(sourceFileUri, targetParentUri, force): { [], number } { 1023 sourceFileUri = decodeUri(sourceFileUri); 1024 targetParentUri = decodeUri(targetParentUri); 1025 if (!checkUri(sourceFileUri) || !checkUri(targetParentUri)) { 1026 hilog.error(DOMAIN_CODE, TAG, 'check arguments error, invalid arguments'); 1027 return this.getReturnValue(sourceFileUri, targetParentUri, E_URIS, EXCEPTION); 1028 } 1029 let displayName = this.getFileName(sourceFileUri); 1030 let newFileUri = this.genNewFileUri(targetParentUri, displayName); 1031 let newPathDir = getPath(targetParentUri); 1032 let oldPath = getPath(sourceFileUri); 1033 let newPath = getPath(newFileUri); 1034 newFileUri = encodePathOfUri(newFileUri); 1035 if (newFileUri === '') { 1036 return this.getReturnValue(sourceFileUri, targetParentUri, E_URIS, EXCEPTION); 1037 } 1038 if (oldPath === newPath) { 1039 return this.getReturnValue(sourceFileUri, newFileOrDirUri, ERR_OK, '', EXCEPTION); 1040 } else if (newPath.indexOf(oldPath) === 0 && newPath.charAt(oldPath.length) === '/') { 1041 return this.getReturnValue(sourceFileUri, targetParentUri, E_GETRESULT, '', NOEXCEPTION); 1042 } 1043 try { 1044 let stat = fs.statSync(getPath(targetParentUri)); 1045 let statOld = fs.statSync(oldPath); 1046 if (!fs.accessSync(oldPath) || !stat || !stat.isDirectory() || !statOld) { 1047 hilog.error(DOMAIN_CODE, TAG, 'operate illegal'); 1048 return this.getReturnValue(sourceFileUri, targetParentUri, E_GETRESULT, '', EXCEPTION); 1049 } 1050 if (statOld.isFile()) { 1051 hilog.info(DOMAIN_CODE, TAG, 'sourceUri is file'); 1052 let isExist = fs.accessSync(newPath); 1053 if (isExist && fs.statSync(newPath).isDirectory()) { 1054 return this.getReturnValue(sourceFileUri, newFileUri, E_IS_DIR, '', NOEXCEPTION); 1055 } 1056 if (isExist && force === false) { 1057 return this.getReturnValue(sourceFileUri, newFileUri, E_EXIST, '', NOEXCEPTION); 1058 } else { 1059 return this.moveForFile(oldPath, newPath); 1060 } 1061 } else if (statOld.isDirectory()) { 1062 hilog.info(DOMAIN_CODE, TAG, 'sourceUri is dir'); 1063 return this.moveDirectory(oldPath, newPathDir, force); 1064 } else { 1065 hilog.error(DOMAIN_CODE, TAG, 'the move operation is not permitted'); 1066 return this.getReturnValue(sourceFileUri, targetParentUri, E_PERM, '', EXCEPTION); 1067 } 1068 } catch (err) { 1069 hilog.error(DOMAIN_CODE, TAG, 'error message: ' + err.message + ', error code: ' + err.code); 1070 return this.getReturnValue(sourceFileUri, targetParentUri, err.code, err.message, EXCEPTION); 1071 } 1072 } 1073 1074 moveFile(sourceFileUri, targetParentUri, fileName): { string, number } { 1075 sourceFileUri = decodeUri(sourceFileUri); 1076 targetParentUri = decodeUri(targetParentUri); 1077 if (!checkUri(sourceFileUri) || !checkUri(targetParentUri)) { 1078 return uriReturnObject('', E_URIS); 1079 } 1080 let displayName = this.getFileName(sourceFileUri); 1081 let newFileUri = this.genNewFileUri(targetParentUri, displayName); 1082 let fixedUri = this.genNewFileUri(targetParentUri, fileName); 1083 let oldPath = getPath(sourceFileUri); 1084 let newPath = getPath(newFileUri); 1085 let fixedPath = getPath(fixedUri); 1086 fixedUri = encodePathOfUri(fixedUri); 1087 newFileUri = encodePathOfUri(newFileUri); 1088 if (newFileUri === '') { 1089 return uriReturnObject('', E_URIS); 1090 } 1091 if (oldPath === newPath) { 1092 // move to the same directory 1093 return { 1094 uri: newFileUri, 1095 code: ERR_OK, 1096 }; 1097 } 1098 try { 1099 // The source file does not exist or the destination is not a directory 1100 let isAccess = fs.accessSync(oldPath); 1101 let stat = fs.statSync(getPath(targetParentUri)); 1102 let statOld = fs.statSync(oldPath); 1103 if (!isAccess || !stat || !stat.isDirectory() || !statOld) { 1104 return uriReturnObject('', E_GETRESULT); 1105 } 1106 // isDir 1107 if (statOld.isDirectory()) { 1108 return uriReturnObject('', E_URIS); 1109 } 1110 1111 let isAccessNewPath = fs.accessSync(newPath); 1112 if (isAccessNewPath) { 1113 if (fs.accessSync(fixedPath)) { 1114 hilog.error(DOMAIN_CODE, TAG, 'fileName is exist'); 1115 return uriReturnObject('', E_EXIST); 1116 } 1117 fs.moveFileSync(oldPath, fixedPath, 0); 1118 return uriReturnObject(fixedUri, ERR_OK); 1119 } 1120 fs.moveFileSync(oldPath, newPath, 0); 1121 return uriReturnObject(newFileUri, ERR_OK); 1122 } catch (e) { 1123 hilog.error(DOMAIN_CODE, TAG, 'move error ' + e.message); 1124 return uriReturnObject('', e.code); 1125 } 1126 } 1127}; 1128