* Commits a new file (well, a FILE or a DIRECTORY) to the file system with * the given mode. * Note: This will commit the transaction. * @param p The path to the new file. * @param type The type of the new file. * @param mode The mode to create the new file with. * @param data The
(tx: AsyncKeyValueRWTransaction, p: string, type: FileType, mode: number, data: Buffer, cb: BFSCallback<Inode>)
| 1155 | * @param cb Passed an error or the Inode for the new file. |
| 1156 | */ |
| 1157 | private commitNewFile(tx: AsyncKeyValueRWTransaction, p: string, type: FileType, mode: number, data: Buffer, cb: BFSCallback<Inode>): void { |
| 1158 | const parentDir = path.dirname(p), |
| 1159 | fname = path.basename(p), |
| 1160 | currTime = (new Date()).getTime(); |
| 1161 | |
| 1162 | // Invariant: The root always exists. |
| 1163 | // If we don't check this prior to taking steps below, we will create a |
| 1164 | // file with name '' in root should p == '/'. |
| 1165 | if (p === '/') { |
| 1166 | return cb(ApiError.EEXIST(p)); |
| 1167 | } |
| 1168 | |
| 1169 | // Let's build a pyramid of code! |
| 1170 | |
| 1171 | // Step 1: Get the parent directory's inode and directory listing |
| 1172 | this.findINodeAndDirListing(tx, parentDir, (e?: ApiError | null, parentNode?: Inode, dirListing?: {[name: string]: string}): void => { |
| 1173 | if (noErrorTx(e, tx, cb)) { |
| 1174 | if (dirListing![fname]) { |
| 1175 | // File already exists. |
| 1176 | tx.abort(() => { |
| 1177 | cb(ApiError.EEXIST(p)); |
| 1178 | }); |
| 1179 | } else { |
| 1180 | // Step 2: Commit data to store. |
| 1181 | this.addNewNode(tx, data, (e: ApiError, dataId?: string): void => { |
| 1182 | if (noErrorTx(e, tx, cb)) { |
| 1183 | // Step 3: Commit the file's inode to the store. |
| 1184 | const fileInode = new Inode(dataId!, data.length, mode | type, currTime, currTime, currTime); |
| 1185 | this.addNewNode(tx, fileInode.toBuffer(), (e: ApiError, fileInodeId?: string): void => { |
| 1186 | if (noErrorTx(e, tx, cb)) { |
| 1187 | // Step 4: Update parent directory's listing. |
| 1188 | dirListing![fname] = fileInodeId!; |
| 1189 | tx.put(parentNode!.id, Buffer.from(JSON.stringify(dirListing)), true, (e: ApiError): void => { |
| 1190 | if (noErrorTx(e, tx, cb)) { |
| 1191 | // Step 5: Commit and return the new inode. |
| 1192 | tx.commit((e?: ApiError): void => { |
| 1193 | if (noErrorTx(e, tx, cb)) { |
| 1194 | cb(null, fileInode); |
| 1195 | } |
| 1196 | }); |
| 1197 | } |
| 1198 | }); |
| 1199 | } |
| 1200 | }); |
| 1201 | } |
| 1202 | }); |
| 1203 | } |
| 1204 | } |
| 1205 | }); |
| 1206 | } |
| 1207 | |
| 1208 | /** |
| 1209 | * Remove all traces of the given path from the file system. |
no test coverage detected