<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/*
 * Copyright (C) 2015 Cloudius Systems, Ltd.
 */

#pragma once

/// \mainpage
///
/// Seastar is a high performance C++ application framework for high
/// concurrency server applications.
///
/// A good place to start is the [Tutorial](doc/tutorial.md).
///
/// Please see:
///   - \ref future-module Documentation on futures and promises, which are
///          the seastar building blocks.
///   - \ref future-util Utililty functions for working with futures
///   - \ref memory-module Memory management
///   - \ref networking-module TCP/IP networking
///   - \ref fileio-module File Input/Output
///   - \ref smp-module Multicore support
///   - \ref fiber-module Utilities for managing loosely coupled chains of
///          continuations, also known as fibers
///   - \ref thread-module Support for traditional threaded execution
///   - \ref rpc Build high-level communication protocols
///
/// View the [Seastar compatibility statement](./md_compatibility.html) for
/// information about library evolution.

#include <seastar/core/sstring.hh>
#include <seastar/core/future.hh>
#include <seastar/core/file-types.hh>
#include <seastar/util/bool_class.hh>
#include <seastar/util/std-compat.hh>
#include "./internal/api-level.hh"

namespace seastar {

// iostream.hh
template <class CharType> class input_stream;
template <class CharType> class output_stream;

class server_socket;
class socket;
class connected_socket;
class socket_address;
struct listen_options;
enum class transport;

// file.hh
class file;
struct file_open_options;
struct stat_data;

namespace net {

class udp_channel;

}

// Networking API

/// \defgroup networking-module Networking
///
/// Seastar provides a simple networking API, backed by two
/// TCP/IP stacks: the POSIX stack, utilizing the kernel's
/// BSD socket APIs, and the native stack, implement fully
/// within seastar and able to drive network cards directly.
/// The native stack supports zero-copy on both transmit
/// and receive, and is implemented using seastar's high
/// performance, lockless sharded design.  The network stack
/// can be selected with the \c \--network-stack command-line
/// parameter.

/// \addtogroup networking-module
/// @{

/// Listen for connections on a given port
///
/// Starts listening on a given address for incoming connections.
///
/// \param sa socket address to listen on
///
/// \return \ref server_socket object ready to accept connections.
///
/// \see listen(socket_address sa, listen_options opts)
server_socket listen(socket_address sa);

/// Listen for connections on a given port
///
/// Starts listening on a given address for incoming connections.
///
/// \param sa socket address to listen on
/// \param opts options controlling the listen operation
///
/// \return \ref server_socket object ready to accept connections.
///
/// \see listen(socket_address sa)
server_socket listen(socket_address sa, listen_options opts);

/// Establishes a connection to a given address
///
/// Attempts to connect to the given address.
///
/// \param sa socket address to connect to
///
/// \return a \ref connected_socket object, or an exception
future<connected_socket> connect(socket_address sa);

/// Establishes a connection to a given address
///
/// Attempts to connect to the given address with a defined local endpoint
///
/// \param sa socket address to connect to
/// \param local socket address for local endpoint
/// \param proto transport protocol (TCP or SCTP)
///
/// \return a \ref connected_socket object, or an exception
future<connected_socket> connect(socket_address sa, socket_address local, transport proto);

/// Creates a socket object suitable for establishing stream-oriented connections
///
/// \return a \ref net::socket object that can be used for establishing connections
socket make_socket();

/// Creates a udp_channel object suitable for sending UDP packets
///
/// The channel is not bound to a local address, and thus can only be used
/// for sending.
///
/// \return a \ref net::udp_channel object that can be used for UDP transfers.
net::udp_channel make_udp_channel();

/// Creates a udp_channel object suitable for sending and receiving UDP packets
///
/// \param local local address to bind to
///
/// \return a \ref net::udp_channel object that can be used for UDP transfers.
net::udp_channel make_udp_channel(const socket_address& local);

/// @}

/// \defgroup fileio-module File Input/Output
///
/// Seastar provides a file API to deal with persistent storage.
/// Unlike most file APIs, seastar offers unbuffered file I/O
/// (similar to, and based on, \c O_DIRECT).  Unbuffered I/O means
/// that the application is required to do its own caching, but
/// delivers better performance if this caching is done correctly.
///
/// For random I/O or sequential unbuffered I/O, the \ref file
/// class provides a set of methods for reading, writing, discarding,
/// or otherwise manipulating a file.  For buffered sequential I/O,
/// see \ref make_file_input_stream() and \ref make_file_output_stream().

/// \addtogroup fileio-module
/// @{

/// Opens or creates a file.  The "dma" in the name refers to the fact
/// that data transfers are unbuffered and uncached.
///
/// \param name  the name of the file to open or create
/// \param flags various flags controlling the open process
/// \return a \ref file object, as a future
///
/// \note
/// The file name is not guaranteed to be stable on disk, unless the
/// containing directory is sync'ed.
///
/// \relates file
future<file> open_file_dma(sstring name, open_flags flags) noexcept;

/// Opens or creates a file.  The "dma" in the name refers to the fact
/// that data transfers are unbuffered and uncached.
///
/// \param name  the name of the file to open or create
/// \param flags various flags controlling the open process
/// \param options options for opening the file
/// \return a \ref file object, as a future
///
/// \note
/// The file name is not guaranteed to be stable on disk, unless the
/// containing directory is sync'ed.
///
/// \relates file
future<file> open_file_dma(sstring name, open_flags flags, file_open_options options) noexcept;

/// Checks if a given directory supports direct io
///
/// Seastar bypasses the Operating System caches and issues direct io to the
/// underlying block devices. Projects using seastar should check if the directory
/// lies in a filesystem that support such operations. This function can be used
/// to do that.
///
/// It will return if direct io can be used, or throw an std::system_error
/// exception, with the EINVAL error code.
///
/// A std::system_error with the respective error code is also thrown if \ref path is
/// not a directory.
///
/// \param path the directory we need to verify.
future<> check_direct_io_support(sstring path);

/// Opens a directory.
///
/// \param name name of the directory to open
///
/// \return a \ref file object representing a directory.  The only
///    legal operations are \ref file::list_directory(),
///    \ref file::fsync(), and \ref file::close().
///
/// \relates file
future<file> open_directory(sstring name) noexcept;

/// Creates a new directory.
///
/// \param name name of the directory to create
/// \param permissions optional file permissions of the directory to create.
///
/// \note
/// The directory is not guaranteed to be stable on disk, unless the
/// containing directory is sync'ed.
future<> make_directory(sstring name, file_permissions permissions = file_permissions::default_dir_permissions) noexcept;

/// Ensures a directory exists
///
/// Checks whether a directory exists, and if not, creates it.  Only
/// the last component of the directory name is created.
///
/// \param name name of the directory to potentially create
/// \param permissions optional file permissions of the directory to create.
///
/// \note
/// The directory is not guaranteed to be stable on disk, unless the
/// containing directory is sync'ed.
/// If the directory exists, the provided permissions are not applied.
future<> touch_directory(sstring name, file_permissions permissions = file_permissions::default_dir_permissions) noexcept;

/// Recursively ensures a directory exists
///
/// Checks whether each component of a directory exists, and if not, creates it.
///
/// \param name name of the directory to potentially create
/// \param permissions optional file permissions of the directory to create.
///
/// \note
/// This function fsyncs each component created, and is therefore guaranteed to be stable on disk.
/// The provided permissions are applied only on the last component in the path, if it needs to be created,
/// if intermediate directories do not exist, they are created with the default_dir_permissions.
/// If any directory exists, the provided permissions are not applied.
future<> recursive_touch_directory(sstring name, file_permissions permissions = file_permissions::default_dir_permissions) noexcept;

/// Synchronizes a directory to disk
///
/// Makes sure the modifications in a directory are synchronized in disk.
/// This is useful, for instance, after creating or removing a file inside the
/// directory.
///
/// \param name name of the directory to potentially create
future<> sync_directory(sstring name) noexcept;

/// Removes (unlinks) a file or an empty directory
///
/// \param name name of the file or the directory to remove
///
/// \note
/// The removal is not guaranteed to be stable on disk, unless the
/// containing directory is sync'ed.
future<> remove_file(sstring name) noexcept;

/// Renames (moves) a file.
///
/// \param old_name existing file name
/// \param new_name new file name
///
/// \note
/// The rename is not guaranteed to be stable on disk, unless the
/// both containing directories are sync'ed.
future<> rename_file(sstring old_name, sstring new_name) noexcept;

struct follow_symlink_tag { };
using follow_symlink = bool_class<follow_symlink_tag>;

/// Return stat information about a file.
///
/// \param name name of the file to return its stat information
/// \param follow_symlink follow symbolic links.
///
/// \return stat_data of the file identified by name.
/// If name identifies a symbolic link then stat_data is returned either for the target of the link,
/// with follow_symlink::yes, or for the link itself, with follow_symlink::no.
future<stat_data> file_stat(sstring name, follow_symlink fs = follow_symlink::yes) noexcept;

/// Return the size of a file.
///
/// \param name name of the file to return the size
///
/// Note that file_size of a symlink is NOT the size of the symlink -
/// which is the length of the pathname it contains -
/// but rather the size of the file to which it points.
future<uint64_t> file_size(sstring name) noexcept;

/// Check file access.
///
/// \param name name of the file to check
/// \param flags bit pattern containing type of access to check (read/write/execute or exists).
///
/// If only access_flags::exists is queried, returns true if the file exists, or false otherwise.
/// Throws a std::filesystem::filesystem_error exception if any error other than ENOENT is encountered.
///
/// If any of the access_flags (read/write/execute) is set, returns true if the file exists and is
/// accessible with the requested flags, or false if the file exists and is not accessible
/// as queried.
/// Throws a std::filesystem::filesystem_error exception if any error other than EACCES is encountered.
/// Note that if any path component leading to the file is not searchable, the file is considered inaccessible
/// with the requested mode and false will be returned.
future<bool> file_accessible(sstring name, access_flags flags) noexcept;

/// check if a file exists.
///
/// \param name name of the file to check
future<bool> file_exists(sstring name) noexcept;

/// Determine the type of a file (regular file, directory, etc.)
///
/// \param name name of the file for which type information is requested
/// \param name follow_symlink whether a trailing symbolic link should be followed or not
///
/// \return a engaged optional with the file type if lookup was successful; a disengaged optional
///      if the file (or one of its parent directories) does not exist; an exceptional future on
///      other errors.
future<std::optional<directory_entry_type>> file_type(sstring name, follow_symlink = follow_symlink::yes) noexcept;

/// Creates a hard link for a file
///
/// \param oldpath existing file name
/// \param newpath name of link
///
future<> link_file(sstring oldpath, sstring newpath) noexcept;

/// Changes the permissions mode of a file or directory
///
/// \param name name of the file ot directory to change
/// \param permissions permissions to set
///
future<> chmod(sstring name, file_permissions permissions) noexcept;

/// Return information about the filesystem where a file is located.
///
/// \param name name of the file to inspect
future<fs_type> file_system_at(sstring name) noexcept;

/// Return space available to unprivileged users in filesystem where a file is located, in bytes.
///
/// \param name name of the file to inspect
future<uint64_t> fs_avail(sstring name) noexcept;

/// Return free space in filesystem where a file is located, in bytes.
///
/// \param name name of the file to inspect
future<uint64_t> fs_free(sstring name) noexcept;
/// @}

}
<commit_msg>doc: seastar: fix refrence to doc/tutorial.md<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/*
 * Copyright (C) 2015 Cloudius Systems, Ltd.
 */

