-rw-r--r-- | config.in | 1 | ||||
-rw-r--r-- | core/launcher/server.cpp | 2 | ||||
-rw-r--r-- | core/symlinker/Makefile | 160 | ||||
-rw-r--r-- | core/symlinker/config.in | 5 | ||||
-rw-r--r-- | core/symlinker/main.cpp | 160 | ||||
-rw-r--r-- | core/symlinker/opie-symlinker.control | 9 | ||||
-rw-r--r-- | core/symlinker/symlinker.pro | 15 | ||||
-rw-r--r-- | packages | 1 |
8 files changed, 352 insertions, 1 deletions
@@ -152,12 +152,13 @@ menu "Base" 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 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 @@ -705,13 +705,13 @@ 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(); } 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 ) + @@ -164,12 +164,13 @@ 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 |