summaryrefslogtreecommitdiff
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--config.in1
-rw-r--r--core/launcher/server.cpp2
-rw-r--r--core/symlinker/Makefile160
-rw-r--r--core/symlinker/config.in5
-rw-r--r--core/symlinker/main.cpp160
-rw-r--r--core/symlinker/opie-symlinker.control9
-rw-r--r--core/symlinker/symlinker.pro15
-rw-r--r--packages1
8 files changed, 352 insertions, 1 deletions
diff --git a/config.in b/config.in
index b57488a..1a5b53b 100644
--- a/config.in
+++ b/config.in
@@ -150,16 +150,17 @@ menu "Base"
source x11/config.in
endchoice
source libopie/config.in
source core/opie-login/config.in
source core/opiealarm/config.in
source core/tools/quicklauncher/config.in
source core/launcher/config.in
source core/qws/config.in
+ source core/symlinker/config.in
endmenu
comment ""
menu "Applets"
source core/applets/config.in
source noncore/applets/config.in
endmenu
diff --git a/core/launcher/server.cpp b/core/launcher/server.cpp
index 634082b..9a86a80 100644
--- a/core/launcher/server.cpp
+++ b/core/launcher/server.cpp
@@ -703,17 +703,17 @@ void Server::applicationTerminated(int pid, const QString &app)
void Server::applicationConnected(const QString &app)
{
serverGui->applicationStateChanged( app, ServerInterface::Running );
}
void Server::storageChanged()
{
- system( "qtopia-update-symlinks" );
+ system( "opie-update-symlinks" );
serverGui->storageChanged( storage->fileSystems() );
docList->storageChanged();
}
void Server::preloadApps()
{
diff --git a/core/symlinker/Makefile b/core/symlinker/Makefile
new file mode 100644
index 0000000..f35292c
--- a/dev/null
+++ b/core/symlinker/Makefile
@@ -0,0 +1,160 @@
+#############################################################################
+# Makefile for building: $(OPIEDIR)/bin/opie-update-symlinks
+# Generated by qmake (1.05a) (Qt 3.1.2) on: Tue Mar 16 10:46:29 2004
+# Project: symlinker.pro
+# Template: app
+# Command: $(QMAKE) -o Makefile symlinker.pro
+#############################################################################
+
+####### Compiler, tools and options
+
+CC = arm-linux-gcc
+CXX = arm-linux-g++ -DQT_QWS_IPAQ
+LEX = flex
+YACC = yacc
+CFLAGS = -pipe $(CFLAGS_EXTRA) -Wall -W $(if $(CFLAGS_RELEASE),$(CFLAGS_RELEASE), -O2) -DUSE_REALTIME_AUDIO_THREAD -DOPIE_NEW_MALLOC -DOPIE_SOUND_FRAGMENT_SHIFT=14 -DOPIE_WE_VERSION=15 -DQT_NO_DEBUG
+CXXFLAGS = -pipe $(CFLAGS_EXTRA) -DQWS -fno-exceptions -fno-rtti $(CXXFLAGS_EXTRA) -Wall -W $(if $(CFLAGS_RELEASE),$(CFLAGS_RELEASE), -O2) -DUSE_REALTIME_AUDIO_THREAD -DOPIE_NEW_MALLOC -DOPIE_SOUND_FRAGMENT_SHIFT=14 -DOPIE_WE_VERSION=15 -DQT_NO_DEBUG
+LEXFLAGS =
+YACCFLAGS= -d
+INCPATH = -I/opt/arm/opie//mkspecs/qws/linux-ipaq-g++ -I. -I$(OPIEDIR)/include -I$(QTDIR)/include -I.moc/$(PLATFORM)/
+LINK = arm-linux-gcc
+LFLAGS = $(LFLAGS_EXTRA) -Wl,-rpath=$(OPIEDIR)/lib
+LIBS = $(SUBLIBS) -Wl,-rpath-link,$(OPIEDIR)/lib -L$(OPIEDIR)/lib -Wl,-rpath-link,$(QTDIR)/lib -L$(QTDIR)/lib $(LIBS_EXTRA) -lqpe -lopie -lqte
+AR = ar cqs
+RANLIB =
+MOC = $(QTDIR)/bin/moc
+UIC = $(QTDIR)/bin/uic
+QMAKE = qmake
+TAR = tar -cf
+GZIP = gzip -9f
+COPY = cp -f
+COPY_FILE= $(COPY) -p
+COPY_DIR = $(COPY) -pR
+DEL_FILE = rm -f
+SYMLINK = ln -sf
+DEL_DIR = rmdir
+MOVE = mv -f
+PRO = symlinker.pro
+CHK_DIR_EXISTS= test -d
+MKDIR = mkdir -p
+
+####### Output directory
+
+OBJECTS_DIR = .obj/$(PLATFORM)/
+
+####### Files
+
+HEADERS =
+SOURCES = main.cpp
+OBJECTS = .obj/$(PLATFORM)/main.o
+FORMS =
+UICDECLS =
+UICIMPLS =
+SRCMOC =
+OBJMOC =
+DIST = ../../gen.pro \
+ ../../include.pro \
+ symlinker.pro
+QMAKE_TARGET = opie-update-symlinks
+DESTDIR = $(OPIEDIR)/bin/
+TARGET = $(OPIEDIR)/bin/opie-update-symlinks
+
+first: all
+####### Implicit rules
+
+.SUFFIXES: .c .cpp .cc .cxx .C
+
+.cpp.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.cc.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.cxx.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.C.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+.c.o:
+ $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
+
+####### Build rules
+
+all: Makefile $(TARGET)
+
+$(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC)
+ test -d $(OPIEDIR)/bin/ || mkdir -p $(OPIEDIR)/bin/
+ $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS)
+
+mocables: $(SRCMOC)
+
+$(MOC):
+ ( cd $(QTDIR)/src/moc ; $(MAKE) )
+
+Makefile: symlinker.pro /opt/arm/opie//mkspecs/qws/linux-ipaq-g++/qmake.conf ../../gen.pro \
+ ../../include.pro
+ $(QMAKE) -o Makefile symlinker.pro
+qmake:
+ @$(QMAKE) -o Makefile symlinker.pro
+
+dist:
+ @mkdir -p .obj/$(PLATFORM)/opie-update-symlinks && $(COPY_FILE) --parents $(SOURCES) $(HEADERS) $(FORMS) $(DIST) .obj/$(PLATFORM)/opie-update-symlinks/ && ( cd `dirname .obj/$(PLATFORM)/opie-update-symlinks` && $(TAR) opie-update-symlinks.tar opie-update-symlinks && $(GZIP) opie-update-symlinks.tar ) && $(MOVE) `dirname .obj/$(PLATFORM)/opie-update-symlinks`/opie-update-symlinks.tar.gz . && $(DEL_FILE) -r .obj/$(PLATFORM)/opie-update-symlinks
+
+mocclean:
+
+uiclean:
+
+yaccclean:
+lexclean:
+clean:
+ -$(DEL_FILE) $(OBJECTS)
+ -$(DEL_FILE) *~ core *.core
+
+
+####### Sub-libraries
+
+distclean: clean
+ -$(DEL_FILE) $(OPIEDIR)/bin/$(TARGET) $(TARGET)
+
+
+lupdate:
+ lupdate -noobsolete $(PRO)
+
+lrelease:
+ lrelease $(PRO)
+
+ipk:
+ tmp=`mktemp -d /tmp/ipkg-opie.XXXXXXXXXX` && ( $(MAKE) INSTALL_ROOT="" install && ipkg-build ; rm -rf ; )
+
+opie-lupdate:
+ opie-lupdate $(PRO)
+
+opie-lrelease:
+ opie-lrelease $(PRO)
+
+messages:
+ xgettext -C -n -ktr -kQT_TRANSLATE_NOOP main.cpp -o '$(OPIEDIR)/messages-$(QMAKE_TARGET)-tr.po' && xgettext -C -n -a main.cpp -o '$(OPIEDIR)/messages-$(QMAKE_TARGET)-allstrings.po'
+
+FORCE:
+
+####### Compile
+
+.obj/$(PLATFORM)/main.o: main.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .obj/$(PLATFORM)/main.o main.cpp
+
+####### Install
+
+install_target:
+ @$(CHK_DIR_EXISTS) "$(INSTALL_ROOT)$(OPIEDIR)/bin/" || $(MKDIR) "$(INSTALL_ROOT)$(OPIEDIR)/bin/"
+ -$(COPY) "$(OPIEDIR)/bin/$(QMAKE_TARGET)" "$(INSTALL_ROOT)$(OPIEDIR)/bin/$(QMAKE_TARGET)"
+
+uninstall_target:
+ -$(DEL_FILE) "$(INSTALL_ROOT)$(OPIEDIR)/bin/$(QMAKE_TARGET)"
+ -$(DEL_DIR) "$(INSTALL_ROOT)$(OPIEDIR)/bin/"
+
+
+install: all install_target
+
+uninstall: uninstall_target
+
diff --git a/core/symlinker/config.in b/core/symlinker/config.in
new file mode 100644
index 0000000..a378d3a
--- a/dev/null
+++ b/core/symlinker/config.in
@@ -0,0 +1,5 @@
+ config SYMLINKER
+ boolean "Opie Symlinker for external media"
+ default "y"
+ depends ( LIBQPE || LIBQPE-X11 ) && LIBOPIE && LAUNCHER
+
diff --git a/core/symlinker/main.cpp b/core/symlinker/main.cpp
new file mode 100644
index 0000000..73d5166
--- a/dev/null
+++ b/core/symlinker/main.cpp
@@ -0,0 +1,160 @@
+#include <qapplication.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qdir.h>
+#include <qtextstream.h>
+#include <qstringlist.h>
+
+#include <stdlib.h>
+#include <unistd.h> //symlink()
+#include <sys/stat.h> // mkdir()
+
+#include <sys/vfs.h>
+#include <mntent.h>
+
+static const char *listDir = "/usr/lib/ipkg/externinfo/";
+
+static void createSymlinks( const QString &location, const QString &package )
+{
+ QFile inFile( location + "/usr/lib/ipkg/info/" + package + ".list" );
+ mkdir( "/usr/lib/ipkg", 0777 );
+ mkdir( listDir, 0777 );
+
+ QFile outFile( listDir + package + ".list");
+
+ //qDebug( "createSymlinks %s -> %s", inFile.name().ascii(), outFile.name().ascii() );
+
+
+
+ if ( inFile.open(IO_ReadOnly) && outFile.open(IO_WriteOnly)) {
+ QTextStream in(&inFile);
+ QTextStream out(&outFile);
+
+ QString s;
+ while ( !in.eof() ) { // until end of file...
+ s = in.readLine(); // line of text excluding '\n'
+ //qDebug( "Read: %s", s.ascii() );
+ // for s, do link/mkdir.
+ if ( s.right(1) == "/" ) {
+ //qDebug("do mkdir for %s", s.ascii());
+ mkdir( s.ascii(), 0777 );
+ //possible optimization: symlink directories
+ //that don't exist already. -- Risky.
+ } else {
+ //qDebug("do symlink for %s", s.ascii());
+ QFileInfo ffi( s );
+ //Don't try to symlink if a regular file exists already
+ if ( !ffi.exists() || ffi.isSymLink() ) {
+ symlink( (location+s).ascii(), s.ascii() );
+// qDebug ( "Created %s" ,s.ascii() );
+ out << s << "\n";
+ } //else {
+ // qDebug( "%s exists already, not symlinked", s.ascii() );
+// }
+ }
+ }
+ inFile.close();
+ outFile.close();
+ }
+}
+
+
+
+static void removeSymlinks( const QString &package )
+{
+ QFile inFile( listDir + package + ".list" );
+
+ if ( inFile.open(IO_ReadOnly) ) {
+ QTextStream in(&inFile);
+
+ QString s;
+ while ( !in.eof() ) { // until end of file...
+ s = in.readLine(); // line of text excluding '\n'
+ //qDebug("remove symlink %s", s.ascii());
+ QFileInfo ffi( s );
+ //Confirm that it's still a symlink.
+ if ( ffi.isSymLink() )
+ unlink( s.ascii() );
+// qDebug ( "Removed %s", s.ascii() );
+// else
+// qDebug( "Not removed %s", s.ascii() );
+ }
+ inFile.close();
+ inFile.remove();
+ }
+}
+
+
+
+/*
+ Slightly hacky: we can't use StorageInfo, since we don't have a
+ QApplication. We look for filesystems that have the directory
+ /usr/lib/ipkg/info, and assume that they are removable media
+ with packages installed. This is safe even if eg. /usr is on a
+ separate filesystem, since then we would be testing for
+ /usr/usr/lib/ipkg/info, which should not exist. (And if it
+ does they deserve to have it treated as removable.)
+ */
+
+static void updateSymlinks()
+{
+ QDir lists( listDir );
+ QStringList knownPackages = lists.entryList( "*.list" ); // No tr
+
+ struct mntent *me;
+ FILE *mntfp = setmntent( "/etc/mtab", "r" );
+
+ if ( mntfp ) {
+ while ( (me = getmntent( mntfp )) != 0 ) {
+ QString root = me->mnt_dir;
+ if ( root == "/" )
+ continue;
+
+ QString info = root + "/usr/lib/ipkg/info";
+ QDir infoDir( info );
+ //qDebug( "looking at %s", info.ascii() );
+ if ( infoDir.isReadable() ) {
+ const QFileInfoList *packages = infoDir.entryInfoList( "*.list" ); // No tr
+ QFileInfoListIterator it( *packages );
+ QFileInfo *fi;
+ while (( fi = *it )) {
+ ++it;
+ if ( knownPackages.contains( fi->fileName() ) ) {
+ //qDebug( "found %s and we've seen it before", fi->fileName().latin1() );
+ knownPackages.remove( fi->fileName() );
+ } else {
+ //it's a new one
+ createSymlinks( root, fi->baseName() );
+ }
+
+ }
+
+ }
+ }
+ endmntent( mntfp );
+ }
+
+ for ( QStringList::Iterator it = knownPackages.begin();
+ it != knownPackages.end(); ++it ) {
+ // strip ".info" off the end.
+ removeSymlinks( (*it).left((*it).length()-5) );
+ }
+}
+
+
+
+int main( int argc, char *argv[] )
+{
+ QApplication a( argc, argv, QApplication::Tty );
+
+ QString command = argc > 1 ? argv[1] : "update"; // No tr
+
+ if ( command == "update" ) // No tr
+ updateSymlinks();
+ else if ( command == "create" && argc > 3 ) // No tr
+ createSymlinks( argv[2], argv[3] );
+ else if ( command == "remove" && argc > 2 ) // No tr
+ removeSymlinks( argv[2] );
+ else
+ qWarning( "Argument error" );
+}
diff --git a/core/symlinker/opie-symlinker.control b/core/symlinker/opie-symlinker.control
new file mode 100644
index 0000000..6378653
--- a/dev/null
+++ b/core/symlinker/opie-symlinker.control
@@ -0,0 +1,9 @@
+Package: opie-symlinker
+Files: bin/opie-update-symlinks
+Priority: optional
+Section: opie/system
+Maintainer: Project Opie <opie@handhelds.org>
+Architecture: arm
+Version: $QPE_VERSION-$SUB_VERSION.3
+Depends: task-opie-minimal
+Description: Enables apps on external media
diff --git a/core/symlinker/symlinker.pro b/core/symlinker/symlinker.pro
new file mode 100644
index 0000000..9558b3e
--- a/dev/null
+++ b/core/symlinker/symlinker.pro
@@ -0,0 +1,15 @@
+TEMPLATE = app
+CONFIG += qtopia warn_on release
+DESTDIR = $(OPIEDIR)/bin
+
+HEADERS =
+SOURCES = main.cpp
+INTERFACES =
+
+TARGET = opie-update-symlinks
+INCLUDEPATH += $(OPIEDIR)/include
+DEPENDPATH += $(OPIEDIR)/include .
+LIBS += -lqpe -lopie
+
+include ( $(OPIEDIR)/include.pro )
+
diff --git a/packages b/packages
index 8f4f731..9e5406e 100644
--- a/packages
+++ b/packages
@@ -162,16 +162,17 @@ CONFIG_SIMPLE_MAIN examples/simple-main example.pro
CONFIG_SIMPLE noncore/tools/calc2/simple simple.pro
CONFIG_SIMPLE_PIM examples/simple-pim example.pro
CONFIG_SINGLE single single.pro
CONFIG_SNAKE noncore/games/snake snake.pro
CONFIG_SOLITAIRE noncore/games/solitaire solitaire.pro
CONFIG_SOUND noncore/settings/sound sound.pro
CONFIG_SSHKEYS noncore/settings/sshkeys sshkeys.pro
CONFIG_SUSPENDAPPLET core/applets/suspendapplet suspendapplet.pro
+CONFIG_SYMLINKER core/symlinker symlinker.pro
CONFIG_SYSINFO noncore/settings/sysinfo sysinfo.pro
CONFIG_TABLEVIEWER noncore/apps/tableviewer tableviewer.pro
CONFIG_TABMANAGER noncore/settings/tabmanager tabmanager.pro
CONFIG_TABOAPP core/apps/taboapp taboapp.pro
CONFIG_TEST libsql/test test.pro
CONFIG_TEST noncore/apps/opie-console/test test.pro
CONFIG_TETRIX noncore/games/tetrix tetrix.pro
CONFIG_TEXTEDIT core/apps/textedit textedit.pro