status_t Inode::Create(const char* name, int mode, int perms, OpenFileCookie* cookie, OpenDelegationData* data, ino_t* id) { ASSERT(name != NULL); ASSERT(cookie != NULL); ASSERT(data != NULL); cookie->fMode = mode; cookie->fLocks = NULL; OpenState* state = new(std::nothrow) OpenState; if (state == NULL) return B_NO_MEMORY; status_t result = CreateState(name, mode, perms, state, data); if (result != B_OK) { delete state; return result; } cookie->fOpenState = state; cookie->fFileSystem = fFileSystem; *id = FileIdToInoT(state->fInfo.fFileId); fFileSystem->AddOpenFile(state); fFileSystem->Root()->MakeInfoInvalid(); notify_entry_created(fFileSystem->DevId(), ID(), name, *id); return B_OK; }
static status_t ext2_create_dir(fs_volume* _volume, fs_vnode* _directory, const char* name, int mode) { TRACE("ext2_create_dir()\n"); Volume* volume = (Volume*)_volume->private_volume; Inode* directory = (Inode*)_directory->private_node; if (volume->IsReadOnly()) return B_READ_ONLY_DEVICE; if (!directory->IsDirectory()) return B_BAD_TYPE; status_t status = directory->CheckPermissions(W_OK); if (status != B_OK) return status; TRACE("ext2_create_dir(): Starting transaction\n"); Transaction transaction(volume->GetJournal()); ino_t id; status = Inode::Create(transaction, directory, name, S_DIRECTORY | (mode & S_IUMSK), 0, EXT2_TYPE_DIRECTORY, NULL, &id); if (status != B_OK) return status; put_vnode(volume->FSVolume(), id); entry_cache_add(volume->ID(), directory->ID(), name, id); status = transaction.Done(); if (status != B_OK) { entry_cache_remove(volume->ID(), directory->ID(), name); return status; } notify_entry_created(volume->ID(), directory->ID(), name, id); TRACE("ext2_create_dir(): Done\n"); return B_OK; }
// _HandleRequest status_t KernelRequestHandler::_HandleRequest(NotifyListenerRequest* request) { // check and execute the request status_t result = B_OK; if (fVolume && request->device != fVolume->GetID()) result = B_BAD_VALUE; // get the names // name char* name = (char*)request->name.GetData(); int32 nameLen = request->name.GetSize(); if (name && (nameLen <= 0)) name = NULL; else if (name) name[nameLen - 1] = '\0'; // NULL-terminate to be safe // old name char* oldName = (char*)request->oldName.GetData(); int32 oldNameLen = request->oldName.GetSize(); if (oldName && (oldNameLen <= 0)) oldName = NULL; else if (oldName) oldName[oldNameLen - 1] = '\0'; // NULL-terminate to be safe // check the names if (result == B_OK) { switch (request->operation) { case B_ENTRY_MOVED: if (!oldName) { ERROR(("NotifyListenerRequest: NULL oldName for " "B_ENTRY_MOVED\n")); result = B_BAD_VALUE; break; } // fall through... case B_ENTRY_CREATED: case B_ENTRY_REMOVED: case B_ATTR_CHANGED: if (!name) { ERROR(("NotifyListenerRequest: NULL name for opcode: %" B_PRId32 "\n", request->operation)); result = B_BAD_VALUE; } break; case B_STAT_CHANGED: break; } } // execute the request if (result == B_OK) { switch (request->operation) { case B_ENTRY_CREATED: PRINT(("notify_entry_created(%" B_PRId32 ", %" B_PRId64 ", " "\"%s\", %" B_PRId64 ")\n", request->device, request->directory, name, request->node)); result = notify_entry_created(request->device, request->directory, name, request->node); break; case B_ENTRY_REMOVED: PRINT(("notify_entry_removed(%" B_PRId32 ", %" B_PRId64 ", " "\"%s\", %" B_PRId64 ")\n", request->device, request->directory, name, request->node)); result = notify_entry_removed(request->device, request->directory, name, request->node); break; case B_ENTRY_MOVED: PRINT(("notify_entry_moved(%" B_PRId32 ", %" B_PRId64 ", " "\"%s\", %" B_PRId64 ", \"%s\", %" B_PRId64 ")\n", request->device, request->oldDirectory, oldName, request->directory, name, request->node)); result = notify_entry_moved(request->device, request->oldDirectory, oldName, request->directory, name, request->node); break; case B_STAT_CHANGED: PRINT(("notify_stat_changed(%" B_PRId32 ", %" B_PRId64 ", " "0x%" B_PRIx32 ")\n", request->device, request->node, request->details)); result = notify_stat_changed(request->device, request->node, request->details); break; case B_ATTR_CHANGED: PRINT(("notify_attribute_changed(%" B_PRId32 ", %" B_PRId64 ", " "\"%s\", 0x%" B_PRIx32 ")\n", request->device, request->node, name, (int32)request->details)); result = notify_attribute_changed(request->device, request->node, name, (int32)request->details); break; default: ERROR(("NotifyQueryRequest: unsupported operation: %" B_PRId32 "\n", request->operation)); result = B_BAD_VALUE; break; } } // prepare the reply RequestAllocator allocator(fPort->GetPort()); NotifyListenerReply* reply; status_t error = AllocateRequest(allocator, &reply); if (error != B_OK) return error; reply->error = result; // send the reply return fPort->SendRequest(&allocator); }
static status_t ext2_create_symlink(fs_volume* _volume, fs_vnode* _directory, const char* name, const char* path, int mode) { TRACE("ext2_create_symlink()\n"); Volume* volume = (Volume*)_volume->private_volume; Inode* directory = (Inode*)_directory->private_node; if (volume->IsReadOnly()) return B_READ_ONLY_DEVICE; if (!directory->IsDirectory()) return B_BAD_TYPE; status_t status = directory->CheckPermissions(W_OK); if (status != B_OK) return status; TRACE("ext2_create_symlink(): Starting transaction\n"); Transaction transaction(volume->GetJournal()); Inode* link; ino_t id; status = Inode::Create(transaction, directory, name, S_SYMLINK | 0777, 0, (uint8)EXT2_TYPE_SYMLINK, NULL, &id, &link); if (status != B_OK) return status; // TODO: We have to prepare the link before publishing? size_t length = strlen(path); TRACE("ext2_create_symlink(): Path (%s) length: %d\n", path, (int)length); if (length < EXT2_SHORT_SYMLINK_LENGTH) { strcpy(link->Node().symlink, path); link->Node().SetSize((uint32)length); TRACE("ext2_create_symlink(): Publishing vnode\n"); publish_vnode(volume->FSVolume(), id, link, &gExt2VnodeOps, link->Mode(), 0); put_vnode(volume->FSVolume(), id); } else { TRACE("ext2_create_symlink(): Publishing vnode\n"); publish_vnode(volume->FSVolume(), id, link, &gExt2VnodeOps, link->Mode(), 0); put_vnode(volume->FSVolume(), id); if (!link->HasFileCache()) { status = link->CreateFileCache(); if (status != B_OK) return status; } size_t written = length; status = link->WriteAt(transaction, 0, (const uint8*)path, &written); if (status == B_OK && written != length) status = B_IO_ERROR; } if (status == B_OK) status = link->WriteBack(transaction); entry_cache_add(volume->ID(), directory->ID(), name, id); status = transaction.Done(); if (status != B_OK) { entry_cache_remove(volume->ID(), directory->ID(), name); return status; } notify_entry_created(volume->ID(), directory->ID(), name, id); TRACE("ext2_create_symlink(): Done\n"); return status; }
static status_t ext2_create(fs_volume* _volume, fs_vnode* _directory, const char* name, int openMode, int mode, void** _cookie, ino_t* _vnodeID) { Volume* volume = (Volume*)_volume->private_volume; Inode* directory = (Inode*)_directory->private_node; TRACE("ext2_create()\n"); if (volume->IsReadOnly()) return B_READ_ONLY_DEVICE; if (!directory->IsDirectory()) return B_BAD_TYPE; TRACE("ext2_create(): Creating cookie\n"); // Allocate cookie file_cookie* cookie = new(std::nothrow) file_cookie; if (cookie == NULL) return B_NO_MEMORY; ObjectDeleter<file_cookie> cookieDeleter(cookie); cookie->open_mode = openMode; cookie->last_size = 0; cookie->last_notification = system_time(); TRACE("ext2_create(): Starting transaction\n"); Transaction transaction(volume->GetJournal()); TRACE("ext2_create(): Creating inode\n"); Inode* inode; bool created; status_t status = Inode::Create(transaction, directory, name, S_FILE | (mode & S_IUMSK), openMode, EXT2_TYPE_FILE, &created, _vnodeID, &inode, &gExt2VnodeOps); if (status != B_OK) return status; TRACE("ext2_create(): Created inode\n"); if ((openMode & O_NOCACHE) != 0) { status = inode->DisableFileCache(); if (status != B_OK) return status; } entry_cache_add(volume->ID(), directory->ID(), name, *_vnodeID); status = transaction.Done(); if (status != B_OK) { entry_cache_remove(volume->ID(), directory->ID(), name); return status; } *_cookie = cookie; cookieDeleter.Detach(); if (created) notify_entry_created(volume->ID(), directory->ID(), name, *_vnodeID); return B_OK; }