#pragma once

/// \mainpage
///
/// Seastar is a high performance C++ application framework for high
/// concurrency server applications.
///
/// A good place to start is the [Tutorial](tutorial.html).
///
/// Please see:
///   - \ref future-module Documentation on futures and promises, which are
///          the seastar building blocks.
///   - \ref future-util Utililty functions for working with futures
///   - \ref memory-module Memory management
///   - \ref networking-module TCP/IP networking
///   - \ref fileio-module File Input/Output
///   - \ref smp-module Multicore support
///   - \ref fiber-module Utilities for managing loosely coupled chains of
///          continuations, also known as fibers
///   - \ref thread-module Support for traditional threaded execution
///   - \ref rpc Build high-level communication protocols
///
/// View the [Seastar compatibility statement](./md_compatibility.html) for
/// information about library evolution.

#include <seastar/core/sstring.hh>
#include <seastar/core/future.hh>
#include <seastar/core/file-types.hh>
#include <seastar/util/bool_class.hh>
#include <seastar/util/std-compat.hh>
#include "./internal/api-level.hh"

namespace seastar {

// iostream.hh
template <class CharType> class input_stream;
template <class CharType> class output_stream;

class server_socket;
class socket;
class connected_socket;
class socket_address;
struct listen_options;
enum class transport;

// file.hh
class file;
struct file_open_options;
struct stat_data;

namespace net {

class udp_channel;

}

// Networking API

/// \defgroup networking-module Networking
///
/// Seastar provides a simple networking API, backed by two
/// TCP/IP stacks: the POSIX stack, utilizing the kernel's
/// BSD socket APIs, and the native stack, implement fully
/// within seastar and able to drive network cards directly.
/// The native stack supports zero-copy on both transmit
/// and receive, and is implemented using seastar's high
/// performance, lockless sharded design.  The network stack
/// can be selected with the \c \--network-stack command-line
/// parameter.

/// \addtogroup networking-module
/// @{

/// Listen for connections on a given port
///
/// Starts listening on a given address for incoming connections.
///
/// \param sa socket address to listen on
///
/// \return \ref server_socket object ready to accept connections.
///
/// \see listen(socket_address sa, listen_options opts)
server_socket listen(socket_address sa);

/// Listen for connections on a given port
///
/// Starts listening on a given address for incoming connections.
///
/// \param sa socket address to listen on
/// \param opts options controlling the listen operation
///
/// \return \ref server_socket object ready to accept connections.
///
/// \see listen(socket_address sa)
server_socket listen(socket_address sa, listen_options opts);

/// Establishes a connection to a given address
///
/// Attempts to connect to the given address.
///
/// \param sa socket address to connect to
///
/// \return a \ref connected_socket object, or an exception
future<connected_socket> connect(socket_address sa);

/// Establishes a connection to a given address
///
/// Attempts to connect to the given address with a defined local endpoint
///
/// \param sa socket address to connect to
/// \param local socket address for local endpoint
/// \param proto transport protocol (TCP or SCTP)
///
/// \return a \ref connected_socket object, or an exception
future<connected_socket> connect(socket_address sa, socket_address local, transport proto);

/// Creates a socket object suitable for establishing stream-oriented connections
///
/// \return a \ref net::socket object that can be used for establishing connections
socket make_socket();

/// Creates a udp_channel object suitable for sending UDP packets
///
/// The channel is not bound to a local address, and thus can only be used
/// for sending.
///
/// \return a \ref net::udp_channel object that can be used for UDP transfers.
net::udp_channel make_udp_channel();

/// Creates a udp_channel object suitable for sending and receiving UDP packets
///
/// \param local local address to bind to
///
/// \return a \ref net::udp_channel object that can be used for UDP transfers.
net::udp_channel make_udp_channel(const socket_address& local);

/// @}

/// \defgroup fileio-module File Input/Output
///
/// Seastar provides a file API to deal with persistent storage.
/// Unlike most file APIs, seastar offers unbuffered file I/O
/// (similar to, and based on, \c O_DIRECT).  Unbuffered I/O means
/// that the application is required to do its own caching, but
/// delivers better performance if this caching is done correctly.
///
/// For random I/O or sequential unbuffered I/O, the \ref file
/// class provides a set of methods for reading, writing, discarding,
/// or otherwise manipulating a file.  For buffered sequential I/O,
/// see \ref make_file_input_stream() and \ref make_file_output_stream().

/// \addtogroup fileio-module
/// @{

/// Opens or creates a file.  The "dma" in the name refers to the fact
/// that data transfers are unbuffered and uncached.
///
/// \param name  the name of the file to open or create
/// \param flags various flags controlling the open process
/// \return a \ref file object, as a future
///
/// \note
/// The file name is not guaranteed to be stable on disk, unless the
/// containing directory is sync'ed.
///
/// \relates file
future<file> open_file_dma(sstring name, open_flags flags) noexcept;

/// Opens or creates a file.  The "dma" in the name refers to the fact
/// that data transfers are unbuffered and uncached.
///
/// \param name  the name of the file to open or create
/// \param flags various flags controlling the open process
/// \param options options for opening the file
/// \return a \ref file object, as a future
///
/// \note
/// The file name is not guaranteed to be stable on disk, unless the
/// containing directory is sync'ed.
///
/// \relates file
future<file> open_file_dma(sstring name, open_flags flags, file_open_options options) noexcept;

/// Checks if a given directory supports direct io
///
/// Seastar bypasses the Operating System caches and issues direct io to the
/// underlying block devices. Projects using seastar should check if the directory
/// lies in a filesystem that support such operations. This function can be used
/// to do that.
///
/// It will return if direct io can be used, or throw an std::system_error
/// exception, with the EINVAL error code.
///
/// A std::system_error with the respective error code is also thrown if \ref path is
/// not a directory.
///
/// \param path the directory we need to verify.
future<> check_direct_io_support(sstring path);

/// Opens a directory.
///
/// \param name name of the directory to open
///
/// \return a \ref file object representing a directory.  The only
///    legal operations are \ref file::list_directory(),
///    \ref file::fsync(), and \ref file::close().
///
/// \relates file
future<file> open_directory(sstring name) noexcept;

/// Creates a new directory.
///
/// \param name name of the directory to create
/// \param permissions optional file permissions of the directory to create.
///
/// \note
/// The directory is not guaranteed to be stable on disk, unless the
/// containing directory is sync'ed.
future<> make_directory(sstring name, file_permissions permissions = file_permissions::default_dir_permissions) noexcept;

/// Ensures a directory exists
///
/// Checks whether a directory exists, and if not, creates it.  Only
/// the last component of the directory name is created.
///
/// \param name name of the directory to potentially create
/// \param permissions optional file permissions of the directory to create.
///
/// \note
/// The directory is not guaranteed to be stable on disk, unless the
/// containing directory is sync'ed.
/// If the directory exists, the provided permissions are not applied.
future<> touch_directory(sstring name, file_permissions permissions = file_permissions::default_dir_permissions) noexcept;

/// Recursively ensures a directory exists
///
/// Checks whether each component of a directory exists, and if not, creates it.
///
/// \param name name of the directory to potentially create
/// \param permissions optional file permissions of the directory to create.
///
/// \note
/// This function fsyncs each component created, and is therefore guaranteed to be stable on disk.
/// The provided permissions are applied only on the last component in the path, if it needs to be created,
/// if intermediate directories do not exist, they are created with the default_dir_permissions.
/// If any directory exists, the provided permissions are not applied.
future<> recursive_touch_directory(sstring name, file_permissions permissions = file_permissions::default_dir_permissions) noexcept;

/// Synchronizes a directory to disk
///
/// Makes sure the modifications in a directory are synchronized in disk.
/// This is useful, for instance, after creating or removing a file inside the
/// directory.
///
/// \param name name of the directory to potentially create
future<> sync_directory(sstring name) noexcept;

/// Removes (unlinks) a file or an empty directory
///
/// \param name name of the file or the directory to remove
///
/// \note
/// The removal is not guaranteed to be stable on disk, unless the
/// containing directory is sync'ed.
future<> remove_file(sstring name) noexcept;

/// Renames (moves) a file.
///
/// \param old_name existing file name
/// \param new_name new file name
///
/// \note
/// The rename is not guaranteed to be stable on disk, unless the
/// both containing directories are sync'ed.
future<> rename_file(sstring old_name, sstring new_name) noexcept;

struct follow_symlink_tag { };
using follow_symlink = bool_class<follow_symlink_tag>;

/// Return stat information about a file.
///
/// \param name name of the file to return its stat information
/// \param follow_symlink follow symbolic links.
///
/// \return stat_data of the file identified by name.
/// If name identifies a symbolic link then stat_data is returned either for the target of the link,
/// with follow_symlink::yes, or for the link itself, with follow_symlink::no.
future<stat_data> file_stat(sstring name, follow_symlink fs = follow_symlink::yes) noexcept;

/// Return the size of a file.
///
/// \param name name of the file to return the size
///
/// Note that file_size of a symlink is NOT the size of the symlink -
/// which is the length of the pathname it contains -
/// but rather the size of the file to which it points.
future<uint64_t> file_size(sstring name) noexcept;

/// Check file access.
///
/// \param name name of the file to check
/// \param flags bit pattern containing type of access to check (read/write/execute or exists).
///
/// If only access_flags::exists is queried, returns true if the file exists, or false otherwise.
/// Throws a std::filesystem::filesystem_error exception if any error other than ENOENT is encountered.
///
/// If any of the access_flags (read/write/execute) is set, returns true if the file exists and is
/// accessible with the requested flags, or false if the file exists and is not accessible
/// as queried.
/// Throws a std::filesystem::filesystem_error exception if any error other than EACCES is encountered.
/// Note that if any path component leading to the file is not searchable, the file is considered inaccessible
/// with the requested mode and false will be returned.
future<bool> file_accessible(sstring name, access_flags flags) noexcept;

/// check if a file exists.
///
/// \param name name of the file to check
future<bool> file_exists(sstring name) noexcept;

/// Determine the type of a file (regular file, directory, etc.)
///
/// \param name name of the file for which type information is requested
/// \param name follow_symlink whether a trailing symbolic link should be followed or not
///
/// \return a engaged optional with the file type if lookup was successful; a disengaged optional
///      if the file (or one of its parent directories) does not exist; an exceptional future on
///      other errors.
future<std::optional<directory_entry_type>> file_type(sstring name, follow_symlink = follow_symlink::yes) noexcept;

/// Creates a hard link for a file
///
/// \param oldpath existing file name
/// \param newpath name of link
///
future<> link_file(sstring oldpath, sstring newpath) noexcept;

/// Changes the permissions mode of a file or directory
///
/// \param name name of the file ot directory to change
/// \param permissions permissions to set
///
future<> chmod(sstring name, file_permissions permissions) noexcept;

/// Return information about the filesystem where a file is located.
///
/// \param name name of the file to inspect
future<fs_type> file_system_at(sstring name) noexcept;

/// Return space available to unprivileged users in filesystem where a file is located, in bytes.
///
/// \param name name of the file to inspect
future<uint64_t> fs_avail(sstring name) noexcept;

/// Return free space in filesystem where a file is located, in bytes.
///
/// \param name name of the file to inspect
future<uint64_t> fs_free(sstring name) noexcept;
/// @}

}
<|endoftext|>


