Exemple #1
0
void 
ClientLayerManager::MakeSnapshotIfRequired()
{
  if (!mShadowTarget) {
    return;
  }
  if (mWidget) {
    if (CompositorChild* remoteRenderer = GetRemoteRenderer()) {
      nsIntRect bounds;
      mWidget->GetBounds(bounds);
      SurfaceDescriptor inSnapshot, snapshot;
      if (AllocSurfaceDescriptor(bounds.Size(),
                                 gfxASurface::CONTENT_COLOR_ALPHA,
                                 &inSnapshot) &&
          // The compositor will usually reuse |snapshot| and return
          // it through |outSnapshot|, but if it doesn't, it's
          // responsible for freeing |snapshot|.
          remoteRenderer->SendMakeSnapshot(inSnapshot, &snapshot)) {
        AutoOpenSurface opener(OPEN_READ_ONLY, snapshot);
        gfxASurface* source = opener.Get();

        mShadowTarget->DrawSurface(source, source->GetSize());
      }
      if (IsSurfaceDescriptorValid(snapshot)) {
        ShadowLayerForwarder::DestroySharedSurface(&snapshot);
      }
    }
  }
  mShadowTarget = nullptr;
}
Exemple #2
0
FileHandle_t VirtualFunctionHooks::IBaseFileSystem__Open(const char *pFileName, const char *pOptions, const char *pathID) {
	IBaseFileSystem *ths = (IBaseFileSystem *)this;
	std::string relative_path, full_path;
	
	if (pathID && strcmp("SKIN", pathID))
		if (FunctionHooks->mainthread == ThreadGetCurrentId()) {

			try {
				ToFull(pFileName, pathID, full_path);
				RelativeFrom(full_path, "BASE_PATH", relative_path);
			}
			catch (std::exception e) {
				return 0;
			}

			OpenResult opener(relative_path, full_path);
			if (!opener.GetResult())
				return 0;
		}
		else {
			FSLog(std::string("Path ID ") + (pathID ? pathID : "NULL") + " accessed from non-main thread for file " + pFileName + " (" + (pOptions ? pOptions : "no options") + ")");
		}

	return FunctionHooks->BaseFileSystemReplacer->Call<FileHandle_t, const char *, const char *, const char *>(FunctionHooks->IBaseFileSystem__Open__index, pFileName, pOptions, pathID);
}
bool
RealNameAttributeText::CommitEditedTextFlavor(BTextView* textView)
{
	const char* text = textView->Text();

	BEntry entry(fModel->EntryRef());
	if (entry.InitCheck() != B_OK)
		return false;

	BDirectory	parent;
	if (entry.GetParent(&parent) != B_OK)
		return false;

	bool removeExisting = false;
	if (parent.Contains(text)) {
		BAlert* alert = new BAlert("",
			B_TRANSLATE("That name is already taken. "
			"Please type another one."),
			B_TRANSLATE("Replace other file"),
			B_TRANSLATE("OK"),
			NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);

		alert->SetShortcut(0, 'r');

		if (alert->Go())
			return false;

		removeExisting = true;
	}

	// TODO:
	// use model-flavor specific virtuals for all of these special
	// renamings
	status_t result;
	if (fModel->IsVolume()) {
		BVolume volume(fModel->NodeRef()->device);
		result = volume.InitCheck();
		if (result == B_OK) {
			RenameVolumeUndo undo(volume, text);

			result = volume.SetName(text);
			if (result != B_OK)
				undo.Remove();
		}
	} else {
		if (fModel->IsQuery()) {
			BModelWriteOpener opener(fModel);
			ASSERT(fModel->Node());
			MoreOptionsStruct::SetQueryTemporary(fModel->Node(), false);
		}

		RenameUndo undo(entry, text);

		result = entry.Rename(text, removeExisting);
		if (result != B_OK)
			undo.Remove();
	}

	return result == B_OK;
}
Exemple #4
0
void PsiCapsRegistry::saveData(const QByteArray &data)
{
	QFile file(ApplicationInfo::homeDir(ApplicationInfo::CacheLocation) + "/caps.xml");
	IODeviceOpener opener(&file, QIODevice::WriteOnly);
	if (!opener.isOpen()) {
		qWarning("Caps: Unable to open IO device");
		return;
	}
	file.write(data);
}
Exemple #5
0
QByteArray PsiCapsRegistry::loadData()
{
	QFile file(ApplicationInfo::homeDir(ApplicationInfo::CacheLocation) + "/caps.xml");
	IODeviceOpener opener(&file, QIODevice::ReadOnly);
	if (!opener.isOpen()) {
		qWarning("CapsRegistry: Cannot open input device");
		return QByteArray();
	}
	return file.readAll();
}
Exemple #6
0
BTextWidget*
BPose::AddWidget(BPoseView* poseView, BColumn* column)
{
	BModelOpener opener(fModel);
	if (fModel->InitCheck() != B_OK)
		return NULL;

	BTextWidget* widget = new BTextWidget(fModel, column, poseView);
	fWidgetList.AddItem(widget);
	return widget;
}
Exemple #7
0
ssize_t 
Model::WriteAttr(const char *attr, type_code type, off_t offset,
	const void *buffer, size_t length)
{
	BModelWriteOpener opener(this);
	if (!fNode) 
		return 0;

	ssize_t result = fNode->WriteAttr(attr, type, offset, buffer, length);
	return result;
}
Exemple #8
0
CURLcode terrama2::core::CurlPtr::getDownloadFiles(std::string url,
                                                   size_t(*write_response)(void *ptr, size_t size, size_t nmemb, void *data),
                                                   std::string filePath)
{
  terrama2::core::FilePtr opener(filePath.c_str(), "wb");
  curl_easy_setopt(curl_, CURLOPT_URL, url.c_str());
  curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, write_response);
  curl_easy_setopt(curl_, CURLOPT_WRITEDATA, opener.file());

  return curl_easy_perform(curl_);
}
Exemple #9
0
void
NodePreloader::MessageReceived(BMessage* message)
{
	// respond to node monitor notifications

	node_ref itemNode;
	switch (message->what) {
		case B_NODE_MONITOR:
		{
			switch (message->FindInt32("opcode")) {
				case B_ENTRY_REMOVED:
				{
					AutoLock<Benaphore> locker(fLock);
					message->FindInt32("device", &itemNode.device);
					message->FindInt64("node", &itemNode.node);
					Model* model = FindModel(itemNode);
					if (model == NULL)
						break;

					//PRINT(("preloader removing file %s\n", model->Name()));
					IconCache::sIconCache->Removing(model);
					fModelList.RemoveItem(model);
					break;
				}

				case B_ATTR_CHANGED:
				case B_STAT_CHANGED:
				{
					AutoLock<Benaphore> locker(fLock);
					message->FindInt32("device", &itemNode.device);
					message->FindInt64("node", &itemNode.node);

					const char* attrName;
					message->FindString("attr", &attrName);
					Model* model = FindModel(itemNode);
					if (model == NULL)
						break;

					BModelOpener opener(model);
					IconCache::sIconCache->IconChanged(model->ResolveIfLink());
					//PRINT(("preloader updating file %s\n", model->Name()));
					break;
				}
			}
			break;
		}

		default:
			_inherited::MessageReceived(message);
			break;
	}
}
Exemple #10
0
ssize_t 
Model::WriteAttrKillForegin(const char *attr, const char *foreignAttr,
	type_code type, off_t offset, const void *buffer, size_t length)
{
	BModelWriteOpener opener(this);
	if (!fNode) 
		return 0;
	
	ssize_t result = fNode->WriteAttr(attr, type, offset, buffer, length);
	if (result == (ssize_t)length)
		// nuke attribute in opposite endianness
		fNode->RemoveAttr(foreignAttr);
	return result;
}
Exemple #11
0
bool
Model::Mimeset(bool force)
{
	BString oldType = MimeType();
	BPath path;
	GetPath(&path);

	update_mime_info(path.Path(), 0, 1, force ? 2 : 0);
	ModelNodeLazyOpener opener(this);
	opener.OpenNode();
	AttrChanged(NULL);

	return !oldType.ICompare(MimeType());
}
void 
BQueryContainerWindow::SetUpDefaultState()
{
	BNode defaultingNode;

	WindowStateNodeOpener opener(this, true);
		// this is our destination node, whatever it is for this window
	if (!opener.StreamNode())
		return;

	BString defaultStatePath(kQueryTemplates);
	BString sanitizedType(PoseView()->SearchForType());

	defaultStatePath += '/';
	int32 length = sanitizedType.Length();
	char *buf = sanitizedType.LockBuffer(length);
	for (int32 index = length - 1; index >= 0; index--)
		if (buf[index] == '/')
			buf[index] = '_';
	sanitizedType.UnlockBuffer(length);

	defaultStatePath += sanitizedType;

	PRINT(("looking for default query state at %s\n", defaultStatePath.String()));

	if (!DefaultStateSourceNode(defaultStatePath.String(), &defaultingNode, false)) {
		TRACE();
		return;
	}

	// copy over the attributes

	// set up a filter of the attributes we want copied
	const char *allowAttrs[] = {
		kAttrWindowFrame,
		kAttrViewState,
		kAttrViewStateForeign,
		kAttrColumns,
		kAttrColumnsForeign,
		0
	};

	// do it
	AttributeStreamMemoryNode memoryNode;
	NamesToAcceptAttrFilter filter(allowAttrs);
	AttributeStreamFileNode fileNode(&defaultingNode);
	*opener.StreamNode() << memoryNode << filter << fileNode;
}
void LLLandmarksPanelObserver::changed(U32 mask)
{
	mLP->updateShowFolderState();

	LLPlacesInventoryPanel* library = mLP->getLibraryInventoryPanel();
	if (!mIsLibraryLandmarksOpen && library)
	{
		// Search for "Landmarks" folder in the Library and open it once on start up. See EXT-4827.
		const LLUUID &landmarks_cat = gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_LANDMARK, false);
		if (landmarks_cat.notNull())
		{
			LLOpenFolderByID opener(landmarks_cat);
			library->getRootFolder()->applyFunctorRecursively(opener);
			mIsLibraryLandmarksOpen = opener.isFolderOpen();
		}
	}
}
Exemple #14
0
void 
Model::GetPreferredAppForBrokenSymLink(BString &result)
{
	if (!IsSymLink() || LinkTo()) {
		result = "";
		return;
	}

	BModelOpener opener(this);
	BNodeInfo info(fNode);		
	status_t error = info.GetPreferredApp(result.LockBuffer(B_MIME_TYPE_LENGTH));
	result.UnlockBuffer();

	if (error != B_OK)
		// Tracker will have to do
		result = kTrackerSignature;
}
void
VersionAttributeText::ReadValue(BString *result)
{
	fValueDirty = false;

	BModelOpener opener(fModel);
	BFile *file = dynamic_cast<BFile *>(fModel->Node());
	if (file) {
		BAppFileInfo info(file);
		version_info version;
		if (info.InitCheck() == B_OK
			&& info.GetVersionInfo(&version,
				fAppVersion ? B_APP_VERSION_KIND : B_SYSTEM_VERSION_KIND) == B_OK) {
			*result = version.short_info;
			return;
		}
	}
	*result = "-";
}
void CheckMatchingPairs::check_matched_pairs(ustring & text)
// Checks on matched pairs. Output any problems found.
{
  for (unsigned int i = 0; i < text.length(); i++) {
    // Get the unicode character;
    gunichar unichar;
    unichar = g_utf8_get_char(text.substr(i, 1).c_str());
    // If we found a mirror character, investigate further.
    gunichar mirror;
    if (g_unichar_get_mirror_char(unichar, &mirror)) {
      // Do we ignore this one?
      if (ignores.find(unichar) != ignores.end())
        continue;
      // See whether this one opens or closes a pair.
      if (gopeners.find(unichar) != gopeners.end()) {
        // It opens: Add data.
        MatchingPairOpener opener(text.substr(i, 1), unichar, book, chapter, verse, get_context(text, i));
        openers.push_back(opener);
        continue;
      } else {
        // It closes: check for previously seen opener.
        bool give_message = false;
        if (openers.empty()) {
          give_message = true;
        }
        if (!give_message) {
          if (openers[openers.size() - 1].unichar == mirror) {
            // Remove last one.
            openers.pop_back();
          } else {
            // Flag message.
            give_message = true;
          }
        }
        if (give_message) {
          // Give message;
          message(book, chapter, verse, _("Pair not opened: ") + get_context(text, i));
        }
      }
    }
  }
}
Exemple #17
0
bool 
Model::Mimeset(bool force)
{
	BString oldType = MimeType();
	ModelNodeLazyOpener opener(this);
	BPath path;
	GetPath(&path);
	if (force) {
		if (opener.OpenNode(true) != B_OK)
			return false;

		Node()->RemoveAttr(kAttrMIMEType);
		update_mime_info(path.Path(), 0, 1, 1);
	} else
		update_mime_info(path.Path(), 0, 1, 0);

	AttrChanged(0);

	return !oldType.ICompare(MimeType());
}
Exemple #18
0
void 
Model::ResetIconFrom()
{
	BModelOpener opener(this);

	if (InitCheck() != B_OK)
		return;

	// mirror the logic from FinishSettingUpType
	if ((fBaseType == kDirectoryNode || fBaseType == kVolumeNode)
		&& !CheckNodeIconHintPrivate(fNode, dynamic_cast<TTracker *>(be_app) == NULL)) {
		if (WellKnowEntryList::Match(NodeRef()) > (directory_which)-1) {
			fIconFrom = kTrackerSupplied;
			return;
		} else if (dynamic_cast<BDirectory *>(fNode)->IsRootDirectory()) {
			fIconFrom = kVolume;
			return;
		}
	}
	fIconFrom = kUnknownSource;
}
Exemple #19
0
static void do_test(int (*opener)(int)) {
  pid_t child;
  int fd;
  int status;
  int pipe_fds[2];
  struct iovec iov[2];

  test_assert(0 == pipe(pipe_fds));

  child = fork();
  if (!child) {
    char ch;
    test_assert(1 == read(pipe_fds[0], &ch, 1));
    test_assert(COOKIE == cookie1);
    test_assert(COOKIE == cookie2);
    test_assert(COOKIE == cookie3);
    exit(77);
  }

  fd = opener(child);
  test_assert(fd >= 0);
  test_assert(sizeof(COOKIE) ==
              pwrite(fd, &COOKIE, sizeof(COOKIE), (off_t)&cookie1));

  iov[0].iov_base = (char*)&COOKIE;
  iov[0].iov_len = 2;
  iov[1].iov_base = (char*)&COOKIE + 2;
  iov[1].iov_len = 2;
  test_assert(sizeof(COOKIE) == pwritev(fd, iov, 2, (off_t)&cookie2));

  lseek(fd, (off_t)&cookie3, SEEK_SET);
  test_assert(sizeof(COOKIE) == write(fd, &COOKIE, sizeof(COOKIE)));

  test_assert(1 == write(pipe_fds[1], "x", 1));
  test_assert(child == waitpid(child, &status, 0));
  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);
}
Exemple #20
0
int main(int argc, char* argv[])
{
	int i = 1;
	int file = 0;
	if(argc == 1)
	{
		std_input();
	}
	else
	{
		while(argc > i) 
		{
			if(argc >= 3)
			{
				if((divider(argc, argv[i])) < 0)
				{
					return -1;
				}
			}
			if ((argv[i])[0] == 45 && strlen(argv[i]) == 1)  // Checking if the argument is a "-"
			{
				std_input();
			}
			else
			{
				if ((file = opener(argv[i])) >= 0)
				{
					read_and_output(file);
				}
			}
			i = i + 1;
		}
	}
	
	return 0;
}
Exemple #21
0
ModelMenuItem * 
BSlowContextMenu::NewModelItem(Model *model, const BMessage *invokeMessage,
	const BMessenger &target, bool suppressFolderHierarchy,
	BContainerWindow *parentWindow, const BObjectList<BString> *typeslist,
	TrackingHookData *hook)
{
	if (model->InitCheck() != B_OK)
		return NULL;

	entry_ref ref;
	bool container = false;
	if (model->IsSymLink()) {
	
		Model *newResolvedModel = NULL;
		Model *result = model->LinkTo();

		if (!result) {
			newResolvedModel = new Model(model->EntryRef(), true, true);

			if (newResolvedModel->InitCheck() != B_OK) {
				// broken link, still can show though, bail
				delete newResolvedModel;
				newResolvedModel = NULL;
			}
			
			result = newResolvedModel;
		}

		if (result) {
			BModelOpener opener(result);
				// open the model, if it ain't open already
					
			PoseInfo poseInfo;
			ssize_t size = -1;
			
			if (result->Node()) 
				size = result->Node()->ReadAttr(kAttrPoseInfo, B_RAW_TYPE, 0,
					&poseInfo, sizeof(poseInfo));
	
			result->CloseNode();

			ref = *result->EntryRef();
			container = result->IsContainer();
		}
		model->SetLinkTo(result);
	} else {
		ref = *model->EntryRef();
		container = model->IsContainer();
	}

	BMessage *message = new BMessage(*invokeMessage);
	message->AddRef("refs", model->EntryRef());

	// Truncate the name if necessary
	BString truncatedString(model->Name());
	be_plain_font->TruncateString(&truncatedString, B_TRUNCATE_END,
		BNavMenu::GetMaxMenuWidth());

	ModelMenuItem *item = NULL;
	if (!container || suppressFolderHierarchy) {
		item = new ModelMenuItem(model, truncatedString.String(), message);
		if (invokeMessage->what != B_REFS_RECEIVED)
			item->SetEnabled(false);
	} else {
		BNavMenu *menu = new BNavMenu(truncatedString.String(),
			invokeMessage->what, target, parentWindow, typeslist);
		
		menu->SetNavDir(&ref);
		if (hook)
			menu->InitTrackingHook(hook->fTrackingHook, &(hook->fTarget),
				hook->fDragMessage);

		item = new ModelMenuItem(model, menu);
		item->SetMessage(message);
	}

	return item;
}
void LLInventoryPanel::openDefaultFolderForType(LLAssetType::EType type)
{
	LLUUID category_id = mInventory->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(type));
	LLOpenFolderByID opener(category_id);
	mFolderRoot.get()->applyFunctorRecursively(opener);
}
void
GenericAttributeText::ReadValue(BString* outString)
{
	BModelOpener opener(const_cast<Model*>(fModel));

	ssize_t length = 0;
	fFullValueText = "-";
	fValue.int64t = 0;
	fValueIsDefined = false;
	fValueDirty = false;

	if (!fModel->Node())
		return;

	switch (fColumn->AttrType()) {
		case B_STRING_TYPE:
		{
			char buffer[kGenericReadBufferSize];
			length = fModel->Node()->ReadAttr(fColumn->AttrName(),
				fColumn->AttrType(), 0, buffer, kGenericReadBufferSize - 1);

			if (length > 0) {
				buffer[length] = '\0';
				// make sure the buffer is null-terminated even if we
				// didn't read the whole attribute in or it wasn't to
				// begin with

				*outString = buffer;
				fValueIsDefined = true;
			}
			break;
		}

		case B_SSIZE_T_TYPE:
		case B_TIME_TYPE:
		case B_OFF_T_TYPE:
		case B_FLOAT_TYPE:
		case B_BOOL_TYPE:
		case B_CHAR_TYPE:
		case B_INT8_TYPE:
		case B_INT16_TYPE:
		case B_INT32_TYPE:
		case B_INT64_TYPE:
		case B_UINT8_TYPE:
		case B_UINT16_TYPE:
		case B_UINT32_TYPE:
		case B_UINT64_TYPE:
		case B_DOUBLE_TYPE:
		{
			// read in the numerical bit representation and attach it
			// with a type, depending on the bytes that could be read
			attr_info info;
			GenericValueStruct tmp;
			if (fModel->Node()->GetAttrInfo(fColumn->AttrName(), &info)
					== B_OK) {
				if (info.size && info.size <= (off_t)sizeof(int64)) {
					length = fModel->Node()->ReadAttr(fColumn->AttrName(),
						fColumn->AttrType(), 0, &tmp, (size_t)info.size);
				}

				// We used tmp as a block of memory, now set the
				// correct fValue:

				if (length == info.size) {
					if (fColumn->AttrType() == B_FLOAT_TYPE
						|| fColumn->AttrType() == B_DOUBLE_TYPE) {
						// filter out special float/double types
						switch (info.size) {
							case sizeof(float):
								fValueIsDefined = true;
								fValue.floatt = tmp.floatt;
								break;

							case sizeof(double):
								fValueIsDefined = true;
								fValue.doublet = tmp.doublet;
								break;

							default:
								TRESPASS();
								break;
						}
					} else {
						// handle the standard data types
						switch (info.size) {
							case sizeof(char):
								// Takes care of bool too.
								fValueIsDefined = true;
								fValue.int8t = tmp.int8t;
								break;

							case sizeof(int16):
								fValueIsDefined = true;
								fValue.int16t = tmp.int16t;
								break;

							case sizeof(int32):
								// Takes care of time_t too.
								fValueIsDefined = true;
								fValue.int32t = tmp.int32t;
								break;

							case sizeof(int64):
								// Takes care of off_t too.
								fValueIsDefined = true;
								fValue.int64t = tmp.int64t;
								break;

							default:
								TRESPASS();
								break;
						}
					}
				}
			}
			break;
		}
	}
}
Exemple #24
0
status_t
Volume::Mount(const char* deviceName, uint32 flags)
{
	// flags |= B_MOUNT_READ_ONLY;
		// we only support read-only for now
	
	if ((flags & B_MOUNT_READ_ONLY) != 0) {
		TRACE("Volume::Mount(): Read only\n");
	} else {
		TRACE("Volume::Mount(): Read write\n");
	}

	DeviceOpener opener(deviceName, (flags & B_MOUNT_READ_ONLY) != 0
		? O_RDONLY : O_RDWR);
	fDevice = opener.Device();
	if (fDevice < B_OK) {
		FATAL("Volume::Mount(): couldn't open device\n");
		return fDevice;
	}

	if (opener.IsReadOnly())
		fFlags |= VOLUME_READ_ONLY;

	TRACE("features %lx, incompatible features %lx, read-only features %lx\n",
		fSuperBlock.CompatibleFeatures(), fSuperBlock.IncompatibleFeatures(),
		fSuperBlock.ReadOnlyFeatures());

	// read the super block
	status_t status = Identify(fDevice, &fSuperBlock);
	if (status != B_OK) {
		FATAL("Volume::Mount(): Identify() failed\n");
		return status;
	}
	
	// check read-only features if mounting read-write
	if (!IsReadOnly() && _UnsupportedReadOnlyFeatures(fSuperBlock) != 0)
		return B_UNSUPPORTED;

	// initialize short hands to the super block (to save byte swapping)
	fBlockShift = fSuperBlock.BlockShift();
	if (fBlockShift < 10 || fBlockShift > 16)
		return B_ERROR;
	fBlockSize = 1UL << fBlockShift;
	fFirstDataBlock = fSuperBlock.FirstDataBlock();

	fFreeBlocks = fSuperBlock.FreeBlocks(Has64bitFeature());
	fFreeInodes = fSuperBlock.FreeInodes();

	off_t numBlocks = fSuperBlock.NumBlocks(Has64bitFeature()) - fFirstDataBlock;
	uint32 blocksPerGroup = fSuperBlock.BlocksPerGroup();
	fNumGroups = numBlocks / blocksPerGroup;
	if (numBlocks % blocksPerGroup != 0)
		fNumGroups++;

	if (Has64bitFeature()) {
		fGroupDescriptorSize = fSuperBlock.GroupDescriptorSize();
		if (fGroupDescriptorSize < sizeof(ext2_block_group))
			return B_ERROR;
	} else
		fGroupDescriptorSize = EXT2_BLOCK_GROUP_NORMAL_SIZE;
	fGroupsPerBlock = fBlockSize / fGroupDescriptorSize;
	fNumInodes = fSuperBlock.NumInodes();

	TRACE("block size %ld, num groups %ld, groups per block %ld, first %lu\n",
		fBlockSize, fNumGroups, fGroupsPerBlock, fFirstDataBlock);
	
	uint32 blockCount = (fNumGroups + fGroupsPerBlock - 1) / fGroupsPerBlock;

	fGroupBlocks = (uint8**)malloc(blockCount * sizeof(uint8*));
	if (fGroupBlocks == NULL)
		return B_NO_MEMORY;

	memset(fGroupBlocks, 0, blockCount * sizeof(uint8*));
	fInodesPerBlock = fBlockSize / InodeSize();

	// check if the device size is large enough to hold the file system
	off_t diskSize;
	status = opener.GetSize(&diskSize);
	if (status != B_OK)
		return status;
	if (diskSize < ((off_t)NumBlocks() << BlockShift()))
		return B_BAD_VALUE;

	fBlockCache = opener.InitCache(NumBlocks(), fBlockSize);
	if (fBlockCache == NULL)
		return B_ERROR;
	
	TRACE("Volume::Mount(): Initialized block cache: %p\n", fBlockCache);

	// initialize journal if mounted read-write
	if (!IsReadOnly() &&
		(fSuperBlock.CompatibleFeatures() & EXT2_FEATURE_HAS_JOURNAL) != 0) {
		// TODO: There should be a mount option to ignore the existent journal
		if (fSuperBlock.JournalInode() != 0) {
			fJournalInode = new(std::nothrow) Inode(this, 
				fSuperBlock.JournalInode());

			if (fJournalInode == NULL)
				return B_NO_MEMORY;

			TRACE("Opening an on disk, inode mapped journal.\n");
			fJournal = new(std::nothrow) InodeJournal(fJournalInode);
		} else {
			// TODO: external journal
			TRACE("Can not open an external journal.\n");
			return B_UNSUPPORTED;
		}
	} else {
		TRACE("Opening a fake journal (NoJournal).\n");
		fJournal = new(std::nothrow) NoJournal(this);
	}

	if (fJournal == NULL) {
		TRACE("No memory to create the journal\n");
		return B_NO_MEMORY;
	}

	TRACE("Volume::Mount(): Checking if journal was initialized\n");
	status = fJournal->InitCheck();
	if (status != B_OK) {
		FATAL("could not initialize journal!\n");
		return status;
	}

	// TODO: Only recover if asked to
	TRACE("Volume::Mount(): Asking journal to recover\n");
	status = fJournal->Recover();
	if (status != B_OK) {
		FATAL("could not recover journal!\n");
		return status;
	}

	TRACE("Volume::Mount(): Restart journal log\n");
	status = fJournal->StartLog();
	if (status != B_OK) {
		FATAL("could not initialize start journal!\n");
		return status;
	}

	if (!IsReadOnly()) {
		// Initialize allocators
		fBlockAllocator = new(std::nothrow) BlockAllocator(this);
		if (fBlockAllocator != NULL) {
			TRACE("Volume::Mount(): Initialize block allocator\n");
			status = fBlockAllocator->Initialize();
		}
		if (fBlockAllocator == NULL || status != B_OK) {
			delete fBlockAllocator;
			fBlockAllocator = NULL;
			FATAL("could not initialize block allocator, going read-only!\n");
			fFlags |= VOLUME_READ_ONLY;
			fJournal->Uninit();
			delete fJournal;
			delete fJournalInode;
			fJournalInode = NULL;
			fJournal = new(std::nothrow) NoJournal(this);
		}
	}

	// ready
	status = get_vnode(fFSVolume, EXT2_ROOT_NODE, (void**)&fRootNode);
	if (status != B_OK) {
		FATAL("could not create root node: get_vnode() failed!\n");
		return status;
	}

	// all went fine
	opener.Keep();

	if (!fSuperBlock.name[0]) {
		// generate a more or less descriptive volume name
		off_t divisor = 1ULL << 40;
		char unit = 'T';
		if (diskSize < divisor) {
			divisor = 1UL << 30;
			unit = 'G';
			if (diskSize < divisor) {
				divisor = 1UL << 20;
				unit = 'M';
			}
		}

		double size = double((10 * diskSize + divisor - 1) / divisor);
			// %g in the kernel does not support precision...

		snprintf(fName, sizeof(fName), "%g %cB Ext2 Volume",
			size / 10, unit);
	}

	return B_OK;
}
Exemple #25
0
status_t
Volume::Mount(const char* deviceName, uint32 flags)
{
	flags |= B_MOUNT_READ_ONLY;
		// we only support read-only for now
	
	if ((flags & B_MOUNT_READ_ONLY) != 0) {
		TRACE("Volume::Mount(): Read only\n");
	} else {
		TRACE("Volume::Mount(): Read write\n");
	}

	DeviceOpener opener(deviceName, (flags & B_MOUNT_READ_ONLY) != 0
		? O_RDONLY : O_RDWR);
	fDevice = opener.Device();
	if (fDevice < B_OK) {
		ERROR("Volume::Mount(): couldn't open device\n");
		return fDevice;
	}

	if (opener.IsReadOnly())
		fFlags |= VOLUME_READ_ONLY;

	// read the superblock
	status_t status = Identify(fDevice, &fSuperBlock);
	if (status != B_OK) {
		ERROR("Volume::Mount(): Identify() failed\n");
		return status;
	}
	
	fBlockSize = 1 << fSuperBlock.BlockShift();
	TRACE("block size %" B_PRIu32 "\n", fBlockSize);
	fEntriesPerBlock = (fBlockSize / sizeof(struct exfat_entry));
		
	// check if the device size is large enough to hold the file system
	off_t diskSize;
	status = opener.GetSize(&diskSize);
	if (status != B_OK)
		return status;
	if (diskSize < (off_t)fSuperBlock.NumBlocks() << fSuperBlock.BlockShift())
		return B_BAD_VALUE;

	fBlockCache = opener.InitCache(fSuperBlock.NumBlocks(), fBlockSize);
	if (fBlockCache == NULL)
		return B_ERROR;
	
	TRACE("Volume::Mount(): Initialized block cache: %p\n", fBlockCache);

	ino_t rootIno;
	// ready
	{
		Inode rootNode(this, fSuperBlock.RootDirCluster(), 0);
		rootIno = rootNode.ID();
	}

	status = get_vnode(fFSVolume, rootIno, (void**)&fRootNode);
	if (status != B_OK) {
		ERROR("could not create root node: get_vnode() failed!\n");
		return status;
	}

	TRACE("Volume::Mount(): Found root node: %" B_PRIdINO " (%s)\n", fRootNode->ID(),
		strerror(fRootNode->InitCheck()));

	// all went fine
	opener.Keep();

	DirectoryIterator iterator(fRootNode);
	LabelVisitor visitor(this);
	iterator.Iterate(visitor);

	if (fName[0] == '\0') {
		// generate a more or less descriptive volume name
		off_t divisor = 1ULL << 40;
		char unit = 'T';
		if (diskSize < divisor) {
			divisor = 1UL << 30;
			unit = 'G';
			if (diskSize < divisor) {
				divisor = 1UL << 20;
				unit = 'M';
			}
		}

		double size = double((10 * diskSize + divisor - 1) / divisor);
			// %g in the kernel does not support precision...

		snprintf(fName, sizeof(fName), "%g %cB ExFAT Volume",
			size / 10, unit);
	}

	return B_OK;
}
Exemple #26
0
status_t
Partition::Scan(bool mountFileSystems, bool isBootDevice)
{
	// scan for partitions first (recursively all eventual children as well)

	TRACE(("%p Partition::Scan()\n", this));

	// if we were not booted from the real boot device, we won't scan
	// the device we were booted from (which is likely to be a slow
	// floppy or CD)
	if (isBootDevice && gKernelArgs.boot_volume.GetBool(
			BOOT_VOLUME_BOOTED_FROM_IMAGE, false)) {
		return B_ENTRY_NOT_FOUND;
	}

	const partition_module_info *bestModule = NULL;
	void *bestCookie = NULL;
	float bestPriority = -1;

	for (int32 i = 0; i < sNumPartitionModules; i++) {
		const partition_module_info *module = sPartitionModules[i];
		void *cookie = NULL;
		NodeOpener opener(this, O_RDONLY);

		TRACE(("check for partitioning_system: %s\n", module->pretty_name));

		float priority
			= module->identify_partition(opener.Descriptor(), this, &cookie);
		if (priority < 0.0)
			continue;

		TRACE(("  priority: %ld\n", (int32)(priority * 1000)));
		if (priority <= bestPriority) {
			// the disk system recognized the partition worse than the currently
			// best one
			module->free_identify_partition_cookie(this, cookie);
			continue;
		}

		// a new winner, replace the previous one
		if (bestModule)
			bestModule->free_identify_partition_cookie(this, bestCookie);
		bestModule = module;
		bestCookie = cookie;
		bestPriority = priority;
	}

	// find the best FS module
	const file_system_module_info *bestFSModule = NULL;
	float bestFSPriority = -1;
	for (int32 i = 0; i < sNumFileSystemModules; i++) {
		if (sFileSystemModules[i]->identify_file_system == NULL)
			continue;

		float priority = sFileSystemModules[i]->identify_file_system(this);
		if (priority <= 0)
			continue;

		if (priority > bestFSPriority) {
			bestFSModule = sFileSystemModules[i];
			bestFSPriority = priority;
		}
	}

	// now let the best matching disk system scan the partition
	if (bestModule && bestPriority >= bestFSPriority) {
		NodeOpener opener(this, O_RDONLY);
		status_t status = bestModule->scan_partition(opener.Descriptor(), this,
			bestCookie);
		bestModule->free_identify_partition_cookie(this, bestCookie);

		if (status != B_OK) {
			dprintf("Partitioning module `%s' recognized the partition, but "
				"failed to scan it\n", bestModule->pretty_name);
			return status;
		}

		fIsPartitioningSystem = true;

		content_type = bestModule->pretty_name;
		flags |= B_PARTITION_PARTITIONING_SYSTEM;

		// now that we've found something, check our children
		// out as well!

		NodeIterator iterator = fChildren.GetIterator();
		Partition *child = NULL;

		while ((child = (Partition *)iterator.Next()) != NULL) {
			TRACE(("%p Partition::Scan(): scan child %p (start = %Ld, size "
				"= %Ld, parent = %p)!\n", this, child, child->offset,
				child->size, child->Parent()));

			child->Scan(mountFileSystems);

			if (!mountFileSystems || child->IsFileSystem()) {
				// move the partitions containing file systems to the partition
				// list
				fChildren.Remove(child);
				gPartitions.Add(child);
			}
		}

		// remove all unused children (we keep only file systems)

		while ((child = (Partition *)fChildren.Head()) != NULL) {
			fChildren.Remove(child);
			delete child;
		}

		// remember the name of the module that identified us
		fModuleName = bestModule->module.name;

		return B_OK;
	}

	// scan for file systems

	if (mountFileSystems) {
		// TODO: Use the FS module we've got, if any. Requires to implement the
		// identify_file_system() hook in every FS.
		return Mount();
	}

	return B_ENTRY_NOT_FOUND;
}
Exemple #27
0
void
Model::TrackIconSource(icon_size size)
{
	PRINT(("tracking %s icon\n", size == B_LARGE_ICON ? "large" : "small"));
	BRect rect;
	if (size == B_MINI_ICON)
		rect.Set(0, 0, B_MINI_ICON - 1, B_MINI_ICON - 1);
	else
		rect.Set(0, 0, B_LARGE_ICON - 1, B_LARGE_ICON - 1);

	BBitmap bitmap(rect, B_CMAP8);

	BModelOpener opener(this);

	if (Node() == NULL) {
		PRINT(("track icon error - no node\n"));
		return;
	}

	if (IsSymLink()) {
		PRINT(("tracking symlink icon\n"));
		if (fLinkTo) {
			fLinkTo->TrackIconSource(size);
			return;
		}
	}

	if (fBaseType == kVolumeNode) {
		BVolume volume(NodeRef()->device);
		status_t result = volume.GetIcon(&bitmap, size);
		PRINT(("getting icon from volume %s\n", strerror(result)));
	} else {
		BNodeInfo nodeInfo(Node());

		status_t err = nodeInfo.GetIcon(&bitmap, size);
		if (err == B_OK) {
			// file knew which icon to use, we are done
			PRINT(("track icon - got icon from file\n"));
			return;
		}

		char preferredApp[B_MIME_TYPE_LENGTH];
		err = nodeInfo.GetPreferredApp(preferredApp);
		if (err == B_OK && preferredApp[0]) {
			BMimeType preferredAppType(preferredApp);
			err = preferredAppType.GetIconForType(MimeType(), &bitmap, size);
			if (err == B_OK) {
				PRINT(("track icon - got icon for type %s from preferred app %s for file\n",
					MimeType(), preferredApp));
				return;
			}
		}

		BMimeType mimeType(MimeType());
		err = mimeType.GetIcon(&bitmap, size);
		if (err == B_OK) {
			// the system knew what icon to use for the type, we are done
			PRINT(("track icon - signature %s, got icon from system\n",
				MimeType()));
			return;
		}

		err = mimeType.GetPreferredApp(preferredApp);
		if (err != B_OK) {
			// no preferred App for document, give up
			PRINT(("track icon - signature %s, no prefered app, error %s\n",
				MimeType(), strerror(err)));
			return;
		}

		BMimeType preferredAppType(preferredApp);
		err = preferredAppType.GetIconForType(MimeType(), &bitmap, size);
		if (err == B_OK) {
			// the preferred app knew icon to use for the type, we are done
			PRINT(("track icon - signature %s, got icon from preferred app %s\n",
				MimeType(), preferredApp));
			return;
		}
		PRINT(("track icon - signature %s, preferred app %s, no icon, error %s\n",
			MimeType(), preferredApp, strerror(err)));
	}
}
Exemple #28
0
status_t
Volume::Mount(const char* deviceName, uint32 flags)
{
	// TODO: validate the FS in write mode as well!
#if (B_HOST_IS_LENDIAN && defined(BFS_BIG_ENDIAN_ONLY)) \
	|| (B_HOST_IS_BENDIAN && defined(BFS_LITTLE_ENDIAN_ONLY))
	// in big endian mode, we only mount read-only for now
	flags |= B_MOUNT_READ_ONLY;
#endif

	DeviceOpener opener(deviceName, (flags & B_MOUNT_READ_ONLY) != 0
		? O_RDONLY : O_RDWR);
	fDevice = opener.Device();
	if (fDevice < B_OK)
		RETURN_ERROR(fDevice);

	if (opener.IsReadOnly())
		fFlags |= VOLUME_READ_ONLY;

	// read the superblock
	if (Identify(fDevice, &fSuperBlock) != B_OK) {
		FATAL(("invalid superblock!\n"));
		return B_BAD_VALUE;
	}

	// initialize short hands to the superblock (to save byte swapping)
	fBlockSize = fSuperBlock.BlockSize();
	fBlockShift = fSuperBlock.BlockShift();
	fAllocationGroupShift = fSuperBlock.AllocationGroupShift();

	// check if the device size is large enough to hold the file system
	off_t diskSize;
	if (opener.GetSize(&diskSize, &fDeviceBlockSize) != B_OK)
		RETURN_ERROR(B_ERROR);
	if (diskSize < (NumBlocks() << BlockShift()))
		RETURN_ERROR(B_BAD_VALUE);

	// set the current log pointers, so that journaling will work correctly
	fLogStart = fSuperBlock.LogStart();
	fLogEnd = fSuperBlock.LogEnd();

	if ((fBlockCache = opener.InitCache(NumBlocks(), fBlockSize)) == NULL)
		return B_ERROR;

	fJournal = new(std::nothrow) Journal(this);
	if (fJournal == NULL)
		return B_NO_MEMORY;

	status_t status = fJournal->InitCheck();
	if (status < B_OK) {
		FATAL(("could not initialize journal: %s!\n", strerror(status)));
		return status;
	}

	// replaying the log is the first thing we will do on this disk
	status = fJournal->ReplayLog();
	if (status != B_OK) {
		FATAL(("Replaying log failed, data may be corrupted, volume "
			"read-only.\n"));
		fFlags |= VOLUME_READ_ONLY;
			// TODO: if this is the boot volume, Bootscript will assume this
			// is a CD...
			// TODO: it would be nice to have a user visible alert instead
			// of letting him just find this in the syslog.
	}

	status = fBlockAllocator.Initialize();
	if (status != B_OK) {
		FATAL(("could not initialize block bitmap allocator!\n"));
		return status;
	}

	fRootNode = new(std::nothrow) Inode(this, ToVnode(Root()));
	if (fRootNode != NULL && fRootNode->InitCheck() == B_OK) {
		status = publish_vnode(fVolume, ToVnode(Root()), (void*)fRootNode,
			&gBFSVnodeOps, fRootNode->Mode(), 0);
		if (status == B_OK) {
			// try to get indices root dir

			if (!Indices().IsZero()) {
				fIndicesNode = new(std::nothrow) Inode(this,
					ToVnode(Indices()));
			}

			if (fIndicesNode == NULL
				|| fIndicesNode->InitCheck() < B_OK
				|| !fIndicesNode->IsContainer()) {
				INFORM(("bfs: volume doesn't have indices!\n"));

				if (fIndicesNode) {
					// if this is the case, the index root node is gone bad,
					// and BFS switch to read-only mode
					fFlags |= VOLUME_READ_ONLY;
					delete fIndicesNode;
					fIndicesNode = NULL;
				}
			} else {
				// we don't use the vnode layer to access the indices node
			}
		} else {
			FATAL(("could not create root node: publish_vnode() failed!\n"));
			delete fRootNode;
			return status;
		}
	} else {
		status = B_BAD_VALUE;
		FATAL(("could not create root node!\n"));
		return status;
	}

	// all went fine
	opener.Keep();
	return B_OK;
}
Exemple #29
0
status_t
Volume::Initialize(int fd, const char* name, uint32 blockSize,
	uint32 flags)
{
	// although there is no really good reason for it, we won't
	// accept '/' in disk names (mkbfs does this, too - and since
	// Tracker names mounted volumes like their name)
	if (strchr(name, '/') != NULL)
		return B_BAD_VALUE;

	if (blockSize != 1024 && blockSize != 2048 && blockSize != 4096
		&& blockSize != 8192)
		return B_BAD_VALUE;

	DeviceOpener opener(fd, O_RDWR);
	if (opener.Device() < B_OK)
		return B_BAD_VALUE;

	if (opener.IsReadOnly())
		return B_READ_ONLY_DEVICE;

	fDevice = opener.Device();

	uint32 deviceBlockSize;
	off_t deviceSize;
	if (opener.GetSize(&deviceSize, &deviceBlockSize) < B_OK)
		return B_ERROR;

	off_t numBlocks = deviceSize / blockSize;

	// create valid superblock

	fSuperBlock.Initialize(name, numBlocks, blockSize);

	// initialize short hands to the superblock (to save byte swapping)
	fBlockSize = fSuperBlock.BlockSize();
	fBlockShift = fSuperBlock.BlockShift();
	fAllocationGroupShift = fSuperBlock.AllocationGroupShift();

	// determine log size depending on the size of the volume
	off_t logSize = 2048;
	if (numBlocks <= 20480)
		logSize = 512;
	if (deviceSize > 1LL * 1024 * 1024 * 1024)
		logSize = 4096;

	// since the allocator has not been initialized yet, we
	// cannot use BlockAllocator::BitmapSize() here
	off_t bitmapBlocks = (numBlocks + blockSize * 8 - 1) / (blockSize * 8);

	fSuperBlock.log_blocks = ToBlockRun(bitmapBlocks + 1);
	fSuperBlock.log_blocks.length = HOST_ENDIAN_TO_BFS_INT16(logSize);
	fSuperBlock.log_start = fSuperBlock.log_end = HOST_ENDIAN_TO_BFS_INT64(
		ToBlock(Log()));

	// set the current log pointers, so that journaling will work correctly
	fLogStart = fSuperBlock.LogStart();
	fLogEnd = fSuperBlock.LogEnd();

	if (!IsValidSuperBlock())
		RETURN_ERROR(B_ERROR);

	if ((fBlockCache = opener.InitCache(NumBlocks(), fBlockSize)) == NULL)
		return B_ERROR;

	fJournal = new(std::nothrow) Journal(this);
	if (fJournal == NULL || fJournal->InitCheck() < B_OK)
		RETURN_ERROR(B_ERROR);

	// ready to write data to disk

	Transaction transaction(this, 0);

	if (fBlockAllocator.InitializeAndClearBitmap(transaction) < B_OK)
		RETURN_ERROR(B_ERROR);

	off_t id;
	status_t status = Inode::Create(transaction, NULL, NULL,
		S_DIRECTORY | 0755, 0, 0, NULL, &id, &fRootNode);
	if (status < B_OK)
		RETURN_ERROR(status);

	fSuperBlock.root_dir = ToBlockRun(id);

	if ((flags & VOLUME_NO_INDICES) == 0) {
		// The indices root directory will be created automatically
		// when the standard indices are created (or any other).
		Index index(this);
		status = index.Create(transaction, "name", B_STRING_TYPE);
		if (status < B_OK)
			return status;

		status = index.Create(transaction, "BEOS:APP_SIG", B_STRING_TYPE);
		if (status < B_OK)
			return status;

		status = index.Create(transaction, "last_modified", B_INT64_TYPE);
		if (status < B_OK)
			return status;

		status = index.Create(transaction, "size", B_INT64_TYPE);
		if (status < B_OK)
			return status;
	}

	status = CreateVolumeID(transaction);
	if (status < B_OK)
		return status;

	status = _EraseUnusedBootBlock();
	if (status < B_OK)
		return status;

	status = WriteSuperBlock();
	if (status < B_OK)
		return status;

	status = transaction.Done();
	if (status < B_OK)
		return status;

	Sync();
	opener.RemoveCache(true);
	return B_OK;
}
Exemple #30
0
	// process a line of the sass text
	string process (string& sass, converter& converter)
	{

		// resulting string
		string scss = "";

		// strip multi line comments
		if (STRIP_COMMENT(converter))
		{
			sass = removeMultilineComment(sass);
		}

		// right trim input
		sass = rtrim(sass);

		// get postion of first meaningfull character in string
		size_t pos_left = sass.find_first_not_of(SASS2SCSS_FIND_WHITESPACE);

		// special case for final run
		if (converter.end_of_file) pos_left = 0;

		// maybe has only whitespace
		if (pos_left == string::npos)
		{
			// just add complete whitespace
			converter.whitespace += sass + "\n";
		}
		// have meaningfull first char
		else
		{

			// extract and store indentation string
			string indent = sass.substr(0, pos_left);

			// check if current line starts a comment
			string open = sass.substr(pos_left, 2);

			// line has less or same indentation
			// finalize previous open parser context
			if (indent.length() <= INDENT(converter).length())
			{

				// close multilinie comment
				if (IS_CSS_COMMENT(converter))
				{
					// check if comments will be stripped anyway
					if (!STRIP_COMMENT(converter)) scss += " */";
				}
				// close src comment comment
				else if (IS_SRC_COMMENT(converter))
				{
					// add a newline to avoid closer on same line
					// this would put the bracket in the comment node
					// no longer needed since we parse them correctly
					// if (KEEP_COMMENT(converter)) scss += "\n";
				}
				// close css properties
				else if (converter.property)
				{
					// add closer unless in concat mode
					if (!converter.comma)
					{
						// if there was no colon we have a selector
						// looks like there were no inner properties
						if (converter.selector) scss += " {}";
						// add final semicolon
						else if (!converter.semicolon) scss += ";";
					}
				}

				// reset comment state
				converter.comment = "";

			}

			// make sure we close every "higher" block
			while (indent.length() < INDENT(converter).length())
			{
				// pop stacked context
				converter.indents.pop();
				// print close bracket
				if (IS_PARSING(converter))
				{ scss += closer(converter); }
				else { scss += " */"; }
				// reset comment state
				converter.comment = "";
			}

			// reset converter state
			converter.selector = false;

			// check if we have sass property syntax
			if (sass.substr(pos_left, 1) == ":" && sass.substr(pos_left, 2) != "::")
			{

				// default to a selector
				// change back if property found
				converter.selector = true;
				// get postion of first whitespace char
				size_t pos_wspace = sass.find_first_of(SASS2SCSS_FIND_WHITESPACE, pos_left);
				// assertion check for valid result
				if (pos_wspace != string::npos)
				{
					// get the possible pseudo selector
					string pseudo = sass.substr(pos_left, pos_wspace - pos_left);
					// get position of the first real property value char
					// pseudo selectors get this far, but have no actual value
					size_t pos_value =  sass.find_first_not_of(SASS2SCSS_FIND_WHITESPACE, pos_wspace);
					// assertion check for valid result
					if (pos_value != string::npos)
					{
						// only process if not (fallowed by a semicolon or is a pseudo selector)
						if (!(sass.at(pos_value) == ':' || isPseudoSelector(pseudo)))
						{
							// create new string by interchanging the colon sign for property and value
							sass = indent + sass.substr(pos_left + 1, pos_wspace - pos_left - 1) + ":" + sass.substr(pos_wspace);
							// try to find a colon in the current line, but only ...
							size_t pos_colon = sass.find_first_not_of(":", pos_left);
							// assertion for valid result
							if (pos_colon != string::npos)
							{
								// ... after the first word (skip begining colons)
								pos_colon = sass.find_first_of(":", pos_colon);
								// it is a selector if there was no colon found
								converter.selector = pos_colon == string::npos;
							}
						}
					}
				}

			}

			// terminate warn and debug statements immediately
			else if (sass.substr(pos_left, 5) == "@warn" || sass.substr(pos_left, 6) == "@debug")
			{ sass = indent + sass.substr(pos_left); }
			// replace some specific sass shorthand directives (if not fallowed by a white space character)
			else if (sass.substr(pos_left, 1) == "=" && sass.find_first_of(SASS2SCSS_FIND_WHITESPACE, pos_left) != pos_left + 1)
			{ sass = indent + "@mixin " + sass.substr(pos_left + 1); }
			else if (sass.substr(pos_left, 1) == "+" && sass.find_first_of(SASS2SCSS_FIND_WHITESPACE, pos_left) != pos_left + 1)
			{ sass = indent + "@include " + sass.substr(pos_left + 1); }

			// add quotes for import if needed
			else if (sass.substr(pos_left, 7) == "@import")
			{
				// get positions for the actual import url
				size_t pos_import = sass.find_first_of(SASS2SCSS_FIND_WHITESPACE, pos_left + 7);
				size_t pos_quote = sass.find_first_not_of(SASS2SCSS_FIND_WHITESPACE, pos_import);
				// leave proper urls untouched
				if (sass.substr(pos_quote, 4) != "url(")
				{
					// check if the url appears to be already quoted
					if (sass.substr(pos_quote, 1) != "\"" && sass.substr(pos_quote, 1) != "\'")
					{
						// get position of the last char on the line
						size_t pos_end = sass.find_last_not_of(SASS2SCSS_FIND_WHITESPACE);
						// assertion check for valid result
						if (pos_end != string::npos)
						{
							// add quotes around the full line after the import statement
							sass = sass.substr(0, pos_quote) + "\"" + sass.substr(pos_quote, pos_end - pos_quote + 1) + "\"";
						}
					}
				}

			}
			else if (
				sass.substr(pos_left, 7) != "@return" &&
				sass.substr(pos_left, 7) != "@extend" &&
				sass.substr(pos_left, 8) != "@content"
			) {

				// try to find a colon in the current line, but only ...
				size_t pos_colon = sass.find_first_not_of(":", pos_left);
				// assertion for valid result
				if (pos_colon != string::npos)
				{
					// ... after the first word (skip begining colons)
					pos_colon = sass.find_first_of(":", pos_colon);
					// it is a selector if there was no colon found
					converter.selector = pos_colon == string::npos;
				}

			}

			// current line has more indentation
			if (indent.length() >= INDENT(converter).length())
			{
				// not in comment mode
				if (IS_PARSING(converter))
				{
					// has meaningfull chars
					if (hasCharData(sass))
					{
						// is probably a property
						// also true for selectors
						converter.property = true;
					}
				}
			}
			// current line has more indentation
			if (indent.length() > INDENT(converter).length())
			{
				// not in comment mode
				if (IS_PARSING(converter))
				{
					// had meaningfull chars
					if (converter.property)
					{
						// print block opener
						scss += opener(converter);
						// push new stack context
						converter.indents.push("");
						// store block indentation
						INDENT(converter) = indent;
					}
				}
				// is and will be a src comment
				else if (!IS_CSS_COMMENT(converter))
				{
					// scss does not allow multiline src comments
					// therefore add forward slashes to all lines
					sass.at(INDENT(converter).length()+0) = '/';
					// there is an edge case here if indentation
					// is minimal (will overwrite the fist char)
					sass.at(INDENT(converter).length()+1) = '/';
					// could code around that, but I dont' think
					// this will ever be the cause for any trouble
				}
			}

			// line is opening a new comment
			if (open == "/*" || open == "//")
			{
				// reset the property state
				converter.property = false;
				// close previous comment
				if (IS_CSS_COMMENT(converter) && open != "")
				{
					if (!STRIP_COMMENT(converter) && !CONVERT_COMMENT(converter)) scss += " */";
				}
				// force single line comments
				// into a correct css comment
				if (CONVERT_COMMENT(converter))
				{
					if (IS_PARSING(converter))
					{ sass.at(pos_left + 1) = '*'; }
				}
				// set comment flag
				converter.comment = open;

			}

			// flush data only under certain conditions
			if (!(
				// strip css and src comments if option is set
				(IS_COMMENT(converter) && STRIP_COMMENT(converter)) ||
				// strip src comment even if strip option is not set
				// but only if the keep src comment option is not set
				(IS_SRC_COMMENT(converter) && ! KEEP_COMMENT(converter))
			))
			{
				// flush data and buffer whitespace
				scss += flush(sass, converter);
			}

			// get postion of last meaningfull char
			size_t pos_right = sass.find_last_not_of(SASS2SCSS_FIND_WHITESPACE);

			// check for invalid result
			if (pos_right != string::npos)
			{

				// get the last meaningfull char
				string close = sass.substr(pos_right, 1);

				// check if next line should be concatenated (list mode)
				converter.comma = IS_PARSING(converter) && close == ",";
				converter.semicolon = IS_PARSING(converter) && close == ";";

				// check if we have more than
				// one meaningfull char
				if (pos_right > 0)
				{

					// get the last two chars from string
					string close = sass.substr(pos_right - 1, 2);
					// update parser status for expicitly closed comment
					if (close == "*/") converter.comment = "";

				}

			}
			// EO have meaningfull chars from end

		}
		// EO have meaningfull chars from start

		// return scss
		return scss;

	}