<commit_before>/*
    Copyright (C) 1998 by Jorrit Tyberghein

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"
#include "csutil/csvector.h"
#include "isound/loader.h"
#include "isys/system.h"
#include "isys/vfs.h"
#include "isound/data.h"

class csSoundLoaderMultiplexer : public iSoundLoader {
private:
  csVector Loaders;

public:
  DECLARE_IBASE;

  // constructor
  csSoundLoaderMultiplexer(iBase *iParent);

  // destructor
  virtual ~csSoundLoaderMultiplexer();

  // Initialize the Sound Loader.
  virtual bool Initialize (iSystem *sys);

  // Load a sound file from the VFS.
  virtual iSoundData *LoadSound(void *Data, unsigned long Size) const;
};

IMPLEMENT_FACTORY(csSoundLoaderMultiplexer);

EXPORT_CLASS_TABLE (sndplex)
EXPORT_CLASS_DEP (csSoundLoaderMultiplexer,
  "crystalspace.sound.loader.multiplexer", "Sound Loader Multiplexer",
  "crystalspace.sound.loader.")
EXPORT_CLASS_TABLE_END;

IMPLEMENT_IBASE(csSoundLoaderMultiplexer)
  IMPLEMENTS_INTERFACE(iSoundLoader)
  IMPLEMENTS_INTERFACE(iPlugIn)
IMPLEMENT_IBASE_END;

csSoundLoaderMultiplexer::csSoundLoaderMultiplexer(iBase *iParent) {
  CONSTRUCT_IBASE(iParent);
}

csSoundLoaderMultiplexer::~csSoundLoaderMultiplexer() {
  for (long i=0; i<Loaders.Length(); i++) {
    iSoundLoader *ldr=(iSoundLoader*)(Loaders.Get(i));
    ldr->DecRef();
  }
}

bool csSoundLoaderMultiplexer::Initialize(iSystem *sys)
{
  sys->Printf(MSG_INITIALIZATION, "Initializing sound loading multiplexer...\n");
  sys->Printf(MSG_INITIALIZATION, "  Looking for sound loader modules:\n");

  iVFS *pVFS = QUERY_PLUGIN (sys, iVFS);
  if (pVFS)
  {
    csVector list;
    iSCF::SCF->QueryClassList ("crystalspace.sound.loader.", list);
    for (long i=0; i<list.Length (); i++)
    {
      const char *classname = (const char *)list.Get (i);
      if (strcasecmp (classname, "crystalspace.sound.loader.multiplexer"))
      {
	sys->Printf(MSG_INITIALIZATION, "  soundloader: %s\n", classname);
	iSoundLoader *ldr = LOAD_PLUGIN (sys, classname, 0, iSoundLoader);
	if (ldr)
	  Loaders.Push(ldr);
      }
    }
    pVFS->DecRef ();
    return true;
  }
  else
    sys->Printf(MSG_WARNING,
		"  Oops, couldn't query iVFS from the system driver, cannot look for soundloaders now !\n");
  return false;
}

iSoundData *csSoundLoaderMultiplexer::LoadSound(void *Data, unsigned long Size) const {
  for (long i=0;i<Loaders.Length();i++) {
    iSoundLoader *Ldr=(iSoundLoader*)(Loaders.Get(i));
    iSoundData *snd=Ldr->LoadSound(Data, Size);
    if (snd) return snd;
  }
  return NULL;
}
<commit_msg>removed the unneeded query for iVFS, don't no why i coded it in in the first place, probably to hog the system a bit<commit_after>/*
    Copyright (C) 1998 by Jorrit Tyberghein

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"
#include "csutil/csvector.h"
#include "isound/loader.h"
#include "isys/system.h"
#include "isys/vfs.h"
#include "isound/data.h"

class csSoundLoaderMultiplexer : public iSoundLoader {
private:
  csVector Loaders;

public:
  DECLARE_IBASE;

  // constructor
  csSoundLoaderMultiplexer(iBase *iParent);

  // destructor
  virtual ~csSoundLoaderMultiplexer();

  // Initialize the Sound Loader.
  virtual bool Initialize (iSystem *sys);

  // Load a sound file from the VFS.
  virtual iSoundData *LoadSound(void *Data, unsigned long Size) const;
};

IMPLEMENT_FACTORY(csSoundLoaderMultiplexer);

EXPORT_CLASS_TABLE (sndplex)
EXPORT_CLASS_DEP (csSoundLoaderMultiplexer,
  "crystalspace.sound.loader.multiplexer", "Sound Loader Multiplexer",
  "crystalspace.sound.loader.")
EXPORT_CLASS_TABLE_END;

IMPLEMENT_IBASE(csSoundLoaderMultiplexer)
  IMPLEMENTS_INTERFACE(iSoundLoader)
  IMPLEMENTS_INTERFACE(iPlugIn)
IMPLEMENT_IBASE_END;

csSoundLoaderMultiplexer::csSoundLoaderMultiplexer(iBase *iParent) {
  CONSTRUCT_IBASE(iParent);
}

csSoundLoaderMultiplexer::~csSoundLoaderMultiplexer() {
  for (long i=0; i<Loaders.Length(); i++) {
    iSoundLoader *ldr=(iSoundLoader*)(Loaders.Get(i));
    ldr->DecRef();
  }
}

bool csSoundLoaderMultiplexer::Initialize(iSystem *sys)
{
  sys->Printf(MSG_INITIALIZATION, "Initializing sound loading multiplexer...\n");
  sys->Printf(MSG_INITIALIZATION, "  Looking for sound loader modules:\n");

  csVector list;
  iSCF::SCF->QueryClassList ("crystalspace.sound.loader.", list);
  for (long i=0; i<list.Length (); i++)
  {
    const char *classname = (const char *)list.Get (i);
    if (strcasecmp (classname, "crystalspace.sound.loader.multiplexer"))
    {
      sys->Printf(MSG_INITIALIZATION, "  soundloader: %s\n", classname);
      iSoundLoader *ldr = LOAD_PLUGIN (sys, classname, 0, iSoundLoader);
      if (ldr)
	Loaders.Push(ldr);
    }
  }
  return true;
}

iSoundData *csSoundLoaderMultiplexer::LoadSound(void *Data, unsigned long Size) const {
  for (long i=0;i<Loaders.Length();i++) {
    iSoundLoader *Ldr=(iSoundLoader*)(Loaders.Get(i));
    iSoundData *snd=Ldr->LoadSound(Data, Size);
    if (snd) return snd;
  }
  return NULL;
}
<|endoftext|>


<commit_before>//===- Filesystem.cpp -----------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a few utility functions to handle files.
//
//===----------------------------------------------------------------------===//

#include "Filesystem.h"
#include "Config.h"
#include "lld/Common/Threads.h"
#include "llvm/Config/config.h"
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/FileSystem.h"
#if defined(HAVE_UNISTD_H)
#include <unistd.h>
#endif

using namespace llvm;

using namespace lld;
using namespace lld::elf;

// Removes a given file asynchronously. This is a performance hack,
// so remove this when operating systems are improved.
//
// On Linux (and probably on other Unix-like systems), unlink(2) is a
// noticeably slow system call. As of 2016, unlink takes 250
// milliseconds to remove a 1 GB file on ext4 filesystem on my machine.
//
// To create a new result file, we first remove existing file. So, if
// you repeatedly link a 1 GB program in a regular compile-link-debug
// cycle, every cycle wastes 250 milliseconds only to remove a file.
// Since LLD can link a 1 GB binary in about 5 seconds, that waste
// actually counts.
//
// This function spawns a background thread to remove the file.
// The calling thread returns almost immediately.
void elf::unlinkAsync(StringRef Path) {
// Removing a file is async on windows.
#if defined(LLVM_ON_WIN32)
  sys::fs::remove(Path);
#else
  if (!ThreadsEnabled || !sys::fs::exists(Path) ||
      !sys::fs::is_regular_file(Path))
    return;

  // We cannot just remove path from a different thread because we are now going
  // to create path as a new file.
  // Instead we open the file and unlink it on this thread. The unlink is fast
  // since the open fd guarantees that it is not removing the last reference.
  int FD;
  if (std::error_code EC = sys::fs::openFileForRead(Path, FD))
    return;

  sys::fs::remove(Path);

  // close and therefore remove TempPath in background.
  runBackground([=] { ::close(FD); });
#endif
}

// Simulate file creation to see if Path is writable.
//
// Determining whether a file is writable or not is amazingly hard,
// and after all the only reliable way of doing that is to actually
// create a file. But we don't want to do that in this function
// because LLD shouldn't update any file if it will end in a failure.
// We also don't want to reimplement heuristics to determine if a
// file is writable. So we'll let FileOutputBuffer do the work.
//
// FileOutputBuffer doesn't touch a desitnation file until commit()
// is called. We use that class without calling commit() to predict
// if the given file is writable.
std::error_code elf::tryCreateFile(StringRef Path) {
  if (Path.empty())
    return std::error_code();
  return FileOutputBuffer::create(Path, 1).getError();
}
<commit_msg>Use std::thread directly.<commit_after>//===- Filesystem.cpp -----------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a few utility functions to handle files.
//
//===----------------------------------------------------------------------===//

#include "Filesystem.h"
#include "Config.h"
#include "lld/Common/Threads.h"
#include "llvm/Config/config.h"
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/FileSystem.h"
#if defined(HAVE_UNISTD_H)
#include <unistd.h>
#endif
#include <thread>

using namespace llvm;

using namespace lld;
using namespace lld::elf;

// Removes a given file asynchronously. This is a performance hack,
// so remove this when operating systems are improved.
//
// On Linux (and probably on other Unix-like systems), unlink(2) is a
// noticeably slow system call. As of 2016, unlink takes 250
// milliseconds to remove a 1 GB file on ext4 filesystem on my machine.
//
// To create a new result file, we first remove existing file. So, if
// you repeatedly link a 1 GB program in a regular compile-link-debug
// cycle, every cycle wastes 250 milliseconds only to remove a file.
// Since LLD can link a 1 GB binary in about 5 seconds, that waste
// actually counts.
//
// This function spawns a background thread to remove the file.
// The calling thread returns almost immediately.
void elf::unlinkAsync(StringRef Path) {
// Removing a file is async on windows.
#if defined(LLVM_ON_WIN32)
  sys::fs::remove(Path);
#else
  if (!ThreadsEnabled || !sys::fs::exists(Path) ||
      !sys::fs::is_regular_file(Path))
    return;

  // We cannot just remove path from a different thread because we are now going
  // to create path as a new file.
  // Instead we open the file and unlink it on this thread. The unlink is fast
  // since the open fd guarantees that it is not removing the last reference.
  int FD;
  if (std::error_code EC = sys::fs::openFileForRead(Path, FD))
    return;

  sys::fs::remove(Path);

  // close and therefore remove TempPath in background.
  std::thread([=] { ::close(FD); }).detach();
#endif
}

// Simulate file creation to see if Path is writable.
//
// Determining whether a file is writable or not is amazingly hard,
// and after all the only reliable way of doing that is to actually
// create a file. But we don't want to do that in this function
// because LLD shouldn't update any file if it will end in a failure.
// We also don't want to reimplement heuristics to determine if a
// file is writable. So we'll let FileOutputBuffer do the work.
//
// FileOutputBuffer doesn't touch a desitnation file until commit()
// is called. We use that class without calling commit() to predict
// if the given file is writable.
std::error_code elf::tryCreateFile(StringRef Path) {
  if (Path.empty())
    return std::error_code();
  return FileOutputBuffer::create(Path, 1).getError();
}
<|endoftext|>


<commit_before>#include "LIBMCRD.H"
#include "LIBETC.H"

#include <stdio.h>
#include <assert.h>
#include <string.h>

#define MC_HEADER_FRAME_INDEX (0)

int bIsInitialised = 0;
int bCanUseMemoryCardFuncs = 0;
int memoryCardStatus = -1;

FILE* memoryCards[2];
int memoryCardsNew[2];

long memoryCardCmds = -1;
long memoryCardResult = -1;

void MemCardInit(long val)
{
	bIsInitialised = 1;
	bCanUseMemoryCardFuncs = 0;
	memoryCardStatus = -1;
	memoryCardCmds = -1;
	memoryCardResult = -1;
	memoryCardsNew[0] = 1;
	memoryCardsNew[1] = 1;
}

void MemCardEnd()
{
	if (!bCanUseMemoryCardFuncs)
		return;

}

void MemCardStart()
{
	bCanUseMemoryCardFuncs = 1;
}

void MemCardStop()
{
	if (!bCanUseMemoryCardFuncs)
		return;

}
long MemCardExist(long chan)
{
	if (!bCanUseMemoryCardFuncs)
		return 0;

	char buf[16];
	sprintf(&buf[0], "%d.MCD", chan);
	memoryCards[chan] = fopen(&buf[0], "rb");

	memoryCardCmds = McFuncExist;

	if (memoryCards[chan] == NULL)
	{
		memoryCardStatus = -1;//CHECKME
		memoryCardResult = McErrCardNotExist;//CHECKME
		return 0;
	}
	else
	{
		fclose(memoryCards[chan]);

		if (memoryCardResult == McErrNewCard)
		{
			memoryCardResult = McErrNone;
			memoryCardStatus = 0;
		}
		else
		{
			memoryCardResult = McErrNewCard;
			memoryCardStatus = 1;
		}
	}

	return 1;
}

long MemCardAccept(long chan)
{
	if (!bCanUseMemoryCardFuncs)
		return 0;

	char buf[16];
	sprintf(&buf[0], "%d.MCD", chan);
	memoryCards[chan] = fopen(&buf[0], "rb");
	memoryCardCmds = McFuncAccept;

	unsigned int fileMagic = 0;
	fread(&fileMagic, 4, 1, memoryCards[chan]);

	//Is this card formatted?
	if (fileMagic != 0x0000434D || memoryCardsNew[chan] == 1)
	{
		//If not, this is a new card!
		memoryCardResult = McErrNewCard;
		memoryCardsNew[chan] = 0;
		return 0;
	}

	memoryCardResult = McErrNone;
	return 1;
}
long MemCardOpen(long chan, char* file, long flag)
{

	return 0;
}

void MemCardClose()
{

}

long MemCardReadData(unsigned long* adrs, long ofs, long bytes)
{
	memoryCardCmds = McFuncReadData;
	return 0;
}

long MemCardReadFile(long chan, char* file, unsigned long* adrs, long ofs, long bytes)
{
	memoryCardCmds = McFuncReadFile;
	return 0;
}

long MemCardWriteData(unsigned long* adrs, long ofs, long bytes)
{
	memoryCardCmds = McFuncWriteData;
	return 0;
}

long MemCardWriteFile(long chan, char* file, unsigned long* adrs, long ofs, long bytes)
{
	memoryCardCmds = McFuncWriteFile;

	return 0;
}

long MemCardCreateFile(long chan, char* file, long blocks)
{

	return 0;
}

long MemCardDeleteFile(long chan, char* file)
{

	return 0;
}

long MemCardFormat(long chan)
{

	return 0;
}

long MemCardUnformat(long chan)
{

	return 0;
}

long MemCardSync(long mode, long* cmds, long* rslt)
{
	if (mode == 1)
	{
		if (memoryCardCmds != -1)
		{
			*cmds = memoryCardCmds;
		}

		if (memoryCardResult != -1)
		{
			*rslt = memoryCardResult;
		}

		return memoryCardStatus;
	}

	return 0;
}

MemCB MemCardCallback(MemCB func)
{

	return 0;
}

long MemCardGetDirentry(long chan, char* name, struct DIRENTRY* dir, long* files, long ofs, long max)
{

#pragma pack(push,1)
	struct MemoryCardFrame
	{
		unsigned int attr;
		unsigned int size;
		unsigned short unknown;
		char name[20];
		char padding[98];
	};
#pragma pack(pop)
	//Read all
	fseek(memoryCards[chan], 0, SEEK_SET);

	if (strcmp(name, "*") == 0)
	{
		for (int i = 0, head = -64; i < 16; i++, head += 128)
		{
			MemoryCardFrame frame;
			fread(&frame, sizeof(MemoryCardFrame), 1, memoryCards[chan]);

			if (i > MC_HEADER_FRAME_INDEX && frame.name[0] != '\0')
			{
				memcpy(dir->name, &frame.name, 20);
				dir->attr = frame.attr & 0xF0;
				dir->size = frame.size;
				dir->next = (struct DIRENTRY*)9;
				dir->head = head;
				dir->system[0] = 9;
				dir++;
				files[0]++;
			}
		}
	}

	memoryCardStatus = -1;//?

	return 0;
}
<commit_msg>Improve MEMCARD emulation.<commit_after>#include "LIBMCRD.H"
#include "LIBETC.H"

#include <stdio.h>
#include <assert.h>
#include <string.h>

#define MC_HEADER_FRAME_INDEX (0)

int bIsInitialised = 0;
int bCanUseMemoryCardFuncs = 0;
int memoryCardStatus = -1;

FILE* memoryCards[2];
int memoryCardsNew[2];

long memoryCardCmds = -1;
long memoryCardResult = -1;

void MemCardInit(long val)
{
	bIsInitialised = 1;
	bCanUseMemoryCardFuncs = 0;
	memoryCardStatus = -1;
	memoryCardCmds = -1;
	memoryCardResult = -1;
	memoryCardsNew[0] = 1;
	memoryCardsNew[1] = 1;
}

void MemCardEnd()
{
	if (!bCanUseMemoryCardFuncs)
		return;

}

void MemCardStart()
{
	bCanUseMemoryCardFuncs = 1;
}

void MemCardStop()
{
	if (!bCanUseMemoryCardFuncs)
		return;

	bCanUseMemoryCardFuncs = 0;
	memoryCardStatus = -1;
	memoryCardCmds = -1;
	memoryCardResult = -1;
	memoryCardsNew[0] = 1;
	memoryCardsNew[1] = 1;

	if (memoryCards[0] != NULL)
	{
		fclose(memoryCards[0]);
	}

	if (memoryCards[1] != NULL)
	{
		fclose(memoryCards[1]);
	}
}

long MemCardExist(long chan)
{
	if (!bCanUseMemoryCardFuncs)
		return 0;

	char buf[16];
	sprintf(&buf[0], "%d.MCD", chan);
	memoryCards[chan] = fopen(&buf[0], "rb");

	memoryCardCmds = McFuncExist;

	if (memoryCards[chan] == NULL)
	{
		memoryCardStatus = -1;//CHECKME
		memoryCardResult = McErrCardNotExist;//CHECKME
		return 0;
	}
	else
	{
		fclose(memoryCards[chan]);

		if (memoryCardResult == McErrNewCard)
		{
			memoryCardResult = McErrNone;
			memoryCardStatus = 0;
		}
		else
		{
			memoryCardResult = McErrNewCard;
			memoryCardStatus = 1;
		}
	}

	return 1;
}

long MemCardAccept(long chan)
{
	if (!bCanUseMemoryCardFuncs)
		return 0;

	char buf[16];
	sprintf(&buf[0], "%d.MCD", chan);
	memoryCards[chan] = fopen(&buf[0], "rb");
	memoryCardCmds = McFuncAccept;

	unsigned int fileMagic = 0;
	fread(&fileMagic, 4, 1, memoryCards[chan]);

	//Is this card formatted?
	if (fileMagic != 0x0000434D)
	{
		//If not, this is a new card!
		memoryCardResult = McErrNewCard;
		memoryCardsNew[chan] = 0;
		return 0;
	}

	memoryCardResult = 3;
	memoryCardStatus = 1;
	return 1;
}
long MemCardOpen(long chan, char* file, long flag)
{

	return 0;
}

void MemCardClose()
{

}

long MemCardReadData(unsigned long* adrs, long ofs, long bytes)
{
	memoryCardCmds = McFuncReadData;
	return 0;
}

long MemCardReadFile(long chan, char* file, unsigned long* adrs, long ofs, long bytes)
{
	memoryCardCmds = McFuncReadFile;
	return 0;
}

long MemCardWriteData(unsigned long* adrs, long ofs, long bytes)
{
	memoryCardCmds = McFuncWriteData;
	return 0;
}

long MemCardWriteFile(long chan, char* file, unsigned long* adrs, long ofs, long bytes)
{
	memoryCardCmds = McFuncWriteFile;

	return 0;
}

long MemCardCreateFile(long chan, char* file, long blocks)
{

	return 0;
}

long MemCardDeleteFile(long chan, char* file)
{

	return 0;
}

long MemCardFormat(long chan)
{

	return 0;
}

long MemCardUnformat(long chan)
{

	return 0;
}

long MemCardSync(long mode, long* cmds, long* rslt)
{
	if (mode == 1)
	{
		if (memoryCardCmds != -1)
		{
			*cmds = memoryCardCmds;
		}

		if (memoryCardResult != -1)
		{
			*rslt = memoryCardResult;
		}

		return memoryCardStatus;
	}

	return 0;
}

MemCB MemCardCallback(MemCB func)
{

	return 0;
}

long MemCardGetDirentry(long chan, char* name, struct DIRENTRY* dir, long* files, long ofs, long max)
{

#pragma pack(push,1)
	struct MemoryCardFrame
	{
		unsigned int attr;
		unsigned int size;
		unsigned short unknown;
		char name[20];
		char padding[98];
	};
#pragma pack(pop)
	//Read all
	fseek(memoryCards[chan], 0, SEEK_SET);

	if (strcmp(name, "*") == 0)
	{
		for (int i = 0, head = -64; i < 16; i++, head += 128)
		{
			MemoryCardFrame frame;
			fread(&frame, sizeof(MemoryCardFrame), 1, memoryCards[chan]);

			if (i > MC_HEADER_FRAME_INDEX && frame.name[0] != '\0')
			{
				memcpy(dir->name, &frame.name, 20);
				dir->attr = frame.attr & 0xF0;
				dir->size = frame.size;
				dir->next = (struct DIRENTRY*)9;
				dir->head = head;
				dir->system[0] = 9;
				dir++;
				files[0]++;
			}
		}
	}
	memoryCardCmds = McFuncExist;
	memoryCardResult = 0;
	memoryCardStatus = 1;

	return 0;
}
<|endoftext|>


<commit_before><commit_msg>Fixups<commit_after><|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2013-2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <types.hpp>
#include <unique_ptr.hpp>
#include <algorithms.hpp>
#include <errors.hpp>

#include "fs/sysfs.hpp"

#include "console.hpp"
#include "rtc.hpp"

namespace {

struct sys_value {
    std::string name;
    std::string value;

    sys_value(){}
    sys_value(std::string name, std::string value) : name(name), value(value){
        //Nothing else to init
    }
};

struct sys_folder {
    std::string name;
    std::vector<sys_folder> folders;
    std::vector<sys_value> values;

    sys_folder(){}

    sys_folder(std::string name) : name(name) {
        //Nothing else to init
    }
};

std::vector<sys_folder> root_folders;

sys_folder& find_root_folder(const std::string& mount_point){
    for(auto& sys_folder : root_folders){
        if(sys_folder.name == mount_point){
            return sys_folder;
        }
    }

    root_folders.emplace_back(mount_point);

    return root_folders.back();
}

sys_folder& find_folder(sys_folder& root, const std::vector<std::string>& path, size_t i, size_t last){
    auto& name = path[i];

    for(auto& folder : root.folders){
        if(folder.name == name){
            if(i == last - 1){
                return folder;
            } else {
                return find_folder(folder, path, i + 1, last);
            }
        }
    }

    root.folders.emplace_back(name);

    if(i == last - 1){
        return root.folders.back();
    } else {
        return find_folder(root.folders.back(), path, i + 1, last);
    }
}

bool exists_folder(sys_folder& root, const std::vector<std::string>& path, size_t i, size_t last){
    auto& name = path[i];

    for(auto& folder : root.folders){
        if(folder.name == name){
            if(i == last - 1){
                return true;
            } else {
                return exists_folder(folder, path, i + 1, last);
            }
        }
    }

    return false;
}

} //end of anonymous namespace

sysfs::sysfs_file_system::sysfs_file_system(std::string mp) : mount_point(mp) {
    //Nothing to init
}

sysfs::sysfs_file_system::~sysfs_file_system(){
    //Nothing to delete
}

size_t sysfs::sysfs_file_system::get_file(const std::vector<std::string>& file_path, vfs::file& f){
    auto& root_folder = find_root_folder(mount_point);

    if(exists_folder(root_folder, file_path, 0, file_path.size() - 1)){
        auto& folder = find_folder(root_folder, file_path, 0, file_path.size() - 1);

        for(auto& file : folder.folders){
            if(file.name == file_path.back()){
                f.file_name = file.name;
                f.directory = true;
                f.hidden = false;
                f.system = false;
                f.size = 0;

                return 0;
            }
        }

        for(auto& file : folder.values){
            if(file.name == file_path.back()){
                f.file_name = file.name;
                f.directory = false;
                f.hidden = false;
                f.system = false;
                f.size = 0;

                return 0;
            }
        }
    }

    return std::ERROR_NOT_EXISTS;
}

size_t sysfs::sysfs_file_system::read(const std::vector<std::string>& file_path, std::string& content){
    auto& root_folder = find_root_folder(mount_point);

    if(exists_folder(root_folder, file_path, 0, file_path.size() - 1)){
        auto& folder = find_folder(root_folder, file_path, 0, file_path.size() - 1);

        for(auto& file : folder.values){
            if(file.name == file_path.back()){
                content = file.value;
                return 0;
            }
        }

        for(auto& file : folder.folders){
            if(file.name == file_path.back()){
                return std::ERROR_DIRECTORY;
            }
        }
    }

    return std::ERROR_NOT_EXISTS;
}

size_t sysfs::sysfs_file_system::ls(const std::vector<std::string>& file_path, std::vector<vfs::file>& contents){
    auto& root_folder = find_root_folder(mount_point);

    if(exists_folder(root_folder, file_path, 0, file_path.size() - 1)){
        auto& folder = find_folder(root_folder, file_path, 0, file_path.size() - 1);

        for(auto& file : folder.folders){
            vfs::file f;
            f.file_name = file.name;
            f.directory = true;
            f.hidden = false;
            f.system = false;
            f.size = 0;
            contents.push_back(f);
        }

        for(auto& file : folder.values){
            vfs::file f;
            f.file_name = file.name;
            f.directory = false;
            f.hidden = false;
            f.system = false;
            f.size = 0;
            contents.push_back(f);
        }

        return 0;
    } else {
        return std::ERROR_NOT_EXISTS;
    }
}

size_t sysfs::sysfs_file_system::touch(const std::vector<std::string>& ){
    return std::ERROR_PERMISSION_DENIED;
}

size_t sysfs::sysfs_file_system::mkdir(const std::vector<std::string>& ){
    return std::ERROR_PERMISSION_DENIED;
}

size_t sysfs::sysfs_file_system::rm(const std::vector<std::string>& ){
    return std::ERROR_PERMISSION_DENIED;
}

size_t sysfs::sysfs_file_system::statfs(statfs_info& file){
    file.total_size = 0;
    file.free_size = 0;

    return 0;
}

void set_value(const std::string& mount_point, const std::string& path, const std::string& value){
    auto& root_folder = find_root_folder(mount_point);

    auto file_path = std::split(path, '/');
    auto last = file_path.back();
    file_path.pop_back();

    auto& folder = find_folder(root_folder, file_path, 0, file_path.size());

    for(auto& v : folder.values){
        if(v.name == last){
            v.value = value;
            return;
        }
    }

    folder.values.emplace_back(last, value);
}

void delete_value(const std::string& mount_point, const std::string& path){
    auto& root_folder = find_root_folder(mount_point);

    auto file_path = std::split(path, '/');
    auto last = file_path.back();
    file_path.pop_back();

    auto& folder = find_folder(root_folder, file_path, 0, file_path.size());

    for(size_t i = 0; i < folder.values.size(); ++i){
        auto& v = folder.values[i];

        if(v.name == last){
            folder.values.erase(i);
            break;
        }
    }
}

void delete_folder(const std::string& mount_point, const std::string& path){
    auto& root_folder = find_root_folder(mount_point);

    auto file_path = std::split(path, '/');
    auto last = file_path.back();
    file_path.pop_back();

    auto& folder = find_folder(root_folder, file_path, 0, file_path.size());

    for(size_t i = 0; i < folder.folders.size(); ++i){
        auto& v = folder.folders[i];

        if(v.name == last){
            folder.folders.erase(i);
            break;
        }
    }
}
<commit_msg>Finish implementation of sysfs<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2013-2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <types.hpp>
#include <unique_ptr.hpp>
#include <algorithms.hpp>
#include <errors.hpp>

#include "fs/sysfs.hpp"

#include "console.hpp"
#include "rtc.hpp"

namespace {

struct sys_value {
    std::string name;
    std::string value;

    sys_value(){}
    sys_value(std::string name, std::string value) : name(name), value(value){
        //Nothing else to init
    }
};

struct sys_folder {
    std::string name;
    std::vector<sys_folder> folders;
    std::vector<sys_value> values;

    sys_folder(){}

    sys_folder(std::string name) : name(name) {
        //Nothing else to init
    }
};

std::vector<sys_folder> root_folders;

sys_folder& find_root_folder(const std::string& mount_point){
    for(auto& sys_folder : root_folders){
        if(sys_folder.name == mount_point){
            return sys_folder;
        }
    }

    root_folders.emplace_back(mount_point);

    return root_folders.back();
}

sys_folder& find_folder(sys_folder& root, const std::vector<std::string>& path, size_t i, size_t last){
    auto& name = path[i];

    for(auto& folder : root.folders){
        if(folder.name == name){
            if(i == last - 1){
                return folder;
            } else {
                return find_folder(folder, path, i + 1, last);
            }
        }
    }

    root.folders.emplace_back(name);

    if(i == last - 1){
        return root.folders.back();
    } else {
        return find_folder(root.folders.back(), path, i + 1, last);
    }
}

bool exists_folder(sys_folder& root, const std::vector<std::string>& path, size_t i, size_t last){
    auto& name = path[i];

    for(auto& folder : root.folders){
        if(folder.name == name){
            if(i == last - 1){
                return true;
            } else {
                return exists_folder(folder, path, i + 1, last);
            }
        }
    }

    return false;
}

size_t get_file(const sys_folder& folder, const std::vector<std::string>& file_path, vfs::file& f){
    for(auto& file : folder.folders){
        if(file.name == file_path.back()){
            f.file_name = file.name;
            f.directory = true;
            f.hidden = false;
            f.system = false;
            f.size = 0;

            return 0;
        }
    }

    for(auto& file : folder.values){
        if(file.name == file_path.back()){
            f.file_name = file.name;
            f.directory = false;
            f.hidden = false;
            f.system = false;
            f.size = 0;

            return 0;
        }
    }

    return std::ERROR_NOT_EXISTS;
}

size_t ls(const sys_folder& folder, std::vector<vfs::file>& contents){
    for(auto& file : folder.folders){
        vfs::file f;
        f.file_name = file.name;
        f.directory = true;
        f.hidden = false;
        f.system = false;
        f.size = 0;
        contents.push_back(f);
    }

    for(auto& file : folder.values){
        vfs::file f;
        f.file_name = file.name;
        f.directory = false;
        f.hidden = false;
        f.system = false;
        f.size = 0;
        contents.push_back(f);
    }

    return 0;
}

size_t read(const sys_folder& folder, const std::vector<std::string>& file_path, std::string& content){
    for(auto& file : folder.values){
        if(file.name == file_path.back()){
            content = file.value;
            return 0;
        }
    }

    for(auto& file : folder.folders){
        if(file.name == file_path.back()){
            return std::ERROR_DIRECTORY;
        }
    }

    return std::ERROR_NOT_EXISTS;
}

} //end of anonymous namespace

sysfs::sysfs_file_system::sysfs_file_system(std::string mp) : mount_point(mp) {
    //Nothing to init
}

sysfs::sysfs_file_system::~sysfs_file_system(){
    //Nothing to delete
}

size_t sysfs::sysfs_file_system::get_file(const std::vector<std::string>& file_path, vfs::file& f){
    auto& root_folder = find_root_folder(mount_point);

    if(file_path.empty()){
        f.file_name = "/";
        f.directory = true;
        f.hidden = false;
        f.system = false;
        f.size = 0;

        return 0;
    } else if(file_path.size() == 1){
        return ::get_file(root_folder, file_path, f);
    } else {
        if(exists_folder(root_folder, file_path, 0, file_path.size() - 1)){
            auto& folder = find_folder(root_folder, file_path, 0, file_path.size() - 1);

            return ::get_file(folder, file_path, f);
        }

        return std::ERROR_NOT_EXISTS;
    }
}

size_t sysfs::sysfs_file_system::read(const std::vector<std::string>& file_path, std::string& content){
    auto& root_folder = find_root_folder(mount_point);

    if(file_path.empty()){
        return std::ERROR_DIRECTORY;
    } else if(file_path.size() == 1){
        return ::read(root_folder, file_path, content);
    } else {
        if(exists_folder(root_folder, file_path, 0, file_path.size() - 1)){
            auto& folder = find_folder(root_folder, file_path, 0, file_path.size() - 1);

            return ::read(folder, file_path, content);
        }

        return std::ERROR_NOT_EXISTS;
    }
}

size_t sysfs::sysfs_file_system::ls(const std::vector<std::string>& file_path, std::vector<vfs::file>& contents){
    auto& root_folder = find_root_folder(mount_point);

    if(file_path.empty()){
        return ::ls(root_folder, contents);
    } else {
        if(exists_folder(root_folder, file_path, 0, file_path.size())){
            auto& folder = find_folder(root_folder, file_path, 0, file_path.size());

            return ::ls(folder, contents);
        }

        return std::ERROR_NOT_EXISTS;
    }
}

size_t sysfs::sysfs_file_system::touch(const std::vector<std::string>& ){
    return std::ERROR_PERMISSION_DENIED;
}

size_t sysfs::sysfs_file_system::mkdir(const std::vector<std::string>& ){
    return std::ERROR_PERMISSION_DENIED;
}

size_t sysfs::sysfs_file_system::rm(const std::vector<std::string>& ){
    return std::ERROR_PERMISSION_DENIED;
}

size_t sysfs::sysfs_file_system::statfs(statfs_info& file){
    file.total_size = 0;
    file.free_size = 0;

    return 0;
}

void set_value(const std::string& mount_point, const std::string& path, const std::string& value){
    auto& root_folder = find_root_folder(mount_point);

    auto file_path = std::split(path, '/');
    auto last = file_path.back();
    file_path.pop_back();

    auto& folder = find_folder(root_folder, file_path, 0, file_path.size());

    for(auto& v : folder.values){
        if(v.name == last){
            v.value = value;
            return;
        }
    }

    folder.values.emplace_back(last, value);
}

void delete_value(const std::string& mount_point, const std::string& path){
    auto& root_folder = find_root_folder(mount_point);

    auto file_path = std::split(path, '/');
    auto last = file_path.back();
    file_path.pop_back();

    auto& folder = find_folder(root_folder, file_path, 0, file_path.size());

    for(size_t i = 0; i < folder.values.size(); ++i){
        auto& v = folder.values[i];

        if(v.name == last){
            folder.values.erase(i);
            break;
        }
    }
}

void delete_folder(const std::string& mount_point, const std::string& path){
    auto& root_folder = find_root_folder(mount_point);

    auto file_path = std::split(path, '/');
    auto last = file_path.back();
    file_path.pop_back();

    auto& folder = find_folder(root_folder, file_path, 0, file_path.size());

    for(size_t i = 0; i < folder.folders.size(); ++i){
        auto& v = folder.folders[i];

        if(v.name == last){
            folder.folders.erase(i);
            break;
        }
    }
}
<|endoftext|>


<commit_before>/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
/*
 * Copyright (c) 2008  litl, LLC
 * Copyright (c) 2012  Red Hat, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include <config.h>

#include <sys/types.h>
#include <unistd.h>

#include <gjs/gjs-module.h>
#include <gi/object.h>
#include "system.h"

static JSBool
gjs_address_of(JSContext *context,
               unsigned   argc,
               jsval     *vp)
{
    jsval *argv = JS_ARGV(cx, vp);
    JSObject *target_obj;
    JSBool ret;
    char *pointer_string;
    jsval retval;

    if (!gjs_parse_args(context, "addressOf", "o", argc, argv, "object", &target_obj))
        return JS_FALSE;

    pointer_string = g_strdup_printf("%p", target_obj);

    ret = gjs_string_from_utf8(context, pointer_string, -1, &retval);
    g_free(pointer_string);

    if (ret)
        JS_SET_RVAL(context, vp, retval);

    return ret;
}

static JSBool
gjs_refcount(JSContext *context,
             unsigned   argc,
             jsval     *vp)
{
    jsval *argv = JS_ARGV(cx, vp);
    jsval retval;
    JSObject *target_obj;
    GObject *obj;

    if (!gjs_parse_args(context, "refcount", "o", argc, argv, "object", &target_obj))
        return JS_FALSE;

    if (!gjs_typecheck_object(context, target_obj,
                              G_TYPE_OBJECT, JS_TRUE))
        return JS_FALSE;

    obj = gjs_g_object_from_object(context, target_obj);
    if (obj == NULL)
        return JS_FALSE;

    retval = INT_TO_JSVAL(obj->ref_count);
    JS_SET_RVAL(context, vp, retval);
    return JS_TRUE;
}

static JSBool
gjs_breakpoint(JSContext *context,
               unsigned   argc,
               jsval     *vp)
{
    jsval *argv = JS_ARGV(cx, vp);
    if (!gjs_parse_args(context, "breakpoint", "", argc, argv))
        return JS_FALSE;
    G_BREAKPOINT();
    JS_SET_RVAL(context, vp, JSVAL_VOID);
    return JS_TRUE;
}

static JSBool
gjs_gc(JSContext *context,
       unsigned   argc,
       jsval     *vp)
{
    jsval *argv = JS_ARGV(cx, vp);
    if (!gjs_parse_args(context, "gc", "", argc, argv))
        return JS_FALSE;
    JS_GC(JS_GetRuntime(context));
    JS_SET_RVAL(context, vp, JSVAL_VOID);
    return JS_TRUE;
}

static JSBool
gjs_exit(JSContext *context,
         unsigned   argc,
         jsval     *vp)
{
    jsval *argv = JS_ARGV(cx, vp);
    gint32 ecode;
    if (!gjs_parse_args(context, "exit", "i", argc, argv, "ecode", &ecode))
        return JS_FALSE;
    exit(ecode);
    return JS_TRUE;
}

static JSFunctionSpec module_funcs[] = {
    { "addressOf", JSOP_WRAPPER (gjs_address_of), 1, GJS_MODULE_PROP_FLAGS },
    { "refcount", JSOP_WRAPPER (gjs_refcount), 1, GJS_MODULE_PROP_FLAGS },
    { "breakpoint", JSOP_WRAPPER (gjs_breakpoint), 0, GJS_MODULE_PROP_FLAGS },
    { "gc", JSOP_WRAPPER (gjs_gc), 0, GJS_MODULE_PROP_FLAGS },
    { "exit", JSOP_WRAPPER (gjs_exit), 0, GJS_MODULE_PROP_FLAGS },
    { NULL },
};

JSBool
gjs_js_define_system_stuff(JSContext  *context,
                           JSObject  **module_out)
{
    GjsContext *gjs_context;
    char *program_name;
    jsval value;
    JSBool retval;
    JSObject *module;

    module = JS_NewObject (context, NULL, NULL, NULL);

    if (!JS_DefineFunctions(context, module, &module_funcs[0]))
        return JS_FALSE;

    retval = JS_FALSE;

    gjs_context = (GjsContext*) JS_GetContextPrivate(context);
    g_object_get(gjs_context,
                 "program-name", &program_name,
                 NULL);

    if (!gjs_string_from_utf8(context, program_name,
                              -1, &value))
        goto out;

    /* The name is modeled after program_invocation_name,
       part of the glibc */
    if (!JS_DefineProperty(context, module,
                           "programInvocationName",
                           value,
                           JS_PropertyStub,
                           JS_StrictPropertyStub,
                           GJS_MODULE_PROP_FLAGS | JSPROP_READONLY))
        goto out;

    if (!JS_DefineProperty(context, module,
                           "version",
                           INT_TO_JSVAL(GJS_VERSION),
                           JS_PropertyStub,
                           JS_StrictPropertyStub,
                           GJS_MODULE_PROP_FLAGS | JSPROP_READONLY))
        goto out;

    retval = JS_TRUE;

 out:
    g_free(program_name);
    *module_out = module;

    return retval;
}
<commit_msg>system: Add wrapper for JS_ClearDateCaches<commit_after>/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
/*
 * Copyright (c) 2008  litl, LLC
 * Copyright (c) 2012  Red Hat, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include <config.h>

#include <sys/types.h>
#include <unistd.h>
#include <time.h>

#include <gjs/gjs-module.h>
#include <gi/object.h>
#include "system.h"

static JSBool
gjs_address_of(JSContext *context,
               unsigned   argc,
               jsval     *vp)
{
    jsval *argv = JS_ARGV(cx, vp);
    JSObject *target_obj;
    JSBool ret;
    char *pointer_string;
    jsval retval;

    if (!gjs_parse_args(context, "addressOf", "o", argc, argv, "object", &target_obj))
        return JS_FALSE;

    pointer_string = g_strdup_printf("%p", target_obj);

    ret = gjs_string_from_utf8(context, pointer_string, -1, &retval);
    g_free(pointer_string);

    if (ret)
        JS_SET_RVAL(context, vp, retval);

    return ret;
}

static JSBool
gjs_refcount(JSContext *context,
             unsigned   argc,
             jsval     *vp)
{
    jsval *argv = JS_ARGV(cx, vp);
    jsval retval;
    JSObject *target_obj;
    GObject *obj;

    if (!gjs_parse_args(context, "refcount", "o", argc, argv, "object", &target_obj))
        return JS_FALSE;

    if (!gjs_typecheck_object(context, target_obj,
                              G_TYPE_OBJECT, JS_TRUE))
        return JS_FALSE;

    obj = gjs_g_object_from_object(context, target_obj);
    if (obj == NULL)
        return JS_FALSE;

    retval = INT_TO_JSVAL(obj->ref_count);
    JS_SET_RVAL(context, vp, retval);
    return JS_TRUE;
}

static JSBool
gjs_breakpoint(JSContext *context,
               unsigned   argc,
               jsval     *vp)
{
    jsval *argv = JS_ARGV(cx, vp);
    if (!gjs_parse_args(context, "breakpoint", "", argc, argv))
        return JS_FALSE;
    G_BREAKPOINT();
    JS_SET_RVAL(context, vp, JSVAL_VOID);
    return JS_TRUE;
}

static JSBool
gjs_gc(JSContext *context,
       unsigned   argc,
       jsval     *vp)
{
    jsval *argv = JS_ARGV(cx, vp);
    if (!gjs_parse_args(context, "gc", "", argc, argv))
        return JS_FALSE;
    JS_GC(JS_GetRuntime(context));
    JS_SET_RVAL(context, vp, JSVAL_VOID);
    return JS_TRUE;
}

static JSBool
gjs_exit(JSContext *context,
         unsigned   argc,
         jsval     *vp)
{
    jsval *argv = JS_ARGV(cx, vp);
    gint32 ecode;
    if (!gjs_parse_args(context, "exit", "i", argc, argv, "ecode", &ecode))
        return JS_FALSE;
    exit(ecode);
    return JS_TRUE;
}

static JSBool
gjs_clear_date_caches(JSContext *context,
             unsigned   argc,
             jsval     *vp)
{
    JS_BeginRequest(context);

    // Workaround for a bug in SpiderMonkey where tzset is not called before
    // localtime_r, see https://bugzilla.mozilla.org/show_bug.cgi?id=1004706
    tzset();

    JS_ClearDateCaches(context);
    JS_EndRequest(context);

    JS_SET_RVAL(context, vp, JSVAL_VOID);
    return JS_TRUE;
}

static JSFunctionSpec module_funcs[] = {
    { "addressOf", JSOP_WRAPPER (gjs_address_of), 1, GJS_MODULE_PROP_FLAGS },
    { "refcount", JSOP_WRAPPER (gjs_refcount), 1, GJS_MODULE_PROP_FLAGS },
    { "breakpoint", JSOP_WRAPPER (gjs_breakpoint), 0, GJS_MODULE_PROP_FLAGS },
    { "gc", JSOP_WRAPPER (gjs_gc), 0, GJS_MODULE_PROP_FLAGS },
    { "exit", JSOP_WRAPPER (gjs_exit), 0, GJS_MODULE_PROP_FLAGS },
    { "clearDateCaches", JSOP_WRAPPER (gjs_clear_date_caches), 0, GJS_MODULE_PROP_FLAGS },
    { NULL },
};

JSBool
gjs_js_define_system_stuff(JSContext  *context,
                           JSObject  **module_out)
{
    GjsContext *gjs_context;
    char *program_name;
    jsval value;
    JSBool retval;
    JSObject *module;

    module = JS_NewObject (context, NULL, NULL, NULL);

    if (!JS_DefineFunctions(context, module, &module_funcs[0]))
        return JS_FALSE;

    retval = JS_FALSE;

    gjs_context = (GjsContext*) JS_GetContextPrivate(context);
    g_object_get(gjs_context,
                 "program-name", &program_name,
                 NULL);

    if (!gjs_string_from_utf8(context, program_name,
                              -1, &value))
        goto out;

    /* The name is modeled after program_invocation_name,
       part of the glibc */
    if (!JS_DefineProperty(context, module,
                           "programInvocationName",
                           value,
                           JS_PropertyStub,
                           JS_StrictPropertyStub,
                           GJS_MODULE_PROP_FLAGS | JSPROP_READONLY))
        goto out;

    if (!JS_DefineProperty(context, module,
                           "version",
                           INT_TO_JSVAL(GJS_VERSION),
                           JS_PropertyStub,
                           JS_StrictPropertyStub,
                           GJS_MODULE_PROP_FLAGS | JSPROP_READONLY))
        goto out;

    retval = JS_TRUE;

 out:
    g_free(program_name);
    *module_out = module;

    return retval;
}
<|endoftext|>


<commit_before>/*******************************************************************
 KNotes -- Notes for the KDE project

 Copyright (c) 2002, 2003, Michael Brade <brade@kde.org>

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*******************************************************************/

#include <qfile.h>
#include <qfont.h>
#include <qpoint.h>
#include <qcolor.h>
#include <qstringlist.h>
#include <qtextstream.h>

#include <kdebug.h>
#include <kapplication.h>
#include <kglobal.h>
#include <kstandarddirs.h>
#include <kurl.h>
#include <ksimpleconfig.h>
#include <kio/netaccess.h>

#include <unistd.h>

#include "version.h"
#include "knoteslegacy.h"

#include "libkcal/calendarlocal.h"
#include "libkcal/journal.h"

#include <netwm.h>

using namespace KCal;

void KNotesLegacy::cleanUp()
{
    // remove old (KDE 1.x) local config file if it still exists
    QString configfile = KGlobal::dirs()->findResource( "config", "knotesrc" );
    KSimpleConfig *test = new KSimpleConfig( configfile );
    test->setGroup( "General" );
    double version = test->readDoubleNumEntry( "version", 1 );
    if ( version == 1 )
    {
        delete test;
        if ( !( checkAccess( configfile, W_OK ) &&
                KIO::NetAccess::del( KURL(configfile), 0 ) ) )
        {
            kdError(5500) << k_funcinfo << "Could not delete old config file!!" << endl;
            // TODO
        }
    }
    else if ( version < 3 )
    {
        test->writeEntry( "version", KNOTES_VERSION );
        delete test;
    }
}

bool KNotesLegacy::convert( CalendarLocal *calendar )
{
    bool converted = false;

    QDir noteDir( KGlobal::dirs()->saveLocation( "appdata", "notes/" ) );
    QStringList notes = noteDir.entryList( QDir::Files, QDir::Name );
    for ( QStringList::Iterator note = notes.begin(); note != notes.end(); note++ )
    {
        QString file = noteDir.absFilePath( *note );
        KSimpleConfig* test = new KSimpleConfig( file, true );
        test->setGroup( "General" );
        double version = test->readDoubleNumEntry( "version", 1 );
        delete test;

        if ( version < 3.0 )
        {
            // create the new note
            Journal *journal = new Journal();

            if ( version < 2.0 )
                convertKNotes1Config( journal, noteDir, *note );
            else
                convertKNotes2Config( journal, noteDir, *note );

            calendar->addJournal( journal );
            converted = true;
        }
    }

    return converted;
}

void KNotesLegacy::convertKNotes1Config( Journal *journal, QDir& noteDir,
        const QString& file )
{
    QFile infile( noteDir.absFilePath( file ) );

    if ( !infile.open( IO_ReadOnly ) )
    {
        kdError(5500) << k_funcinfo << "Could not open input file: " << infile.name() << endl;

        // TODO: better return false and delete current journal, same in convertKNotes2Config
        return;
    }

    QTextStream input( &infile );

    // set the new configfile's name...
    QString configFile = noteDir.absFilePath( journal->uid() );

    // set the defaults
    KIO::NetAccess::copy(
        KURL( KGlobal::dirs()->findResource( "config", "knotesrc" ) ), KURL( configFile ), 0
    );

    // get the name
    journal->setSummary( input.readLine() );

    // TODO: Needed? What about KConfig? This deletes everything else?
    //       Test with a config file that contains a value not set here!
    KSimpleConfig config( configFile );

    config.setGroup( "General" );
    config.writeEntry( "version", KNOTES_VERSION );

    // use the new default for this group
    config.setGroup( "Actions" );
    config.writeEntry( "mail", "kmail --msg %f" );

    config.setGroup( "Display" );

    // get the geometry
    QString geo = input.readLine();

    int pos, data[13];
    int n = 0;

    while ( (pos = geo.find('+')) != -1 )
    {
        if( n < 13 )
            data[n++] = geo.left(pos).toInt();
        geo.remove( 0, pos + 1 );
    }
    if ( n < 13 )
        data[n++] = geo.toInt();

    config.writeEntry( "width", data[3] );
    config.writeEntry( "height", data[4] );

    // get the background color
    uint red = input.readLine().toUInt();
    uint green = input.readLine().toUInt();
    uint blue = input.readLine().toUInt();
    config.writeEntry( "bgcolor", QColor( red, green, blue ) );

    // get the foreground color
    red = input.readLine().toUInt();
    green = input.readLine().toUInt();
    blue = input.readLine().toUInt();
    config.writeEntry( "fgcolor", QColor( red, green, blue ) );

    config.setGroup( "Editor" );

    // get the font
    QString fontfamily = input.readLine();
    if ( fontfamily.isEmpty() )
        fontfamily = QString( "helvetica" );
    uint size = input.readLine().toUInt();
    size = QMAX( size, 4 );
    uint weight = input.readLine().toUInt();
    bool italic = ( input.readLine().toUInt() == 1 );
    QFont font( fontfamily, size, weight, italic );

    config.writeEntry( "titlefont", font );
    config.writeEntry( "font", font );

    // 3d frame? Not supported yet!
    input.readLine();

    // autoindent
    bool indent = ( input.readLine().toUInt() == 1 );
    config.writeEntry( "autoindent", indent );

    // rich text and tabsize
    config.writeEntry( "richtext", false );
    config.writeEntry( "tabsize", 4 );

    config.setGroup( "WindowDisplay" );

    // hidden
    bool hidden = ( input.readLine().toUInt() == 1 );

    int note_desktop = data[0];
    if ( hidden )
        note_desktop = 0;
    else if ( data[11] == 1 )
        note_desktop = NETWinInfo::OnAllDesktops;

    config.writeEntry( "desktop", note_desktop );

    if ( data[1] >= 0 && data[2] >= 0 )   // just to be sure...
        config.writeEntry( "position", QPoint( data[1], data[2] ) );
    else
        config.writeEntry( "position", QPoint( 10, 10 ) );

    if ( data[12] & 2048 )
        config.writeEntry( "state", NET::SkipTaskbar | NET::StaysOnTop );
    else
        config.writeEntry( "state", NET::SkipTaskbar );

    config.sync();

    // get the text
    QString text;
    while ( !input.atEnd() )
    {
        text.append( input.readLine() );
        if ( !input.atEnd() )
            text.append( '\n' );
    }

    journal->setDescription( text );
    journal->addAttachment( new Attachment( configFile, CONFIG_MIME ) );

    infile.close();
    infile.remove();        // TODO: success?
}

void KNotesLegacy::convertKNotes2Config( Journal *journal, QDir& noteDir,
        const QString& file )
{
    // new name for config file
    noteDir.rename( file, journal->uid() );
    QString configFile = noteDir.absFilePath( journal->uid() );

    // update the config
    KConfig config( configFile );
    config.setGroup( "Data" );
    journal->setSummary( config.readEntry( "name" ) );
    config.deleteEntry( "name" );
    config.deleteGroup( "Data", false );
    config.setGroup( "General" );
    config.writeEntry( "version", KNOTES_VERSION );

    // load the saved text and put it in the journal
    QFile infile( noteDir.absFilePath( "." + file + "_data" ) );
    if ( infile.open( IO_ReadOnly ) )
    {
        QTextStream input( &infile );
        input.setEncoding( QTextStream::UnicodeUTF8 );
        journal->setDescription( input.read() );
        infile.close();
        infile.remove();    // TODO: success?
    }
    else
        kdError(5500) << k_funcinfo << "Could not open input file: " << infile.name() << endl;

    journal->addAttachment( new Attachment( configFile, CONFIG_MIME ) );
}
<commit_msg>Fix potential mem leak<commit_after>/*******************************************************************
 KNotes -- Notes for the KDE project

 Copyright (c) 2002, 2003, Michael Brade <brade@kde.org>

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*******************************************************************/

#include <qfile.h>
#include <qfont.h>
#include <qpoint.h>
#include <qcolor.h>
#include <qstringlist.h>
#include <qtextstream.h>

#include <kdebug.h>
#include <kapplication.h>
#include <kglobal.h>
#include <kstandarddirs.h>
#include <kurl.h>
#include <ksimpleconfig.h>
#include <kio/netaccess.h>

#include <unistd.h>

#include "version.h"
#include "knoteslegacy.h"

#include "libkcal/calendarlocal.h"
#include "libkcal/journal.h"

#include <netwm.h>

using namespace KCal;

void KNotesLegacy::cleanUp()
{
    // remove old (KDE 1.x) local config file if it still exists
    QString configfile = KGlobal::dirs()->findResource( "config", "knotesrc" );
    KSimpleConfig *test = new KSimpleConfig( configfile );
    test->setGroup( "General" );
    double version = test->readDoubleNumEntry( "version", 1 );
    if ( version == 1 )
    {
        delete test;
        if ( !( checkAccess( configfile, W_OK ) &&
                KIO::NetAccess::del( KURL(configfile), 0 ) ) )
        {
            kdError(5500) << k_funcinfo << "Could not delete old config file!!" << endl;
            // TODO
        }
    }
    else if ( version < 3 )
    {
        test->writeEntry( "version", KNOTES_VERSION );
        delete test;
    }
    else
        delete test;
}

bool KNotesLegacy::convert( CalendarLocal *calendar )
{
    bool converted = false;

    QDir noteDir( KGlobal::dirs()->saveLocation( "appdata", "notes/" ) );
    QStringList notes = noteDir.entryList( QDir::Files, QDir::Name );
    for ( QStringList::Iterator note = notes.begin(); note != notes.end(); note++ )
    {
        QString file = noteDir.absFilePath( *note );
        KSimpleConfig* test = new KSimpleConfig( file, true );
        test->setGroup( "General" );
        double version = test->readDoubleNumEntry( "version", 1 );
        delete test;

        if ( version < 3.0 )
        {
            // create the new note
            Journal *journal = new Journal();

            if ( version < 2.0 )
                convertKNotes1Config( journal, noteDir, *note );
            else
                convertKNotes2Config( journal, noteDir, *note );

            calendar->addJournal( journal );
            converted = true;
        }
    }

    return converted;
}

void KNotesLegacy::convertKNotes1Config( Journal *journal, QDir& noteDir,
        const QString& file )
{
    QFile infile( noteDir.absFilePath( file ) );

    if ( !infile.open( IO_ReadOnly ) )
    {
        kdError(5500) << k_funcinfo << "Could not open input file: " << infile.name() << endl;

        // TODO: better return false and delete current journal, same in convertKNotes2Config
        return;
    }

    QTextStream input( &infile );

    // set the new configfile's name...
    QString configFile = noteDir.absFilePath( journal->uid() );

    // set the defaults
    KIO::NetAccess::copy(
        KURL( KGlobal::dirs()->findResource( "config", "knotesrc" ) ), KURL( configFile ), 0
    );

    // get the name
    journal->setSummary( input.readLine() );

    // TODO: Needed? What about KConfig? This deletes everything else?
    //       Test with a config file that contains a value not set here!
    KSimpleConfig config( configFile );

    config.setGroup( "General" );
    config.writeEntry( "version", KNOTES_VERSION );

    // use the new default for this group
    config.setGroup( "Actions" );
    config.writeEntry( "mail", "kmail --msg %f" );

    config.setGroup( "Display" );

    // get the geometry
    QString geo = input.readLine();

    int pos, data[13];
    int n = 0;

    while ( (pos = geo.find('+')) != -1 )
    {
        if( n < 13 )
            data[n++] = geo.left(pos).toInt();
        geo.remove( 0, pos + 1 );
    }
    if ( n < 13 )
        data[n++] = geo.toInt();

    config.writeEntry( "width", data[3] );
    config.writeEntry( "height", data[4] );

    // get the background color
    uint red = input.readLine().toUInt();
    uint green = input.readLine().toUInt();
    uint blue = input.readLine().toUInt();
    config.writeEntry( "bgcolor", QColor( red, green, blue ) );

    // get the foreground color
    red = input.readLine().toUInt();
    green = input.readLine().toUInt();
    blue = input.readLine().toUInt();
    config.writeEntry( "fgcolor", QColor( red, green, blue ) );

    config.setGroup( "Editor" );

    // get the font
    QString fontfamily = input.readLine();
    if ( fontfamily.isEmpty() )
        fontfamily = QString( "helvetica" );
    uint size = input.readLine().toUInt();
    size = QMAX( size, 4 );
    uint weight = input.readLine().toUInt();
    bool italic = ( input.readLine().toUInt() == 1 );
    QFont font( fontfamily, size, weight, italic );

    config.writeEntry( "titlefont", font );
    config.writeEntry( "font", font );

    // 3d frame? Not supported yet!
    input.readLine();

    // autoindent
    bool indent = ( input.readLine().toUInt() == 1 );
    config.writeEntry( "autoindent", indent );

    // rich text and tabsize
    config.writeEntry( "richtext", false );
    config.writeEntry( "tabsize", 4 );

    config.setGroup( "WindowDisplay" );

    // hidden
    bool hidden = ( input.readLine().toUInt() == 1 );

    int note_desktop = data[0];
    if ( hidden )
        note_desktop = 0;
    else if ( data[11] == 1 )
        note_desktop = NETWinInfo::OnAllDesktops;

    config.writeEntry( "desktop", note_desktop );

    if ( data[1] >= 0 && data[2] >= 0 )   // just to be sure...
        config.writeEntry( "position", QPoint( data[1], data[2] ) );
    else
        config.writeEntry( "position", QPoint( 10, 10 ) );

    if ( data[12] & 2048 )
        config.writeEntry( "state", NET::SkipTaskbar | NET::StaysOnTop );
    else
        config.writeEntry( "state", NET::SkipTaskbar );

    config.sync();

    // get the text
    QString text;
    while ( !input.atEnd() )
    {
        text.append( input.readLine() );
        if ( !input.atEnd() )
            text.append( '\n' );
    }

    journal->setDescription( text );
    journal->addAttachment( new Attachment( configFile, CONFIG_MIME ) );

    infile.close();
    infile.remove();        // TODO: success?
}

void KNotesLegacy::convertKNotes2Config( Journal *journal, QDir& noteDir,
        const QString& file )
{
    // new name for config file
    noteDir.rename( file, journal->uid() );
    QString configFile = noteDir.absFilePath( journal->uid() );

    // update the config
    KConfig config( configFile );
    config.setGroup( "Data" );
    journal->setSummary( config.readEntry( "name" ) );
    config.deleteEntry( "name" );
    config.deleteGroup( "Data", false );
    config.setGroup( "General" );
    config.writeEntry( "version", KNOTES_VERSION );

    // load the saved text and put it in the journal
    QFile infile( noteDir.absFilePath( "." + file + "_data" ) );
    if ( infile.open( IO_ReadOnly ) )
    {
        QTextStream input( &infile );
        input.setEncoding( QTextStream::UnicodeUTF8 );
        journal->setDescription( input.read() );
        infile.close();
        infile.remove();    // TODO: success?
    }
    else
        kdError(5500) << k_funcinfo << "Could not open input file: " << infile.name() << endl;

    journal->addAttachment( new Attachment( configFile, CONFIG_MIME ) );
}
<|endoftext|>


<commit_before><commit_msg>Revert "Correct skiping source file line of  msgctxt"<commit_after><|endoftext|>